1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
//
//
// Copyright 2019 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#ifndef GRPCPP_IMPL_SYNC_H
#define GRPCPP_IMPL_SYNC_H
#include <grpc/support/port_platform.h>
#ifdef GPR_HAS_PTHREAD_H
#include <pthread.h>
#endif
#include <mutex>
#include "y_absl/synchronization/mutex.h"
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
// The core library is not accessible in C++ codegen headers, and vice versa.
// Thus, we need to have duplicate headers with similar functionality.
// Make sure any change to this file is also reflected in
// src/core/lib/gprpp/sync.h too.
//
// Whenever possible, prefer "src/core/lib/gprpp/sync.h" over this file,
// since in core we do not rely on g_core_codegen_interface and hence do not
// pay the costs of virtual function calls.
namespace grpc {
namespace internal {
#ifdef GPR_ABSEIL_SYNC
using Mutex = y_absl::Mutex;
using MutexLock = y_absl::MutexLock;
using ReleasableMutexLock = y_absl::ReleasableMutexLock;
using CondVar = y_absl::CondVar;
#else
class Y_ABSL_LOCKABLE Mutex {
public:
Mutex() { gpr_mu_init(&mu_); }
~Mutex() { gpr_mu_destroy(&mu_); }
Mutex(const Mutex&) = delete;
Mutex& operator=(const Mutex&) = delete;
void Lock() Y_ABSL_EXCLUSIVE_LOCK_FUNCTION() { gpr_mu_lock(&mu_); }
void Unlock() Y_ABSL_UNLOCK_FUNCTION() { gpr_mu_unlock(&mu_); }
private:
union {
gpr_mu mu_;
std::mutex do_not_use_sth_;
#ifdef GPR_HAS_PTHREAD_H
pthread_mutex_t do_not_use_pth_;
#endif
};
friend class CondVar;
};
class Y_ABSL_SCOPED_LOCKABLE MutexLock {
public:
explicit MutexLock(Mutex* mu) Y_ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
mu_->Lock();
}
~MutexLock() Y_ABSL_UNLOCK_FUNCTION() { mu_->Unlock(); }
MutexLock(const MutexLock&) = delete;
MutexLock& operator=(const MutexLock&) = delete;
private:
Mutex* const mu_;
};
class Y_ABSL_SCOPED_LOCKABLE ReleasableMutexLock {
public:
explicit ReleasableMutexLock(Mutex* mu) Y_ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
mu_->Lock();
}
~ReleasableMutexLock() Y_ABSL_UNLOCK_FUNCTION() {
if (!released_) mu_->Unlock();
}
ReleasableMutexLock(const ReleasableMutexLock&) = delete;
ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete;
void Release() Y_ABSL_UNLOCK_FUNCTION() {
GPR_DEBUG_ASSERT(!released_);
released_ = true;
mu_->Unlock();
}
private:
Mutex* const mu_;
bool released_ = false;
};
class CondVar {
public:
CondVar() { gpr_cv_init(&cv_); }
~CondVar() { gpr_cv_destroy(&cv_); }
CondVar(const CondVar&) = delete;
CondVar& operator=(const CondVar&) = delete;
void Signal() { gpr_cv_signal(&cv_); }
void SignalAll() { gpr_cv_broadcast(&cv_); }
void Wait(Mutex* mu) {
gpr_cv_wait(&cv_, &mu->mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
}
private:
gpr_cv cv_;
};
#endif // GPR_ABSEIL_SYNC
template <typename Predicate>
GRPC_DEPRECATED("incompatible with thread safety analysis")
static void WaitUntil(CondVar* cv, Mutex* mu, Predicate pred) {
while (!pred()) {
cv->Wait(mu);
}
}
} // namespace internal
} // namespace grpc
#endif // GRPCPP_IMPL_SYNC_H
|