GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_mutex.h Lines: 92 92 100.0 %
Date: 2021-06-10 04:11:54 Branches: 2 6 33.3 %

Line Branch Exec Source
1
#ifndef SRC_NODE_MUTEX_H_
2
#define SRC_NODE_MUTEX_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
template <typename Traits> class ConditionVariableBase;
15
template <typename Traits> class MutexBase;
16
struct LibuvMutexTraits;
17
struct LibuvRwlockTraits;
18
19
using ConditionVariable = ConditionVariableBase<LibuvMutexTraits>;
20
using Mutex = MutexBase<LibuvMutexTraits>;
21
using RwLock = MutexBase<LibuvRwlockTraits>;
22
23
template <typename T, typename MutexT = Mutex>
24
4741
class ExclusiveAccess {
25
 public:
26
  ExclusiveAccess() = default;
27
28
  template <typename... Args>
29
5214
  explicit ExclusiveAccess(Args&&... args)
30
5214
      : item_(std::forward<Args>(args)...) {}
31
32
  ExclusiveAccess(const ExclusiveAccess&) = delete;
33
  ExclusiveAccess& operator=(const ExclusiveAccess&) = delete;
34
35
302
  class Scoped {
36
   public:
37
    // ExclusiveAccess will commonly be used in conjunction with std::shared_ptr
38
    // and without this constructor it's too easy to forget to keep a reference
39
    // around to the shared_ptr while operating on the ExclusiveAccess object.
40
302
    explicit Scoped(const std::shared_ptr<ExclusiveAccess>& shared)
41
        : shared_(shared)
42
302
        , scoped_lock_(shared->mutex_)
43
604
        , pointer_(&shared->item_) {}
44
45
    explicit Scoped(ExclusiveAccess* exclusive_access)
46
        : shared_()
47
        , scoped_lock_(exclusive_access->mutex_)
48
        , pointer_(&exclusive_access->item_) {}
49
50
    T& operator*() const { return *pointer_; }
51
385
    T* operator->() const { return pointer_; }
52
53
    Scoped(const Scoped&) = delete;
54
    Scoped& operator=(const Scoped&) = delete;
55
56
   private:
57
    std::shared_ptr<ExclusiveAccess> shared_;
58
    typename MutexT::ScopedLock scoped_lock_;
59
    T* const pointer_;
60
  };
61
62
 private:
63
  friend class ScopedLock;
64
  MutexT mutex_;
65
  T item_;
66
};
67
68
template <typename Traits>
69
class MutexBase {
70
 public:
71
  inline MutexBase();
72
  inline ~MutexBase();
73
  inline void Lock();
74
  inline void Unlock();
75
  inline void RdLock();
76
  inline void RdUnlock();
77
78
  MutexBase(const MutexBase&) = delete;
79
  MutexBase& operator=(const MutexBase&) = delete;
80
81
  class ScopedLock;
82
  class ScopedUnlock;
83
84
  class ScopedLock {
85
   public:
86
    inline explicit ScopedLock(const MutexBase& mutex);
87
    inline explicit ScopedLock(const ScopedUnlock& scoped_unlock);
88
    inline ~ScopedLock();
89
90
    ScopedLock(const ScopedLock&) = delete;
91
    ScopedLock& operator=(const ScopedLock&) = delete;
92
93
   private:
94
    template <typename> friend class ConditionVariableBase;
95
    friend class ScopedUnlock;
96
    const MutexBase& mutex_;
97
  };
98
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
114
  class ScopedUnlock {
115
   public:
116
    inline explicit ScopedUnlock(const ScopedLock& scoped_lock);
117
    inline ~ScopedUnlock();
118
119
    ScopedUnlock(const ScopedUnlock&) = delete;
120
    ScopedUnlock& operator=(const ScopedUnlock&) = delete;
121
122
   private:
123
    friend class ScopedLock;
124
    const MutexBase& mutex_;
125
  };
126
127
 private:
128
  template <typename> friend class ConditionVariableBase;
129
  mutable typename Traits::MutexT mutex_;
130
};
131
132
template <typename Traits>
133
class ConditionVariableBase {
134
 public:
135
  using ScopedLock = typename MutexBase<Traits>::ScopedLock;
136
137
  inline ConditionVariableBase();
138
  inline ~ConditionVariableBase();
139
  inline void Broadcast(const ScopedLock&);
140
  inline void Signal(const ScopedLock&);
141
  inline void Wait(const ScopedLock& scoped_lock);
142
143
  ConditionVariableBase(const ConditionVariableBase&) = delete;
144
  ConditionVariableBase& operator=(const ConditionVariableBase&) = delete;
145
146
 private:
147
  typename Traits::CondT cond_;
148
};
149
150
struct LibuvMutexTraits {
151
  using CondT = uv_cond_t;
152
  using MutexT = uv_mutex_t;
153
154
55227
  static inline int cond_init(CondT* cond) {
155
55227
    return uv_cond_init(cond);
156
  }
157
158
168108
  static inline int mutex_init(MutexT* mutex) {
159
168108
    return uv_mutex_init(mutex);
160
  }
161
162
49153
  static inline void cond_broadcast(CondT* cond) {
163
49153
    uv_cond_broadcast(cond);
164
49153
  }
165
166
35612
  static inline void cond_destroy(CondT* cond) {
167
35612
    uv_cond_destroy(cond);
168
35612
  }
169
170
166825
  static inline void cond_signal(CondT* cond) {
171
166825
    uv_cond_signal(cond);
172
166825
  }
173
174
123916
  static inline void cond_wait(CondT* cond, MutexT* mutex) {
175
123916
    uv_cond_wait(cond, mutex);
176
124116
  }
177
178
155877
  static inline void mutex_destroy(MutexT* mutex) {
179
155877
    uv_mutex_destroy(mutex);
180
155873
  }
181
182
16789202
  static inline void mutex_lock(MutexT* mutex) {
183
16789202
    uv_mutex_lock(mutex);
184
16792235
  }
185
186
16791556
  static inline void mutex_unlock(MutexT* mutex) {
187
16791556
    uv_mutex_unlock(mutex);
188
16792166
  }
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
11416
  static inline int mutex_init(MutexT* mutex) {
203
11416
    return uv_rwlock_init(mutex);
204
  }
205
206
11392
  static inline void mutex_destroy(MutexT* mutex) {
207
11392
    uv_rwlock_destroy(mutex);
208
11392
  }
209
210
34244
  static inline void mutex_lock(MutexT* mutex) {
211
34244
    uv_rwlock_wrlock(mutex);
212
34246
  }
213
214
34245
  static inline void mutex_unlock(MutexT* mutex) {
215
34245
    uv_rwlock_wrunlock(mutex);
216
34245
  }
217
218
49211
  static inline void mutex_rdlock(MutexT* mutex) {
219
49211
    uv_rwlock_rdlock(mutex);
220
49224
  }
221
222
49220
  static inline void mutex_rdunlock(MutexT* mutex) {
223
49220
    uv_rwlock_rdunlock(mutex);
224
49222
  }
225
};
226
227
template <typename Traits>
228
55227
ConditionVariableBase<Traits>::ConditionVariableBase() {
229
55227
  CHECK_EQ(0, Traits::cond_init(&cond_));
230
55227
}
231
232
template <typename Traits>
233
35612
ConditionVariableBase<Traits>::~ConditionVariableBase() {
234
35612
  Traits::cond_destroy(&cond_);
235
35612
}
236
237
template <typename Traits>
238
49153
void ConditionVariableBase<Traits>::Broadcast(const ScopedLock&) {
239
49153
  Traits::cond_broadcast(&cond_);
240
49153
}
241
242
template <typename Traits>
243
166825
void ConditionVariableBase<Traits>::Signal(const ScopedLock&) {
244
166825
  Traits::cond_signal(&cond_);
245
166825
}
246
247
template <typename Traits>
248
123918
void ConditionVariableBase<Traits>::Wait(const ScopedLock& scoped_lock) {
249
123918
  Traits::cond_wait(&cond_, &scoped_lock.mutex_.mutex_);
250
124116
}
251
252
template <typename Traits>
253
179524
MutexBase<Traits>::MutexBase() {
254

179524
  CHECK_EQ(0, Traits::mutex_init(&mutex_));
255
179524
}
256
257
template <typename Traits>
258
167268
MutexBase<Traits>::~MutexBase() {
259
167268
  Traits::mutex_destroy(&mutex_);
260
167266
}
261
262
template <typename Traits>
263
void MutexBase<Traits>::Lock() {
264
  Traits::mutex_lock(&mutex_);
265
}
266
267
template <typename Traits>
268
void MutexBase<Traits>::Unlock() {
269
  Traits::mutex_unlock(&mutex_);
270
}
271
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
282
template <typename Traits>
283
16823377
MutexBase<Traits>::ScopedLock::ScopedLock(const MutexBase& mutex)
284
16823377
    : mutex_(mutex) {
285
16823377
  Traits::mutex_lock(&mutex_.mutex_);
286
16826079
}
287
288
template <typename Traits>
289
MutexBase<Traits>::ScopedLock::ScopedLock(const ScopedUnlock& scoped_unlock)
290
    : MutexBase(scoped_unlock.mutex_) {}
