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

source code of include/grpcpp/impl/codegen/sync.h