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‎

Lines changed: 3 additions & 3 deletions
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::ScopedLocklock(group_mutex_);
1334+
RwLock::ScopedReadLocklock(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
voidSiblingGroup::Entangle(std::initializer_list<MessagePortData*> ports){
1379-
Mutex::ScopedLocklock(group_mutex_);
1379+
RwLock::ScopedWriteLocklock(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
voidSiblingGroup::Disentangle(MessagePortData* data){
13881388
auto self = shared_from_this(); // Keep alive until end of function.
1389-
Mutex::ScopedLocklock(group_mutex_);
1389+
RwLock::ScopedWriteLocklock(group_mutex_);
13901390
ports_.erase(data);
13911391
data->group_.reset();
13921392

‎src/node_messaging.h‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@ class SiblingGroup final : public std::enable_shared_from_this<SiblingGroup>{
150150
size_tsize() 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
staticvoidCheckSiblingGroup(const std::string& name);
158158

‎src/node_mutex.h‎

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ namespace node{
1414
template <typename Traits> classConditionVariableBase;
1515
template <typename Traits> classMutexBase;
1616
structLibuvMutexTraits;
17+
structLibuvRwlockTraits;
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
classExclusiveAccess{
@@ -70,6 +72,8 @@ class MutexBase{
7072
inline~MutexBase();
7173
inlinevoidLock();
7274
inlinevoidUnlock();
75+
inlinevoidRdLock();
76+
inlinevoidRdUnlock();
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+
classScopedReadLock{
100+
public:
101+
inlineexplicitScopedReadLock(const MutexBase& mutex);
102+
inline~ScopedReadLock();
103+
104+
ScopedReadLock(const ScopedReadLock&) = delete;
105+
ScopedReadLock& operator=(const ScopedReadLock&) = delete;
106+
107+
private:
108+
template <typename> friendclassConditionVariableBase;
109+
const MutexBase& mutex_;
110+
};
111+
112+
using ScopedWriteLock = ScopedLock;
113+
95114
classScopedUnlock{
96115
public:
97116
inlineexplicitScopedUnlock(const ScopedLock& scoped_lock);
@@ -167,6 +186,42 @@ struct LibuvMutexTraits{
167186
staticinlinevoidmutex_unlock(MutexT* mutex){
168187
uv_mutex_unlock(mutex);
169188
}
189+
190+
staticinlinevoidmutex_rdlock(MutexT* mutex){
191+
uv_mutex_lock(mutex);
192+
}
193+
194+
staticinlinevoidmutex_rdunlock(MutexT* mutex){
195+
uv_mutex_unlock(mutex);
196+
}
197+
};
198+
199+
structLibuvRwlockTraits{
200+
using MutexT = uv_rwlock_t;
201+
202+
staticinlineintmutex_init(MutexT* mutex){
203+
returnuv_rwlock_init(mutex);
204+
}
205+
206+
staticinlinevoidmutex_destroy(MutexT* mutex){
207+
uv_rwlock_destroy(mutex);
208+
}
209+
210+
staticinlinevoidmutex_lock(MutexT* mutex){
211+
uv_rwlock_wrlock(mutex);
212+
}
213+
214+
staticinlinevoidmutex_unlock(MutexT* mutex){
215+
uv_rwlock_wrunlock(mutex);
216+
}
217+
218+
staticinlinevoidmutex_rdlock(MutexT* mutex){
219+
uv_rwlock_rdlock(mutex);
220+
}
221+
222+
staticinlinevoidmutex_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)