This is an experiment to see how much of sync and send from Rust/Swift can be implemented in C++ and what problems arise when we try to do so. Is there anything we can learn about thread safety from these approaches.
- The main sync/send concepts are in sync_send.h
- They are used in safe_thread.h
- They are tested in tests
- It's possible to implement a very restrictive sync/send type trait
- It's more restrictive that could be due to C++ aliasing rules. I.e. there's no way to ensure a const& doesn't have non-const references elsewhere. This is where borrow checking really outshines C++
- It's only possible to get surface level (i.e. one level deep) by directly checking the arguments. Other languages check this recursively. It is hoped this might become more feasible with reflection in C++
- Template errors can be difficult to navigate
- Just having to think about the types passed to scl types (e.g. safe_thread) can help the user think in a more thread-safe way
- Clang 18
- GCC 14.2
- AppleClang 16
-
scl::thread
- A safe thread that encapsulates running a thread and checks arguments to that thread conform to the send trait -
scl::async
- Similar toscl::thread
but aroundstd::async
-
scl::synchronized_value
- A wrapper around a mutex and an object to provide safe concurrent access to it, conforms to thesync
trait - Reflection based implementation that checks
sync
recursively
-
check_state
andscoped_check
to manually check for data-races on function calls -
data_race_registry
to avoid having to use acheck_state
member
-
data_race_checked
- Checks for data races during every function call -
mutex
- Locks access during every function call, conforms tosync
-
shared_mutex
- Locks shared access during every const function call, unique access otherwise, conforms tosync
-
cow
copy-on-write -
arc
automatic-reference-counting -
actor
actor implementation using senders