291
292
template <typename Traits>
293
16825662
MutexBase<Traits>::ScopedLock::~ScopedLock() {
294
16825662
  Traits::mutex_unlock(&mutex_.mutex_);
295
16825970
}
296
297
template <typename Traits>
298
49212
MutexBase<Traits>::ScopedReadLock::ScopedReadLock(const MutexBase& mutex)
299
49212
    : mutex_(mutex) {
300
49212
  Traits::mutex_rdlock(&mutex_.mutex_);
301
49216
}
302
303
template <typename Traits>
304
49220
MutexBase<Traits>::ScopedReadLock::~ScopedReadLock() {
305
49220
  Traits::mutex_rdunlock(&mutex_.mutex_);
306
49218
}
307
308
template <typename Traits>
309
149
MutexBase<Traits>::ScopedUnlock::ScopedUnlock(const ScopedLock& scoped_lock)
310
149
    : mutex_(scoped_lock.mutex_) {
311
149
  Traits::mutex_unlock(&mutex_.mutex_);
312
149
}
313
314
template <typename Traits>
315
149
MutexBase<Traits>::ScopedUnlock::~ScopedUnlock() {
316
149
  Traits::mutex_lock(&mutex_.mutex_);
317
149
}
318
319
}  // namespace node
320
321
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
322
323
#endif  // SRC_NODE_MUTEX_H_