GRPC Core  18.0.0
sync.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2019 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPC_CORE_LIB_GPRPP_SYNC_H
20 #define GRPC_CORE_LIB_GPRPP_SYNC_H
21 
23 
24 #include <grpc/impl/codegen/log.h>
25 #include <grpc/impl/codegen/sync.h>
26 #include <grpc/support/sync.h>
27 #include <grpc/support/time.h>
28 
29 #include "absl/synchronization/mutex.h"
31 
32 // The core library is not accessible in C++ codegen headers, and vice versa.
33 // Thus, we need to have duplicate headers with similar functionality.
34 // Make sure any change to this file is also reflected in
35 // include/grpcpp/impl/codegen/sync.h.
36 //
37 // Whenever possible, prefer using this file over <grpcpp/impl/codegen/sync.h>
38 // since this file doesn't rely on g_core_codegen_interface and hence does not
39 // pay the costs of virtual function calls.
40 
41 namespace grpc_core {
42 
43 #ifdef GPR_ABSEIL_SYNC
44 
45 using Mutex = absl::Mutex;
46 using MutexLock = absl::MutexLock;
47 using ReleasableMutexLock = absl::ReleasableMutexLock;
48 using CondVar = absl::CondVar;
49 
50 // Returns the underlying gpr_mu from Mutex. This should be used only when
51 // it has to like passing the C++ mutex to C-core API.
52 // TODO(veblush): Remove this after C-core no longer uses gpr_mu.
53 inline gpr_mu* GetUnderlyingGprMu(Mutex* mutex) {
54  return reinterpret_cast<gpr_mu*>(mutex);
55 }
56 
57 #else
58 
59 class ABSL_LOCKABLE Mutex {
60  public:
61  Mutex() { gpr_mu_init(&mu_); }
62  ~Mutex() { gpr_mu_destroy(&mu_); }
63 
64  Mutex(const Mutex&) = delete;
65  Mutex& operator=(const Mutex&) = delete;
66 
67  void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { gpr_mu_lock(&mu_); }
68  void Unlock() ABSL_UNLOCK_FUNCTION() { gpr_mu_unlock(&mu_); }
69  bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
70  return gpr_mu_trylock(&mu_) != 0;
71  }
72 
73  private:
74  gpr_mu mu_;
75 
76  friend class CondVar;
77  friend gpr_mu* GetUnderlyingGprMu(Mutex* mutex);
78 };
79 
80 // Returns the underlying gpr_mu from Mutex. This should be used only when
81 // it has to like passing the C++ mutex to C-core API.
82 // TODO(veblush): Remove this after C-core no longer uses gpr_mu.
83 inline gpr_mu* GetUnderlyingGprMu(Mutex* mutex) { return &mutex->mu_; }
84 
85 class ABSL_SCOPED_LOCKABLE MutexLock {
86  public:
87  explicit MutexLock(Mutex* mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
88  mu_->Lock();
89  }
90  ~MutexLock() ABSL_UNLOCK_FUNCTION() { mu_->Unlock(); }
91 
92  MutexLock(const MutexLock&) = delete;
93  MutexLock& operator=(const MutexLock&) = delete;
94 
95  private:
96  Mutex* const mu_;
97 };
98 
99 class ABSL_SCOPED_LOCKABLE ReleasableMutexLock {
100  public:
101  explicit ReleasableMutexLock(Mutex* mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
102  : mu_(mu) {
103  mu_->Lock();
104  }
105  ~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {
106  if (!released_) mu_->Unlock();
107  }
108 
111 
112  void Release() ABSL_UNLOCK_FUNCTION() {
113  GPR_DEBUG_ASSERT(!released_);
114  released_ = true;
115  mu_->Unlock();
116  }
117 
118  private:
119  Mutex* const mu_;
120  bool released_ = false;
121 };
122 
123 class CondVar {
124  public:
125  CondVar() { gpr_cv_init(&cv_); }
127 
128  CondVar(const CondVar&) = delete;
129  CondVar& operator=(const CondVar&) = delete;
130 
131  void Signal() { gpr_cv_signal(&cv_); }
132  void SignalAll() { gpr_cv_broadcast(&cv_); }
133 
134  void Wait(Mutex* mu) { WaitWithDeadline(mu, absl::InfiniteFuture()); }
135  bool WaitWithTimeout(Mutex* mu, absl::Duration timeout) {
136  return gpr_cv_wait(&cv_, &mu->mu_, ToGprTimeSpec(timeout)) != 0;
137  }
138  bool WaitWithDeadline(Mutex* mu, absl::Time deadline) {
139  return gpr_cv_wait(&cv_, &mu->mu_, ToGprTimeSpec(deadline)) != 0;
140  }
141 
142  private:
143  gpr_cv cv_;
144 };
145 
146 #endif // GPR_ABSEIL_SYNC
147 
148 template <typename Predicate>
149 static void WaitUntil(CondVar* cv, Mutex* mu, Predicate pred) {
150  while (!pred()) {
151  cv->Wait(mu);
152  }
153 }
154 
155 // Returns true iff we timed-out
156 template <typename Predicate>
157 static bool WaitUntilWithTimeout(CondVar* cv, Mutex* mu, Predicate pred,
158  absl::Duration timeout) {
159  while (!pred()) {
160  if (cv->WaitWithTimeout(mu, timeout)) return true;
161  }
162  return false;
163 }
164 
165 // Returns true iff we timed-out
166 template <typename Predicate>
167 static bool WaitUntilWithDeadline(CondVar* cv, Mutex* mu, Predicate pred,
168  absl::Time deadline) {
169  while (!pred()) {
170  if (cv->WaitWithDeadline(mu, deadline)) return true;
171  }
172  return false;
173 }
174 
175 // Deprecated. Prefer MutexLock
177  public:
178  explicit MutexLockForGprMu(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); }
180 
181  MutexLockForGprMu(const MutexLock&) = delete;
183 
184  private:
185  gpr_mu* const mu_;
186 };
187 
188 // Deprecated. Prefer MutexLock or ReleasableMutexLock
189 class ABSL_SCOPED_LOCKABLE LockableAndReleasableMutexLock {
190  public:
192  ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
193  : mu_(mu) {
194  mu_->Lock();
195  }
196  ~LockableAndReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {
197  if (!released_) mu_->Unlock();
198  }
199 
201  delete;
203  const LockableAndReleasableMutexLock&) = delete;
204 
205  void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
206  GPR_DEBUG_ASSERT(released_);
207  mu_->Lock();
208  released_ = false;
209  }
210 
211  void Release() ABSL_UNLOCK_FUNCTION() {
212  GPR_DEBUG_ASSERT(!released_);
213  released_ = true;
214  mu_->Unlock();
215  }
216 
217  private:
218  Mutex* const mu_;
219  bool released_ = false;
220 };
221 
222 } // namespace grpc_core
223 
224 #endif /* GRPC_CORE_LIB_GPRPP_SYNC_H */
Definition: sync.h:123
bool WaitWithDeadline(Mutex *mu, absl::Time deadline)
Definition: sync.h:138
CondVar(const CondVar &)=delete
void Signal()
Definition: sync.h:131
CondVar & operator=(const CondVar &)=delete
bool WaitWithTimeout(Mutex *mu, absl::Duration timeout)
Definition: sync.h:135
void Wait(Mutex *mu)
Definition: sync.h:134
CondVar()
Definition: sync.h:125
void SignalAll()
Definition: sync.h:132
~CondVar()
Definition: sync.h:126
LockableAndReleasableMutexLock & operator=(const LockableAndReleasableMutexLock &)=delete
void Release() ABSL_UNLOCK_FUNCTION()
Definition: sync.h:211
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION()
Definition: sync.h:205
~LockableAndReleasableMutexLock() ABSL_UNLOCK_FUNCTION()
Definition: sync.h:196
LockableAndReleasableMutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
Definition: sync.h:191
LockableAndReleasableMutexLock(const LockableAndReleasableMutexLock &)=delete
Definition: sync.h:59
bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true)
Definition: sync.h:69
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION()
Definition: sync.h:67
~Mutex()
Definition: sync.h:62
Mutex()
Definition: sync.h:61
void Unlock() ABSL_UNLOCK_FUNCTION()
Definition: sync.h:68
Mutex(const Mutex &)=delete
Mutex & operator=(const Mutex &)=delete
Definition: sync.h:176
MutexLockForGprMu & operator=(const MutexLock &)=delete
MutexLockForGprMu(const MutexLock &)=delete
~MutexLockForGprMu()
Definition: sync.h:179
MutexLockForGprMu(gpr_mu *mu)
Definition: sync.h:178
Definition: sync.h:85
MutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
Definition: sync.h:87
MutexLock & operator=(const MutexLock &)=delete
~MutexLock() ABSL_UNLOCK_FUNCTION()
Definition: sync.h:90
MutexLock(const MutexLock &)=delete
Definition: sync.h:99
~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION()
Definition: sync.h:105
ReleasableMutexLock & operator=(const ReleasableMutexLock &)=delete
void Release() ABSL_UNLOCK_FUNCTION()
Definition: sync.h:112
ReleasableMutexLock(const ReleasableMutexLock &)=delete
ReleasableMutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
Definition: sync.h:101
#define GPR_DEBUG_ASSERT(x)
Definition: log.h:101
pthread_cond_t gpr_cv
Definition: sync_posix.h:46
pthread_mutex_t gpr_mu
Definition: sync_posix.h:45
GPRAPI void gpr_cv_destroy(gpr_cv *cv)
Cause *cv no longer to be initialized, freeing any memory in use.
GPRAPI void gpr_cv_init(gpr_cv *cv)
— Condition variable interface —
GPRAPI int gpr_mu_trylock(gpr_mu *mu)
Without blocking, attempt to acquire an exclusive lock on *mu for the calling thread,...
GPRAPI void gpr_mu_destroy(gpr_mu *mu)
Cause *mu no longer to be initialized, freeing any memory in use.
GPRAPI void gpr_cv_broadcast(gpr_cv *cv)
Wake all threads waiting on *cv.
GPRAPI void gpr_mu_lock(gpr_mu *mu)
Wait until no thread has a lock on *mu, cause the calling thread to own an exclusive lock on *mu,...
GPRAPI void gpr_mu_init(gpr_mu *mu)
— Mutex interface —
GPRAPI void gpr_cv_signal(gpr_cv *cv)
If any threads are waiting on *cv, wake at least one.
GPRAPI int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline)
Atomically release *mu and wait on *cv.
GPRAPI void gpr_mu_unlock(gpr_mu *mu)
Release an exclusive lock on *mu held by the calling thread.
Round Robin Policy.
Definition: backend_metric.cc:26
gpr_mu * GetUnderlyingGprMu(Mutex *mutex)
Definition: sync.h:83
gpr_timespec ToGprTimeSpec(absl::Duration duration)
Definition: time_util.cc:25
gpr_mu mu
Definition: timer_generic.cc:6