Skip to content

Commit a2da9e2

Browse files
addaleaxdanielleadams
authored andcommitted
worker: use rwlock for sibling group
Since it is much more common to send messages than to add or remove ports from a sibling group, using a rwlock is appropriate here. Refs: #38780 (comment) PR-URL: #38783 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
1 parent 3e6b3b2 commit a2da9e2

File tree

3 files changed

+81
-5
lines changed

3 files changed

+81
-5
lines changed

src/node_messaging.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -1331,7 +1331,7 @@ Maybe<bool> SiblingGroup::Dispatch(
13311331
std::shared_ptr<Message> message,
13321332
std::string* error) {
13331333

1334-
Mutex::ScopedLock lock(group_mutex_);
1334+
RwLock::ScopedReadLock lock(group_mutex_);
13351335

13361336
// The source MessagePortData is not part of this group.
13371337
if (ports_.find(source) == ports_.end()) {
@@ -1376,7 +1376,7 @@ void SiblingGroup::Entangle(MessagePortData* port) {
13761376
}
13771377

13781378
void SiblingGroup::Entangle(std::initializer_list<MessagePortData*> ports) {
1379-
Mutex::ScopedLock lock(group_mutex_);
1379+
RwLock::ScopedWriteLock lock(group_mutex_);
13801380
for (MessagePortData* data : ports) {
13811381
ports_.insert(data);
13821382
CHECK(!data->group_);
@@ -1386,7 +1386,7 @@ void SiblingGroup::Entangle(std::initializer_list<MessagePortData*> ports) {
13861386

13871387
void SiblingGroup::Disentangle(MessagePortData* data) {
13881388
auto self = shared_from_this(); // Keep alive until end of function.
1389-
Mutex::ScopedLock lock(group_mutex_);
1389+
RwLock::ScopedWriteLock lock(group_mutex_);
13901390
ports_.erase(data);
13911391
data->group_.reset();
13921392

src/node_messaging.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@ class SiblingGroup final : public std::enable_shared_from_this<SiblingGroup> {
150150
size_t size() const { return ports_.size(); }
151151

152152
private:
153-
std::string name_;
153+
const std::string name_;
154+
RwLock group_mutex_; // Protects ports_.
154155
std::set<MessagePortData*> ports_;
155-
Mutex group_mutex_;
156156

157157
static void CheckSiblingGroup(const std::string& name);
158158

src/node_mutex.h

+76
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ namespace node {
1414
template <typename Traits> class ConditionVariableBase;
1515
template <typename Traits> class MutexBase;
1616
struct LibuvMutexTraits;
17+
struct LibuvRwlockTraits;
1718

1819
using ConditionVariable = ConditionVariableBase<LibuvMutexTraits>;
1920
using Mutex = MutexBase<LibuvMutexTraits>;
21+
using RwLock = MutexBase<LibuvRwlockTraits>;
2022

2123
template <typename T, typename MutexT = Mutex>
2224
class ExclusiveAccess {
@@ -70,6 +72,8 @@ class MutexBase {
7072
inline ~MutexBase();
7173
inline void Lock();
7274
inline void Unlock();
75+
inline void RdLock();
76+
inline void RdUnlock();
7377

7478
MutexBase(const MutexBase&) = delete;
7579
MutexBase& operator=(const MutexBase&) = delete;
@@ -92,6 +96,21 @@ class MutexBase {
9296
const MutexBase& mutex_;
9397
};
9498

99+
class ScopedReadLock {
100+
public:
101+
inline explicit ScopedReadLock(const MutexBase& mutex);
102+
inline ~ScopedReadLock();
103+
104+
ScopedReadLock(const ScopedReadLock&) = delete;
105+
ScopedReadLock& operator=(const ScopedReadLock&) = delete;
106+
107+
private:
108+
template <typename> friend class ConditionVariableBase;
109+
const MutexBase& mutex_;
110+
};
111+
112+
using ScopedWriteLock = ScopedLock;
113+
95114
class ScopedUnlock {
96115
public:
97116
inline explicit ScopedUnlock(const ScopedLock& scoped_lock);
@@ -167,6 +186,42 @@ struct LibuvMutexTraits {
167186
static inline void mutex_unlock(MutexT* mutex) {
168187
uv_mutex_unlock(mutex);
169188
}
189+
190+
static inline void mutex_rdlock(MutexT* mutex) {
191+
uv_mutex_lock(mutex);
192+
}
193+
194+
static inline void mutex_rdunlock(MutexT* mutex) {
195+
uv_mutex_unlock(mutex);
196+
}
197+
};
198+
199+
struct LibuvRwlockTraits {
200+
using MutexT = uv_rwlock_t;
201+
202+
static inline int mutex_init(MutexT* mutex) {
203+
return uv_rwlock_init(mutex);
204+
}
205+
206+
static inline void mutex_destroy(MutexT* mutex) {
207+
uv_rwlock_destroy(mutex);
208+
}
209+
210+
static inline void mutex_lock(MutexT* mutex) {
211+
uv_rwlock_wrlock(mutex);
212+
}
213+
214+
static inline void mutex_unlock(MutexT* mutex) {
215+
uv_rwlock_wrunlock(mutex);
216+
}
217+
218+
static inline void mutex_rdlock(MutexT* mutex) {
219+
uv_rwlock_rdlock(mutex);
220+
}
221+
222+
static inline void mutex_rdunlock(MutexT* mutex) {
223+
uv_rwlock_rdunlock(mutex);
224+
}
170225
};
171226

172227
template <typename Traits>
@@ -214,6 +269,16 @@ void MutexBase<Traits>::Unlock() {
214269
Traits::mutex_unlock(&mutex_);
215270
}
216271

272+
template <typename Traits>
273+
void MutexBase<Traits>::RdLock() {
274+
Traits::mutex_rdlock(&mutex_);
275+
}
276+
277+
template <typename Traits>
278+
void MutexBase<Traits>::RdUnlock() {
279+
Traits::mutex_rdunlock(&mutex_);
280+
}
281+
217282
template <typename Traits>
218283
MutexBase<Traits>::ScopedLock::ScopedLock(const MutexBase& mutex)
219284
: mutex_(mutex) {
@@ -229,6 +294,17 @@ MutexBase<Traits>::ScopedLock::~ScopedLock() {
229294
Traits::mutex_unlock(&mutex_.mutex_);
230295
}
231296

297+
template <typename Traits>
298+
MutexBase<Traits>::ScopedReadLock::ScopedReadLock(const MutexBase& mutex)
299+
: mutex_(mutex) {
300+
Traits::mutex_rdlock(&mutex_.mutex_);
301+
}
302+
303+
template <typename Traits>
304+
MutexBase<Traits>::ScopedReadLock::~ScopedReadLock() {
305+
Traits::mutex_rdunlock(&mutex_.mutex_);
306+
}
307+
232308
template <typename Traits>
233309
MutexBase<Traits>::ScopedUnlock::ScopedUnlock(const ScopedLock& scoped_lock)
234310
: mutex_(scoped_lock.mutex_) {

0 commit comments

Comments
 (0)