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
44namespace grpc {
45namespace internal {
46
47class Mutex {
48 public:
49 Mutex() { g_core_codegen_interface->gpr_mu_init(mu: &mu_); }
50 ~Mutex() { g_core_codegen_interface->gpr_mu_destroy(mu: &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::
69class MutexLock {
70 public:
71 explicit MutexLock(Mutex* mu) : mu_(mu->get()) {
72 g_core_codegen_interface->gpr_mu_lock(mu: mu_);
73 }
74 explicit MutexLock(gpr_mu* mu) : mu_(mu) {
75 g_core_codegen_interface->gpr_mu_lock(mu: mu_);
76 }
77 ~MutexLock() { g_core_codegen_interface->gpr_mu_unlock(mu: mu_); }
78
79 MutexLock(const MutexLock&) = delete;
80 MutexLock& operator=(const MutexLock&) = delete;
81
82 private:
83 gpr_mu* const mu_;
84};
85
86class ReleasableMutexLock {
87 public:
88 explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) {
89 g_core_codegen_interface->gpr_mu_lock(mu: mu_);
90 }
91 explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) {
92 g_core_codegen_interface->gpr_mu_lock(mu: mu_);
93 }
94 ~ReleasableMutexLock() {
95 if (!released_) g_core_codegen_interface->gpr_mu_unlock(mu: 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: 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: mu_);
111 }
112
113 private:
114 gpr_mu* const mu_;
115 bool released_ = false;
116};
117
118class CondVar {
119 public:
120 CondVar() { g_core_codegen_interface->gpr_cv_init(cv: &cv_); }
121 ~CondVar() { g_core_codegen_interface->gpr_cv_destroy(cv: &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: &cv_); }
127 void Broadcast() { g_core_codegen_interface->gpr_cv_broadcast(cv: &cv_); }
128
129 int Wait(Mutex* mu) {
130 return Wait(mu,
131 deadline: g_core_codegen_interface->gpr_inf_future(type: GPR_CLOCK_REALTIME));
132 }
133 int Wait(Mutex* mu, const gpr_timespec& deadline) {
134 return g_core_codegen_interface->gpr_cv_wait(cv: &cv_, mu: mu->get(), abs_deadline: deadline);
135 }
136
137 template <typename Predicate>
138 void WaitUntil(Mutex* mu, Predicate pred) {
139 while (!pred()) {
140 Wait(mu, deadline: g_core_codegen_interface->gpr_inf_future(type: 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

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