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