/src/node/src/node_locks.h
Line | Count | Source |
1 | | #ifndef SRC_NODE_LOCKS_H_ |
2 | | #define SRC_NODE_LOCKS_H_ |
3 | | |
4 | | #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
5 | | |
6 | | #include <deque> |
7 | | #include <string> |
8 | | #include <unordered_map> |
9 | | #include <unordered_set> |
10 | | |
11 | | #include "base_object.h" |
12 | | #include "env.h" |
13 | | #include "node_mutex.h" |
14 | | #include "v8.h" |
15 | | |
16 | | namespace node::worker::locks { |
17 | | |
18 | | class Lock final : public MemoryRetainer { |
19 | | public: |
20 | | enum class Mode { Shared, Exclusive }; |
21 | | |
22 | | Lock(Environment* env, |
23 | | const std::u16string& name, |
24 | | Mode mode, |
25 | | const std::string& client_id, |
26 | | v8::Local<v8::Promise::Resolver> waiting, |
27 | | v8::Local<v8::Promise::Resolver> released); |
28 | 0 | ~Lock() = default; |
29 | | |
30 | | Lock(const Lock&) = delete; |
31 | | Lock& operator=(const Lock&) = delete; |
32 | | |
33 | | // Resource name for this lock as DOMString |
34 | 0 | const std::u16string& name() const { return name_; } |
35 | | // Lock mode (shared or exclusive). |
36 | 0 | Mode mode() const { return mode_; } |
37 | | // Client identifier string. |
38 | 0 | const std::string& client_id() const { return client_id_; } |
39 | | // Environment that owns this lock. |
40 | 0 | Environment* env() const { return env_; } |
41 | | |
42 | | // Returns true if this lock was stolen by another request. |
43 | 0 | bool is_stolen() const { return stolen_; } |
44 | | // Marks this lock as stolen. |
45 | 0 | void mark_stolen() { stolen_ = true; } |
46 | | |
47 | | // Promise that resolves when the user callback completes. |
48 | 0 | v8::Local<v8::Promise::Resolver> waiting_promise() { |
49 | 0 | return waiting_promise_.Get(env_->isolate()); |
50 | 0 | } |
51 | | // Promise that resolves when the lock is finally released. |
52 | 0 | v8::Local<v8::Promise::Resolver> released_promise() { |
53 | 0 | return released_promise_.Get(env_->isolate()); |
54 | 0 | } |
55 | | |
56 | | void MemoryInfo(node::MemoryTracker* tracker) const override; |
57 | | SET_MEMORY_INFO_NAME(Lock) |
58 | | SET_SELF_SIZE(Lock) |
59 | | |
60 | | private: |
61 | | Environment* env_; |
62 | | std::u16string name_; |
63 | | Mode mode_; |
64 | | std::string client_id_; |
65 | | bool stolen_ = false; |
66 | | v8::Global<v8::Promise::Resolver> waiting_promise_; |
67 | | v8::Global<v8::Promise::Resolver> released_promise_; |
68 | | }; |
69 | | |
70 | | class LockHolder final : public BaseObject { |
71 | | public: |
72 | | LockHolder(Environment* env, |
73 | | v8::Local<v8::Object> obj, |
74 | | std::shared_ptr<Lock> lock) |
75 | 0 | : BaseObject(env, obj), lock_(std::move(lock)) { |
76 | 0 | MakeWeak(); |
77 | 0 | } |
78 | | |
79 | 0 | ~LockHolder() = default; |
80 | | |
81 | | LockHolder(const LockHolder&) = delete; |
82 | | LockHolder& operator=(const LockHolder&) = delete; |
83 | | |
84 | 0 | std::shared_ptr<Lock> lock() const { return lock_; } |
85 | | |
86 | | void MemoryInfo(node::MemoryTracker* tracker) const override; |
87 | | SET_MEMORY_INFO_NAME(LockHolder) |
88 | | SET_SELF_SIZE(LockHolder) |
89 | | |
90 | | static BaseObjectPtr<LockHolder> Create(Environment* env, |
91 | | std::shared_ptr<Lock> lock); |
92 | | |
93 | | private: |
94 | | static v8::Local<v8::FunctionTemplate> GetConstructorTemplate( |
95 | | Environment* env); |
96 | | |
97 | | std::shared_ptr<Lock> lock_; |
98 | | }; |
99 | | |
100 | | class LockRequest final { |
101 | | public: |
102 | | LockRequest(Environment* env, |
103 | | v8::Local<v8::Promise::Resolver> waiting, |
104 | | v8::Local<v8::Promise::Resolver> released, |
105 | | v8::Local<v8::Function> callback, |
106 | | const std::u16string& name, |
107 | | Lock::Mode mode, |
108 | | std::string client_id, |
109 | | bool steal, |
110 | | bool if_available); |
111 | 0 | ~LockRequest() = default; |
112 | | |
113 | | LockRequest(const LockRequest&) = delete; |
114 | | LockRequest& operator=(const LockRequest&) = delete; |
115 | | |
116 | 0 | const std::u16string& name() const { return name_; } |
117 | 0 | Lock::Mode mode() const { return mode_; } |
118 | 0 | const std::string& client_id() const { return client_id_; } |
119 | 0 | bool steal() const { return steal_; } |
120 | | // Returns true if this is an ifAvailable request. |
121 | 0 | bool if_available() const { return if_available_; } |
122 | 0 | Environment* env() const { return env_; } |
123 | | |
124 | 0 | v8::Local<v8::Promise::Resolver> waiting_promise() { |
125 | 0 | return waiting_promise_.Get(env_->isolate()); |
126 | 0 | } |
127 | 0 | v8::Local<v8::Promise::Resolver> released_promise() { |
128 | 0 | return released_promise_.Get(env_->isolate()); |
129 | 0 | } |
130 | 0 | v8::Local<v8::Function> callback() { return callback_.Get(env_->isolate()); } |
131 | | |
132 | | private: |
133 | | Environment* env_; |
134 | | std::u16string name_; |
135 | | Lock::Mode mode_; |
136 | | std::string client_id_; |
137 | | bool steal_; |
138 | | bool if_available_; |
139 | | v8::Global<v8::Promise::Resolver> waiting_promise_; |
140 | | v8::Global<v8::Promise::Resolver> released_promise_; |
141 | | v8::Global<v8::Function> callback_; |
142 | | }; |
143 | | |
144 | | class LockManager final { |
145 | | public: |
146 | | static void Request(const v8::FunctionCallbackInfo<v8::Value>& args); |
147 | | static void Query(const v8::FunctionCallbackInfo<v8::Value>& args); |
148 | | |
149 | | void ProcessQueue(Environment* env); |
150 | | void CleanupEnvironment(Environment* env); |
151 | | |
152 | | static void OnEnvironmentCleanup(void* arg); |
153 | 0 | static LockManager* GetCurrent() { return ¤t_; } |
154 | | void ReleaseLockAndProcessQueue(Environment* env, |
155 | | std::shared_ptr<Lock> lock, |
156 | | v8::Local<v8::Value> result, |
157 | | bool was_rejected = false); |
158 | | |
159 | | private: |
160 | 72 | LockManager() = default; |
161 | 0 | ~LockManager() = default; |
162 | | |
163 | | LockManager(const LockManager&) = delete; |
164 | | LockManager& operator=(const LockManager&) = delete; |
165 | | |
166 | | bool IsGrantable(const LockRequest* req) const; |
167 | | void CleanupStolenLocks(Environment* env); |
168 | | void ReleaseLock(Lock* lock); |
169 | | void WakeEnvironment(Environment* env); |
170 | | |
171 | | static LockManager current_; |
172 | | |
173 | | mutable Mutex mutex_; |
174 | | // All entries for a given Environment* are purged in CleanupEnvironment(). |
175 | | std::unordered_map<std::u16string, std::deque<std::shared_ptr<Lock>>> |
176 | | held_locks_; |
177 | | std::deque<std::unique_ptr<LockRequest>> pending_queue_; |
178 | | std::unordered_set<Environment*> registered_envs_; |
179 | | }; |
180 | | |
181 | | } // namespace node::worker::locks |
182 | | |
183 | | #endif // NODE_WANT_INTERNALS |
184 | | #endif // SRC_NODE_LOCKS_H_ |