• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "absl/synchronization/mutex.h"
36 
37 // The core library is not accessible in C++ codegen headers, and vice versa.
38 // Thus, we need to have duplicate headers with similar functionality.
39 // Make sure any change to this file is also reflected in
40 // src/core/lib/gprpp/sync.h too.
41 //
42 // Whenever possible, prefer "src/core/lib/gprpp/sync.h" over this file,
43 // since in core we do not rely on g_core_codegen_interface and hence do not
44 // pay the costs of virtual function calls.
45 
46 namespace grpc {
47 namespace internal {
48 
49 #ifdef GRPCPP_ABSEIL_SYNC
50 
51 using Mutex = absl::Mutex;
52 using MutexLock = absl::MutexLock;
53 using ReleasableMutexLock = absl::ReleasableMutexLock;
54 using CondVar = absl::CondVar;
55 
56 #else
57 
58 class ABSL_LOCKABLE Mutex {
59  public:
60   Mutex() { g_core_codegen_interface->gpr_mu_init(&mu_); }
61   ~Mutex() { g_core_codegen_interface->gpr_mu_destroy(&mu_); }
62 
63   Mutex(const Mutex&) = delete;
64   Mutex& operator=(const Mutex&) = delete;
65 
66   void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
67     g_core_codegen_interface->gpr_mu_lock(&mu_);
68   }
69   void Unlock() ABSL_UNLOCK_FUNCTION() {
70     g_core_codegen_interface->gpr_mu_unlock(&mu_);
71   }
72 
73  private:
74   union {
75     gpr_mu mu_;
76     std::mutex do_not_use_sth_;
77 #ifdef GPR_HAS_PTHREAD_H
78     pthread_mutex_t do_not_use_pth_;
79 #endif
80   };
81 
82   friend class CondVar;
83 };
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 
109   ReleasableMutexLock(const ReleasableMutexLock&) = delete;
110   ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete;
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() { g_core_codegen_interface->gpr_cv_init(&cv_); }
126   ~CondVar() { g_core_codegen_interface->gpr_cv_destroy(&cv_); }
127 
128   CondVar(const CondVar&) = delete;
129   CondVar& operator=(const CondVar&) = delete;
130 
131   void Signal() { g_core_codegen_interface->gpr_cv_signal(&cv_); }
132   void SignalAll() { g_core_codegen_interface->gpr_cv_broadcast(&cv_); }
133 
134   void Wait(Mutex* mu) {
135     g_core_codegen_interface->gpr_cv_wait(
136         &cv_, &mu->mu_,
137         g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME));
138   }
139 
140  private:
141   gpr_cv cv_;
142 };
143 
144 #endif  // GRPCPP_ABSEIL_SYNC
145 
146 template <typename Predicate>
WaitUntil(CondVar * cv,Mutex * mu,Predicate pred)147 static void WaitUntil(CondVar* cv, Mutex* mu, Predicate pred) {
148   while (!pred()) {
149     cv->Wait(mu);
150   }
151 }
152 
153 }  // namespace internal
154 }  // namespace grpc
155 
156 #endif  // GRPCPP_IMPL_CODEGEN_SYNC_H
157