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