#ifndef SRC_NODE_THREADSAFE_COW_H_ #define SRC_NODE_THREADSAFE_COW_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "util.h" #include "uv.h" #include <memory> // std::shared_ptr<T> #include <utility> // std::forward<T> namespace node { // Copy-on-write utility. Not threadsafe, i.e. there is no synchronization // of the copy operation with other operations. template <typename T> class CopyOnWrite final { public: template <typename... Args> explicit CopyOnWrite(Args&&... args) : data_(std::make_shared<T>(std::forward<Args>(args)...)) {} CopyOnWrite(const CopyOnWrite<T>& other) = default; CopyOnWrite& operator=(const CopyOnWrite<T>& other) = default; CopyOnWrite(CopyOnWrite<T>&& other) = default; CopyOnWrite& operator=(CopyOnWrite<T>&& other) = default; const T* read() const { return data_.get(); } T* write(); const T& operator*() const { return *read(); } const T* operator->() const { return read(); } private: std::shared_ptr<T> data_; }; // Threadsafe copy-on-write utility. Consumers need to use the Read and // Write helpers to access the target data structure. template <typename T> class ThreadsafeCopyOnWrite final { private: // Define this early since some of the public members depend on it // and some compilers need it to be defined first in that case. struct Impl { explicit Impl(const T& data) : data(data) {} explicit Impl(T&& data) : data(std::move(data)) {} Impl(const Impl& other); Impl& operator=(const Impl& other) = delete; Impl(Impl&& other) = delete; Impl& operator=(Impl&& other) = delete; RwLock mutex; T data; }; public: template <typename... Args> ThreadsafeCopyOnWrite(Args&&... args) : impl_(T(std::forward<Args>(args)...)) {} ThreadsafeCopyOnWrite(const ThreadsafeCopyOnWrite<T>& other) = default; ThreadsafeCopyOnWrite& operator=(const ThreadsafeCopyOnWrite<T>& other) = default; ThreadsafeCopyOnWrite(ThreadsafeCopyOnWrite<T>&& other) = default; ThreadsafeCopyOnWrite& operator=(ThreadsafeCopyOnWrite<T>&& other) = default; class Read { public: explicit Read(const ThreadsafeCopyOnWrite<T>* cow); const T& operator*() const; const T* operator->() const; private: const ThreadsafeCopyOnWrite<T>* cow_; RwLock::ScopedReadLock lock_; }; class Write { public: explicit Write(ThreadsafeCopyOnWrite<T>* cow); T& operator*(); T* operator->(); private: ThreadsafeCopyOnWrite<T>* cow_; typename ThreadsafeCopyOnWrite<T>::Impl* impl_; RwLock::ScopedLock lock_; }; Read read() const { return Read(this); } Write write() { return Write(this); } private: CopyOnWrite<Impl> impl_; }; } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_THREADSAFE_COW_H_