3 * Copyright 2019 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #ifndef GRPC_CORE_LIB_GPRPP_SYNC_H
20 #define GRPC_CORE_LIB_GPRPP_SYNC_H
22 #include <grpc/support/port_platform.h>
24 #include <grpc/support/log.h>
25 #include <grpc/support/sync.h>
26 #include <grpc/support/time.h>
28 #include "absl/synchronization/mutex.h"
29 #include "src/core/lib/gprpp/time_util.h"
31 // The core library is not accessible in C++ codegen headers, and vice versa.
32 // Thus, we need to have duplicate headers with similar functionality.
33 // Make sure any change to this file is also reflected in
34 // include/grpcpp/impl/codegen/sync.h.
36 // Whenever possible, prefer using this file over <grpcpp/impl/codegen/sync.h>
37 // since this file doesn't rely on g_core_codegen_interface and hence does not
38 // pay the costs of virtual function calls.
42 #ifdef GPR_ABSEIL_SYNC
44 using Mutex = absl::Mutex;
45 using MutexLock = absl::MutexLock;
46 using ReleasableMutexLock = absl::ReleasableMutexLock;
47 using CondVar = absl::CondVar;
49 // Returns the underlying gpr_mu from Mutex. This should be used only when
50 // it has to like passing the C++ mutex to C-core API.
51 // TODO(veblush): Remove this after C-core no longer uses gpr_mu.
52 inline gpr_mu* GetUnderlyingGprMu(Mutex* mutex) {
53 return reinterpret_cast<gpr_mu*>(mutex);
58 class ABSL_LOCKABLE Mutex {
60 Mutex() { gpr_mu_init(&mu_); }
61 ~Mutex() { gpr_mu_destroy(&mu_); }
63 Mutex(const Mutex&) = delete;
64 Mutex& operator=(const Mutex&) = delete;
66 void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { gpr_mu_lock(&mu_); }
67 void Unlock() ABSL_UNLOCK_FUNCTION() { gpr_mu_unlock(&mu_); }
68 bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
69 return gpr_mu_trylock(&mu_) != 0;
76 friend gpr_mu* GetUnderlyingGprMu(Mutex* mutex);
79 // Returns the underlying gpr_mu from Mutex. This should be used only when
80 // it has to like passing the C++ mutex to C-core API.
81 // TODO(veblush): Remove this after C-core no longer uses gpr_mu.
82 inline gpr_mu* GetUnderlyingGprMu(Mutex* mutex) { return &mutex->mu_; }
84 class ABSL_SCOPED_LOCKABLE MutexLock {
86 explicit MutexLock(Mutex* mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
89 ~MutexLock() ABSL_UNLOCK_FUNCTION() { mu_->Unlock(); }
91 MutexLock(const MutexLock&) = delete;
92 MutexLock& operator=(const MutexLock&) = delete;
98 class ABSL_SCOPED_LOCKABLE ReleasableMutexLock {
100 explicit ReleasableMutexLock(Mutex* mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
104 ~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {
105 if (!released_) mu_->Unlock();
108 ReleasableMutexLock(const ReleasableMutexLock&) = delete;
109 ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete;
111 void Release() ABSL_UNLOCK_FUNCTION() {
112 GPR_DEBUG_ASSERT(!released_);
119 bool released_ = false;
124 CondVar() { gpr_cv_init(&cv_); }
125 ~CondVar() { gpr_cv_destroy(&cv_); }
127 CondVar(const CondVar&) = delete;
128 CondVar& operator=(const CondVar&) = delete;
130 void Signal() { gpr_cv_signal(&cv_); }
131 void SignalAll() { gpr_cv_broadcast(&cv_); }
133 void Wait(Mutex* mu) { WaitWithDeadline(mu, absl::InfiniteFuture()); }
134 bool WaitWithTimeout(Mutex* mu, absl::Duration timeout) {
135 return gpr_cv_wait(&cv_, &mu->mu_, ToGprTimeSpec(timeout)) != 0;
137 bool WaitWithDeadline(Mutex* mu, absl::Time deadline) {
138 return gpr_cv_wait(&cv_, &mu->mu_, ToGprTimeSpec(deadline)) != 0;
145 #endif // GPR_ABSEIL_SYNC
147 // Deprecated. Prefer MutexLock
148 class MutexLockForGprMu {
150 explicit MutexLockForGprMu(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); }
151 ~MutexLockForGprMu() { gpr_mu_unlock(mu_); }
153 MutexLockForGprMu(const MutexLock&) = delete;
154 MutexLockForGprMu& operator=(const MutexLock&) = delete;
160 // Deprecated. Prefer MutexLock or ReleasableMutexLock
161 class ABSL_SCOPED_LOCKABLE LockableAndReleasableMutexLock {
163 explicit LockableAndReleasableMutexLock(Mutex* mu)
164 ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
168 ~LockableAndReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {
169 if (!released_) mu_->Unlock();
172 LockableAndReleasableMutexLock(const LockableAndReleasableMutexLock&) =
174 LockableAndReleasableMutexLock& operator=(
175 const LockableAndReleasableMutexLock&) = delete;
177 void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
178 GPR_DEBUG_ASSERT(released_);
183 void Release() ABSL_UNLOCK_FUNCTION() {
184 GPR_DEBUG_ASSERT(!released_);
191 bool released_ = false;
194 } // namespace grpc_core
196 #endif /* GRPC_CORE_LIB_GPRPP_SYNC_H */