#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 // std::shared_ptr #include // std::forward namespace node { // Copy-on-write utility. Not threadsafe, i.e. there is no synchronization // of the copy operation with other operations. template class CopyOnWrite final { public: template explicit CopyOnWrite(Args&&... args) : data_(std::make_shared(std::forward(args)...)) {} CopyOnWrite(const CopyOnWrite& other) = default; CopyOnWrite& operator=(const CopyOnWrite& other) = default; CopyOnWrite(CopyOnWrite&& other) = default; CopyOnWrite& operator=(CopyOnWrite&& 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 data_; }; // Threadsafe copy-on-write utility. Consumers need to use the Read and // Write helpers to access the target data structure. template 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 ThreadsafeCopyOnWrite(Args&&... args) : impl_(T(std::forward(args)...)) {} ThreadsafeCopyOnWrite(const ThreadsafeCopyOnWrite& other) = default; ThreadsafeCopyOnWrite& operator=(const ThreadsafeCopyOnWrite& other) = default; ThreadsafeCopyOnWrite(ThreadsafeCopyOnWrite&& other) = default; ThreadsafeCopyOnWrite& operator=(ThreadsafeCopyOnWrite&& other) = default; class Read { public: explicit Read(const ThreadsafeCopyOnWrite* cow); const T& operator*() const; const T* operator->() const; private: const ThreadsafeCopyOnWrite* cow_; RwLock::ScopedReadLock lock_; }; class Write { public: explicit Write(ThreadsafeCopyOnWrite* cow); T& operator*(); T* operator->(); private: ThreadsafeCopyOnWrite* cow_; typename ThreadsafeCopyOnWrite::Impl* impl_; RwLock::ScopedLock lock_; }; Read read() const { return Read(this); } Write write() { return Write(this); } private: CopyOnWrite impl_; }; } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_THREADSAFE_COW_H_