|
So ARC is something like the following? template <typename T>
struct Locker {
using M = std::shared_mutex;
struct Locked {
Locked(mtx, value) : m_lock(mtx), m_value(value) {}
// operator->, operator*, get, etc.
private:
std::lock_guard<M> m_lock;
std::shared_ptr<T> m_value;
};
struct Shared {
Shared(mtx, value) : m_lock(mtx), m_value(value) {}
// operator->, operator*, get, etc.
private:
std::shared_lock<M> m_lock;
std::shared_ptr<const T> m_value;
};
Shared shared() { return Shared{m_mutex, m_value}; }
Locked locked() { return Locked{m_mutex, m_value}; }
// a nice forwarding ctor that prevents null m_value
private:
std::shared_ptr<T> m_value;
M m_mutex;
};
|
Rust `Arc` = C++ `std::shared_ptr`
Rust `Rc` = C++ `std::shared_ptr` but using a simple integer instead of an atomic so it is not thread safe
`Arc` and `Rc` do not allow you to mutate their contents directly so instead you should use "interior mutability" using something like a `Mutex` (thread-safe) or `RefCell` (not thread-safe), which have runtime checks to ensure no undefined behaviour is introduced. So `Arc<Mutex<T>>` makes it possible to mutate `T`, but `Arc<T>` cannot. Some types like atomics do not require mutability at all, so an `Arc<AtomicBool>` can be mutated directly.
An example of a big C++ codebase using something similar is Chromium, where `std::shared_ptr` is forbidden and `base::RefCounted` (Rust `Rc`) and `base::RefCountedThreadSafe` (Rust `Arc`) should be used instead. WebKit does this too.