From 9e75179e771fa08a74503eb34593df8ecb496d70 Mon Sep 17 00:00:00 2001 From: rnarubin Date: Sat, 7 Sep 2019 05:59:55 -0700 Subject: [PATCH] Implement Send and Sync for useful types (#318) The Send and Sync traits aren't auto-implemented on the many types which wrap a raw pointer to some RocksDB struct. Most of these types are nevertheless safe to use in Send and Sync context, so they should be marked as such --- src/db.rs | 12 ++++++++++-- src/db_options.rs | 10 ++++++++++ src/lib.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/db.rs b/src/db.rs index 96a3f9a..9af7e72 100644 --- a/src/db.rs +++ b/src/db.rs @@ -199,8 +199,6 @@ pub struct DBIterator<'a> { just_seeked: bool, } -unsafe impl<'a> Send for DBIterator<'a> {} - pub enum Direction { Forward, Reverse, @@ -1854,6 +1852,16 @@ impl Default for ReadOptions { } } +// Safety note: auto-implementing Send on most db-related types is prevented by the inner FFI +// pointer. In most cases, however, this pointer is Send-safe because it is never aliased and +// rocksdb internally does not rely on thread-local information for its user-exposed types. +unsafe impl<'a> Send for DBRawIterator<'a> {} +unsafe impl Send for ReadOptions {} + +// Sync is similarly safe for many types because they do not expose interior mutability, and their +// use within the rocksdb library is generally behind a const reference +unsafe impl Sync for ReadOptions {} + /// Vector of bytes stored in the database. /// /// This is a `C` allocated byte array and a length value. diff --git a/src/db_options.rs b/src/db_options.rs index 43c7092..0baca2e 100644 --- a/src/db_options.rs +++ b/src/db_options.rs @@ -34,7 +34,17 @@ pub fn new_cache(capacity: size_t) -> *mut ffi::rocksdb_cache_t { unsafe { ffi::rocksdb_cache_create_lru(capacity) } } +// Safety note: auto-implementing Send on most db-related types is prevented by the inner FFI +// pointer. In most cases, however, this pointer is Send-safe because it is never aliased and +// rocksdb internally does not rely on thread-local information for its user-exposed types. unsafe impl Send for Options {} +unsafe impl Send for WriteOptions {} +unsafe impl Send for BlockBasedOptions {} +// Sync is similarly safe for many types because they do not expose interior mutability, and their +// use within the rocksdb library is generally behind a const reference +unsafe impl Sync for Options {} +unsafe impl Sync for WriteOptions {} +unsafe impl Sync for BlockBasedOptions {} impl Drop for Options { fn drop(&mut self) { diff --git a/src/lib.rs b/src/lib.rs index e6fbd99..67e6bb9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -290,3 +290,49 @@ pub struct ColumnFamily<'a> { } unsafe impl<'a> Send for ColumnFamily<'a> {} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn is_send() { + // test (at compile time) that certain types implement the auto-trait Send, either directly for + // pointer-wrapping types or transitively for types with all Send fields + + fn is_send() { + // dummy function just used for its parameterized type bound + } + + is_send::(); + is_send::>(); + is_send::>(); + is_send::(); + is_send::(); + is_send::(); + is_send::(); + is_send::(); + is_send::(); + is_send::(); + is_send::(); + } + + #[test] + fn is_sync() { + // test (at compile time) that certain types implement the auto-trait Sync + + fn is_sync() { + // dummy function just used for its parameterized type bound + } + + is_sync::(); + is_sync::(); + is_sync::(); + is_sync::(); + is_sync::(); + is_sync::(); + is_sync::(); + is_sync::(); + } + +}