• 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 // 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