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 22 #include <grpc/impl/codegen/port_platform.h> 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 // The core library is not accessible in C++ codegen headers, and vice versa. 30 // Thus, we need to have duplicate headers with similar functionality. 31 // Make sure any change to this file is also reflected in 32 // include/grpcpp/impl/codegen/sync.h. 33 // 34 // Whenever possible, prefer using this file over <grpcpp/impl/codegen/sync.h> 35 // since this file doesn't rely on g_core_codegen_interface and hence does not 36 // pay the costs of virtual function calls. 37 38 namespace grpc_core { 39 40 class Mutex { 41 public: Mutex()42 Mutex() { gpr_mu_init(&mu_); } ~Mutex()43 ~Mutex() { gpr_mu_destroy(&mu_); } 44 45 Mutex(const Mutex&) = delete; 46 Mutex& operator=(const Mutex&) = delete; 47 get()48 gpr_mu* get() { return &mu_; } get()49 const gpr_mu* get() const { return &mu_; } 50 51 private: 52 gpr_mu mu_; 53 }; 54 55 // MutexLock is a std:: 56 class MutexLock { 57 public: MutexLock(Mutex * mu)58 explicit MutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } MutexLock(gpr_mu * mu)59 explicit MutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } ~MutexLock()60 ~MutexLock() { gpr_mu_unlock(mu_); } 61 62 MutexLock(const MutexLock&) = delete; 63 MutexLock& operator=(const MutexLock&) = delete; 64 65 private: 66 gpr_mu* const mu_; 67 }; 68 69 class ReleasableMutexLock { 70 public: ReleasableMutexLock(Mutex * mu)71 explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } ReleasableMutexLock(gpr_mu * mu)72 explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } ~ReleasableMutexLock()73 ~ReleasableMutexLock() { 74 if (!released_) gpr_mu_unlock(mu_); 75 } 76 77 ReleasableMutexLock(const ReleasableMutexLock&) = delete; 78 ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete; 79 Lock()80 void Lock() { 81 GPR_DEBUG_ASSERT(released_); 82 gpr_mu_lock(mu_); 83 released_ = false; 84 } 85 Unlock()86 void Unlock() { 87 GPR_DEBUG_ASSERT(!released_); 88 released_ = true; 89 gpr_mu_unlock(mu_); 90 } 91 92 private: 93 gpr_mu* const mu_; 94 bool released_ = false; 95 }; 96 97 class CondVar { 98 public: CondVar()99 CondVar() { gpr_cv_init(&cv_); } ~CondVar()100 ~CondVar() { gpr_cv_destroy(&cv_); } 101 102 CondVar(const CondVar&) = delete; 103 CondVar& operator=(const CondVar&) = delete; 104 Signal()105 void Signal() { gpr_cv_signal(&cv_); } Broadcast()106 void Broadcast() { gpr_cv_broadcast(&cv_); } 107 Wait(Mutex * mu)108 int Wait(Mutex* mu) { return Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); } Wait(Mutex * mu,const gpr_timespec & deadline)109 int Wait(Mutex* mu, const gpr_timespec& deadline) { 110 return gpr_cv_wait(&cv_, mu->get(), deadline); 111 } 112 113 template <typename Predicate> WaitUntil(Mutex * mu,Predicate pred)114 void WaitUntil(Mutex* mu, Predicate pred) { 115 while (!pred()) { 116 Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); 117 } 118 } 119 120 // Returns true iff we timed-out 121 template <typename Predicate> WaitUntil(Mutex * mu,Predicate pred,const gpr_timespec & deadline)122 bool WaitUntil(Mutex* mu, Predicate pred, const gpr_timespec& deadline) { 123 while (!pred()) { 124 if (Wait(mu, deadline)) return true; 125 } 126 return false; 127 } 128 129 private: 130 gpr_cv cv_; 131 }; 132 133 } // namespace grpc_core 134 135 #endif /* GRPC_CORE_LIB_GPRPP_SYNC_H */ 136