Repository: cassandra-rs/cassandra-rs (language: rust)

Issue:
Allow PreparedStatement to be used across threads
`PreparedStatement` implements neither `Sync` nor `Clone`, which makes it impossible to use single prepared statement across multiple threads with the following error:
```
`*const cassandra_cpp_sys::cassandra::CassPrepared_` cannot be shared between threads safely
...
note: required because it appears within the type `cassandra_cpp::PreparedStatement`
```

From [datastax docs](http://datastax.github.io/cpp-driver/api/struct.CassPrepared/):
> A prepared statement is read-only and it is thread-safe to concurrently bind new statements.

which makes me think that `PreparedStatement` not implementing `Sync` is just a mistake.

If I'm wrong, could you please provide an example of how `PreparedStatement`s are expected to be used?


Discussion / hints:
The Rust code contains the following comment on `PreparedStatement`:
```rust
// The underlying C type has no thread-local state, but does not support access
// from multiple threads: https://datastax.github.io/cpp-driver/topics/#thread-safety
```
Accordingly, it implements `Send` but not `Sync`.

That means you can get what you want by wrapping it in a `Mutex` - the mutex will ensure it's only ever used by one thread at a time.

HTH.
I believe that the "Thread safety" docs section only refers to concepts mentioned in the "Getting started" page. Shouldn't [API docs](http://datastax.github.io/cpp-driver/api/struct.CassPrepared/) be given preference in case of contradiction like this?
I don't see a reason why read-only access from multiple threads has to be synchronized. It seems like a performance issue if all `bind` calls have to be made under a global lock.

Could you please consider revisiting this issue?
You're right, the API doc you've linked is more specific than the general one the original author linked in the comment. Thanks for pointing that out.

It's hard to imagine this being a performance issue - the act of binding doesn't take very long at all. But I'm now happy to accept a PR fixing this. Thanks!

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f420bbb..3e796a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ version number is tracked in the file `VERSION`.
 ### Added
 - Conversion functions between `uuid::Uuid` and this library's `Uuid`.
 ### Changed
+- `PreparedStatement` is now considered `Sync`, and can be shared across threads.
 ### Fixed
 
 ## [0.15.0] - 2020-01-28
diff --git a/src/cassandra/prepared.rs b/src/cassandra/prepared.rs
index 14a19e9..1ce2b22 100644
--- a/src/cassandra/prepared.rs
+++ b/src/cassandra/prepared.rs
@@ -17,9 +17,8 @@ use std::{mem, slice, str};
 #[derive(Debug)]
 pub struct PreparedStatement(*const _PreparedStatement);
 
-// The underlying C type has no thread-local state, but does not support access
-// from multiple threads: https://datastax.github.io/cpp-driver/topics/#thread-safety
 unsafe impl Send for PreparedStatement {}
+unsafe impl Sync for PreparedStatement {}
 
 impl Drop for PreparedStatement {
     /// Frees a prepared statement


Test patch: