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: 68 68 100.0 %
Date: 2020-02-19 22:14:06 Branches: 2 4 50.0 %

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
18
using ConditionVariable = ConditionVariableBase<LibuvMutexTraits>;
19
using Mutex = MutexBase<LibuvMutexTraits>;
20
21
template <typename T, typename MutexT = Mutex>
22
3973
class ExclusiveAccess {
23
 public:
24
  ExclusiveAccess() = default;
25
26
  template <typename... Args>
27
4378
  explicit ExclusiveAccess(Args&&... args)
28
4378
      : item_(std::forward<Args>(args)...) {}
29
30
  ExclusiveAccess(const ExclusiveAccess&) = delete;
31
  ExclusiveAccess& operator=(const ExclusiveAccess&) = delete;
32
33
260
  class Scoped {
34
   public:
35
    // ExclusiveAccess will commonly be used in conjuction with std::shared_ptr
36
    // and without this constructor it's too easy to forget to keep a reference
37
    // around to the shared_ptr while operating on the ExclusiveAccess object.
38
260
    explicit Scoped(const std::shared_ptr<ExclusiveAccess>& shared)
39
        : shared_(shared)
40
260
        , scoped_lock_(shared->mutex_)
41
520
        , pointer_(&shared->item_) {}
42
43
    explicit Scoped(ExclusiveAccess* exclusive_access)
44
        : shared_()
45
        , scoped_lock_(exclusive_access->mutex_)
46
        , pointer_(&exclusive_access->item_) {}
47
48
    T& operator*() const { return *pointer_; }
49
345
    T* operator->() const { return pointer_; }
50
51
    Scoped(const Scoped&) = delete;
52
    Scoped& operator=(const Scoped&) = delete;
53
54
   private:
55
    std::shared_ptr<ExclusiveAccess> shared_;
56
    typename MutexT::ScopedLock scoped_lock_;
57
    T* const pointer_;
58
  };
59
60
 private:
61
  friend class ScopedLock;
62
  MutexT mutex_;
63
  T item_;
64
};
65
66
template <typename Traits>
67
class MutexBase {
68
 public:
69
  inline MutexBase();
70
  inline ~MutexBase();
71
  inline void Lock();
72
  inline void Unlock();
73
74
  MutexBase(const MutexBase&) = delete;
75
  MutexBase& operator=(const MutexBase&) = delete;
76
77
  class ScopedLock;
78
  class ScopedUnlock;
79
80
  class ScopedLock {
81
   public:
82
    inline explicit ScopedLock(const MutexBase& mutex);
83
    inline explicit ScopedLock(const ScopedUnlock& scoped_unlock);
84
    inline ~ScopedLock();
85
86
    ScopedLock(const ScopedLock&) = delete;
87
    ScopedLock& operator=(const ScopedLock&) = delete;
88
89
   private:
90
    template <typename> friend class ConditionVariableBase;
91
    friend class ScopedUnlock;
92
    const MutexBase& mutex_;
93
  };
94
95
  class ScopedUnlock {
96
   public:
97
    inline explicit ScopedUnlock(const ScopedLock& scoped_lock);
98
    inline ~ScopedUnlock();
99
100
    ScopedUnlock(const ScopedUnlock&) = delete;
101
    ScopedUnlock& operator=(const ScopedUnlock&) = delete;
102
103
   private:
104
    friend class ScopedLock;
105
    const MutexBase& mutex_;
106
  };
107
108
 private:
109
  template <typename> friend class ConditionVariableBase;
110
  mutable typename Traits::MutexT mutex_;
111
};
112
113
template <typename Traits>
114
class ConditionVariableBase {
115
 public:
116
  using ScopedLock = typename MutexBase<Traits>::ScopedLock;
117
118
  inline ConditionVariableBase();
119
  inline ~ConditionVariableBase();
120
  inline void Broadcast(const ScopedLock&);
121
  inline void Signal(const ScopedLock&);
122
  inline void Wait(const ScopedLock& scoped_lock);
123
124
  ConditionVariableBase(const ConditionVariableBase&) = delete;
125
  ConditionVariableBase& operator=(const ConditionVariableBase&) = delete;
126
127
 private:
128
  typename Traits::CondT cond_;
129
};
130
131
struct LibuvMutexTraits {
132
  using CondT = uv_cond_t;
133
  using MutexT = uv_mutex_t;
134
135
47077
  static inline int cond_init(CondT* cond) {
136
47077
    return uv_cond_init(cond);
137
  }
138
139
218111
  static inline int mutex_init(MutexT* mutex) {
140
218111
    return uv_mutex_init(mutex);
141
  }
142
143
88259
  static inline void cond_broadcast(CondT* cond) {
144
88259
    uv_cond_broadcast(cond);
145
88259
  }
146
147
30117
  static inline void cond_destroy(CondT* cond) {
148
30117
    uv_cond_destroy(cond);
149
30118
  }
150
151
162815
  static inline void cond_signal(CondT* cond) {
152
162815
    uv_cond_signal(cond);
153
162815
  }
154
155
150745
  static inline void cond_wait(CondT* cond, MutexT* mutex) {
156
150745
    uv_cond_wait(cond, mutex);
157
150810
  }
158
159
207720
  static inline void mutex_destroy(MutexT* mutex) {
160
207720
    uv_mutex_destroy(mutex);
161
207722
  }
162
163
18980609
  static inline void mutex_lock(MutexT* mutex) {
164
18980609
    uv_mutex_lock(mutex);
165
18982494
  }
166
167
18981863
  static inline void mutex_unlock(MutexT* mutex) {
168
18981863
    uv_mutex_unlock(mutex);
169
18981879
  }
170
};
171
172
template <typename Traits>
173
47077
ConditionVariableBase<Traits>::ConditionVariableBase() {
174
47077
  CHECK_EQ(0, Traits::cond_init(&cond_));
175
47077
}
176
177
template <typename Traits>
178
30115
ConditionVariableBase<Traits>::~ConditionVariableBase() {
179
30115
  Traits::cond_destroy(&cond_);
180
30119
}
181
182
template <typename Traits>
183
88259
void ConditionVariableBase<Traits>::Broadcast(const ScopedLock&) {
184
88259
  Traits::cond_broadcast(&cond_);
185
88259
}
186
187
template <typename Traits>
188
162815
void ConditionVariableBase<Traits>::Signal(const ScopedLock&) {
189
162815
  Traits::cond_signal(&cond_);
190
162815
}
191
192
template <typename Traits>
193
150752
void ConditionVariableBase<Traits>::Wait(const ScopedLock& scoped_lock) {
194
150752
  Traits::cond_wait(&cond_, &scoped_lock.mutex_.mutex_);
195
150810
}
196
197
template <typename Traits>
198
218097
MutexBase<Traits>::MutexBase() {
199
218097
  CHECK_EQ(0, Traits::mutex_init(&mutex_));
200
218003
}
201
202
template <typename Traits>
203
207727
MutexBase<Traits>::~MutexBase() {
204
207727
  Traits::mutex_destroy(&mutex_);
205
207729
}
206
207
template <typename Traits>
208
void MutexBase<Traits>::Lock() {
209
  Traits::mutex_lock(&mutex_);
210
}
211
212
template <typename Traits>
213
void MutexBase<Traits>::Unlock() {
214
  Traits::mutex_unlock(&mutex_);
215
}
216
217
template <typename Traits>
218
18980596
MutexBase<Traits>::ScopedLock::ScopedLock(const MutexBase& mutex)
219
18980596
    : mutex_(mutex) {
220
18980596
  Traits::mutex_lock(&mutex_.mutex_);
221
18982318
}
222
223
template <typename Traits>
224
MutexBase<Traits>::ScopedLock::ScopedLock(const ScopedUnlock& scoped_unlock)
225
    : MutexBase(scoped_unlock.mutex_) {}
226
227
template <typename Traits>
228
18981680
MutexBase<Traits>::ScopedLock::~ScopedLock() {
229
18981680
  Traits::mutex_unlock(&mutex_.mutex_);
230
18981510
}
231
232
template <typename Traits>
233
138
MutexBase<Traits>::ScopedUnlock::ScopedUnlock(const ScopedLock& scoped_lock)
234
138
    : mutex_(scoped_lock.mutex_) {
235
138
  Traits::mutex_unlock(&mutex_.mutex_);
236
138
}
237
238
template <typename Traits>
239
138
MutexBase<Traits>::ScopedUnlock::~ScopedUnlock() {
240
138
  Traits::mutex_lock(&mutex_.mutex_);
241
138
}
242
243
}  // namespace node
244
245
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
246
247
#endif  // SRC_NODE_MUTEX_H_