Imported Upstream version 1.21.0
[platform/upstream/grpc.git] / include / grpcpp / impl / codegen / sync.h
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:
49   Mutex() { g_core_codegen_interface->gpr_mu_init(&mu_); }
50   ~Mutex() { g_core_codegen_interface->gpr_mu_destroy(&mu_); }
51
52   Mutex(const Mutex&) = delete;
53   Mutex& operator=(const Mutex&) = delete;
54
55   gpr_mu* get() { return &mu_; }
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:
71   explicit MutexLock(Mutex* mu) : mu_(mu->get()) {
72     g_core_codegen_interface->gpr_mu_lock(mu_);
73   }
74   explicit MutexLock(gpr_mu* mu) : mu_(mu) {
75     g_core_codegen_interface->gpr_mu_lock(mu_);
76   }
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:
88   explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) {
89     g_core_codegen_interface->gpr_mu_lock(mu_);
90   }
91   explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) {
92     g_core_codegen_interface->gpr_mu_lock(mu_);
93   }
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
101   void Lock() {
102     GPR_DEBUG_ASSERT(released_);
103     g_core_codegen_interface->gpr_mu_lock(mu_);
104     released_ = false;
105   }
106
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:
120   CondVar() { g_core_codegen_interface->gpr_cv_init(&cv_); }
121   ~CondVar() { g_core_codegen_interface->gpr_cv_destroy(&cv_); }
122
123   CondVar(const CondVar&) = delete;
124   CondVar& operator=(const CondVar&) = delete;
125
126   void Signal() { g_core_codegen_interface->gpr_cv_signal(&cv_); }
127   void Broadcast() { g_core_codegen_interface->gpr_cv_broadcast(&cv_); }
128
129   int Wait(Mutex* mu) {
130     return Wait(mu,
131                 g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME));
132   }
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>
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