/src/node/src/node_threadsafe_cow.h
Line | Count | Source |
1 | | #ifndef SRC_NODE_THREADSAFE_COW_H_ |
2 | | #define SRC_NODE_THREADSAFE_COW_H_ |
3 | | |
4 | | #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
5 | | |
6 | | #include "util.h" |
7 | | #include "uv.h" |
8 | | |
9 | | #include <memory> // std::shared_ptr<T> |
10 | | #include <utility> // std::forward<T> |
11 | | |
12 | | namespace node { |
13 | | |
14 | | // Copy-on-write utility. Not threadsafe, i.e. there is no synchronization |
15 | | // of the copy operation with other operations. |
16 | | template <typename T> |
17 | | class CopyOnWrite final { |
18 | | public: |
19 | | template <typename... Args> |
20 | | explicit CopyOnWrite(Args&&... args) |
21 | 142 | : data_(std::make_shared<T>(std::forward<Args>(args)...)) {} |
22 | | |
23 | | CopyOnWrite(const CopyOnWrite<T>& other) = default; |
24 | 70 | CopyOnWrite& operator=(const CopyOnWrite<T>& other) = default; |
25 | | CopyOnWrite(CopyOnWrite<T>&& other) = default; |
26 | | CopyOnWrite& operator=(CopyOnWrite<T>&& other) = default; |
27 | | |
28 | 7.73k | const T* read() const { return data_.get(); } |
29 | | T* write(); |
30 | | |
31 | | const T& operator*() const { return *read(); } |
32 | 7.73k | const T* operator->() const { return read(); } |
33 | | |
34 | | private: |
35 | | std::shared_ptr<T> data_; |
36 | | }; |
37 | | |
38 | | // Threadsafe copy-on-write utility. Consumers need to use the Read and |
39 | | // Write helpers to access the target data structure. |
40 | | template <typename T> |
41 | | class ThreadsafeCopyOnWrite final { |
42 | | private: |
43 | | // Define this early since some of the public members depend on it |
44 | | // and some compilers need it to be defined first in that case. |
45 | | struct Impl { |
46 | | explicit Impl(const T& data) : data(data) {} |
47 | 142 | explicit Impl(T&& data) : data(std::move(data)) {} |
48 | | |
49 | | Impl(const Impl& other); |
50 | | Impl& operator=(const Impl& other) = delete; |
51 | | Impl(Impl&& other) = delete; |
52 | | Impl& operator=(Impl&& other) = delete; |
53 | | |
54 | | RwLock mutex; |
55 | | T data; |
56 | | }; |
57 | | |
58 | | public: |
59 | | template <typename... Args> |
60 | | ThreadsafeCopyOnWrite(Args&&... args) |
61 | 142 | : impl_(T(std::forward<Args>(args)...)) {}node::ThreadsafeCopyOnWrite<std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, node::builtins::BuiltinSource, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::builtins::BuiltinSource> > > >::ThreadsafeCopyOnWrite<>() Line | Count | Source | 61 | 70 | : impl_(T(std::forward<Args>(args)...)) {} |
node::ThreadsafeCopyOnWrite<std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, node::builtins::BuiltinSource, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::builtins::BuiltinSource> > > >::ThreadsafeCopyOnWrite<std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, node::builtins::BuiltinSource, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::builtins::BuiltinSource> > > >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, node::builtins::BuiltinSource, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::builtins::BuiltinSource> > >&&) Line | Count | Source | 61 | 72 | : impl_(T(std::forward<Args>(args)...)) {} |
|
62 | | |
63 | | ThreadsafeCopyOnWrite(const ThreadsafeCopyOnWrite<T>& other) = default; |
64 | | ThreadsafeCopyOnWrite& operator=(const ThreadsafeCopyOnWrite<T>& other) = |
65 | 70 | default; |
66 | | ThreadsafeCopyOnWrite(ThreadsafeCopyOnWrite<T>&& other) = default; |
67 | | ThreadsafeCopyOnWrite& operator=(ThreadsafeCopyOnWrite<T>&& other) = default; |
68 | | |
69 | | class Read { |
70 | | public: |
71 | | explicit Read(const ThreadsafeCopyOnWrite<T>* cow); |
72 | | |
73 | | const T& operator*() const; |
74 | | const T* operator->() const; |
75 | | |
76 | | private: |
77 | | const ThreadsafeCopyOnWrite<T>* cow_; |
78 | | RwLock::ScopedReadLock lock_; |
79 | | }; |
80 | | |
81 | | class Write { |
82 | | public: |
83 | | explicit Write(ThreadsafeCopyOnWrite<T>* cow); |
84 | | |
85 | | T& operator*(); |
86 | | T* operator->(); |
87 | | |
88 | | private: |
89 | | ThreadsafeCopyOnWrite<T>* cow_; |
90 | | typename ThreadsafeCopyOnWrite<T>::Impl* impl_; |
91 | | RwLock::ScopedLock lock_; |
92 | | }; |
93 | | |
94 | 2.59k | Read read() const { return Read(this); } |
95 | 0 | Write write() { return Write(this); } |
96 | | |
97 | | private: |
98 | | CopyOnWrite<Impl> impl_; |
99 | | }; |
100 | | |
101 | | } // namespace node |
102 | | |
103 | | #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
104 | | |
105 | | #endif // SRC_NODE_THREADSAFE_COW_H_ |