grpc
third_party
abseil-cpp
absl
synchronization
abseil-cpp/absl/synchronization/notification_test.cc
Go to the documentation of this file.
1
// Copyright 2017 The Abseil Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "absl/synchronization/notification.h"
16
17
#include <thread>
// NOLINT(build/c++11)
18
#include <vector>
19
20
#include "gtest/gtest.h"
21
#include "absl/synchronization/mutex.h"
22
23
namespace
absl
{
24
ABSL_NAMESPACE_BEGIN
25
26
// A thread-safe class that holds a counter.
27
class
ThreadSafeCounter
{
28
public
:
29
ThreadSafeCounter
() :
count_
(0) {}
30
31
void
Increment
() {
32
MutexLock
lock(&
mutex_
);
33
++
count_
;
34
}
35
36
int
Get
()
const
{
37
MutexLock
lock(&
mutex_
);
38
return
count_
;
39
}
40
41
void
WaitUntilGreaterOrEqual
(
int
n) {
42
MutexLock
lock(&
mutex_
);
43
auto
cond
= [
this
,
n
]() {
return
count_
>=
n
; };
44
mutex_
.
Await
(
Condition
(&
cond
));
45
}
46
47
private
:
48
mutable
Mutex
mutex_
;
49
int
count_
;
50
};
51
52
// Runs the |i|'th worker thread for the tests in BasicTests(). Increments the
53
// |ready_counter|, waits on the |notification|, and then increments the
54
// |done_counter|.
55
static
void
RunWorker
(
int
i,
ThreadSafeCounter
* ready_counter,
56
Notification
*
notification
,
57
ThreadSafeCounter
* done_counter) {
58
ready_counter->
Increment
();
59
notification
->WaitForNotification();
60
done_counter->
Increment
();
61
}
62
63
// Tests that the |notification| properly blocks and awakens threads. Assumes
64
// that the |notification| is not yet triggered. If |notify_before_waiting| is
65
// true, the |notification| is triggered before any threads are created, so the
66
// threads never block in WaitForNotification(). Otherwise, the |notification|
67
// is triggered at a later point when most threads are likely to be blocking in
68
// WaitForNotification().
69
static
void
BasicTests
(
bool
notify_before_waiting,
Notification
*
notification
) {
70
EXPECT_FALSE
(
notification
->HasBeenNotified());
71
EXPECT_FALSE
(
72
notification
->WaitForNotificationWithTimeout(
absl::Milliseconds
(0)));
73
EXPECT_FALSE
(
notification
->WaitForNotificationWithDeadline(
absl::Now
()));
74
75
const
absl::Duration
delay =
absl::Milliseconds
(50);
76
const
absl::Time
start
=
absl::Now
();
77
EXPECT_FALSE
(
notification
->WaitForNotificationWithTimeout(delay));
78
const
absl::Duration
elapsed =
absl::Now
() -
start
;
79
80
// Allow for a slight early return, to account for quality of implementation
81
// issues on various platforms.
82
const
absl::Duration
slop =
absl::Microseconds
(200);
83
EXPECT_LE
(delay - slop, elapsed)
84
<<
"WaitForNotificationWithTimeout returned "
<< delay - elapsed
85
<<
" early (with "
<< slop <<
" slop), start time was "
<<
start
;
86
87
ThreadSafeCounter
ready_counter;
88
ThreadSafeCounter
done_counter;
89
90
if
(notify_before_waiting) {
91
notification
->Notify();
92
}
93
94
// Create a bunch of threads that increment the |done_counter| after being
95
// notified.
96
const
int
kNumThreads
= 10;
97
std::vector<std::thread>
workers
;
98
for
(
int
i
= 0;
i
<
kNumThreads
; ++
i
) {
99
workers
.push_back(
std::thread
(&
RunWorker
,
i
, &ready_counter,
notification
,
100
&done_counter));
101
}
102
103
if
(!notify_before_waiting) {
104
ready_counter.
WaitUntilGreaterOrEqual
(
kNumThreads
);
105
106
// Workers have not been notified yet, so the |done_counter| should be
107
// unmodified.
108
EXPECT_EQ
(0, done_counter.
Get
());
109
110
notification
->Notify();
111
}
112
113
// After notifying and then joining the workers, both counters should be
114
// fully incremented.
115
notification
->WaitForNotification();
// should exit immediately
116
EXPECT_TRUE
(
notification
->HasBeenNotified());
117
EXPECT_TRUE
(
notification
->WaitForNotificationWithTimeout(
absl::Seconds
(0)));
118
EXPECT_TRUE
(
notification
->WaitForNotificationWithDeadline(
absl::Now
()));
119
for
(
std::thread
&
worker
:
workers
) {
120
worker
.join();
121
}
122
EXPECT_EQ
(
kNumThreads
, ready_counter.
Get
());
123
EXPECT_EQ
(
kNumThreads
, done_counter.
Get
());
124
}
125
126
TEST
(NotificationTest, SanityTest) {
127
Notification
local_notification1, local_notification2;
128
BasicTests
(
false
, &local_notification1);
129
BasicTests
(
true
, &local_notification2);
130
}
131
132
ABSL_NAMESPACE_END
133
}
// namespace absl
EXPECT_FALSE
#define EXPECT_FALSE(condition)
Definition:
bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1970
absl::Time
Definition:
third_party/abseil-cpp/absl/time/time.h:642
absl::Mutex
Definition:
abseil-cpp/absl/synchronization/mutex.h:131
absl::TEST
TEST(NotificationTest, SanityTest)
Definition:
abseil-cpp/absl/synchronization/notification_test.cc:126
EXPECT_LE
#define EXPECT_LE(val1, val2)
Definition:
bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2030
absl::Mutex::Await
void Await(const Condition &cond)
Definition:
abseil-cpp/absl/synchronization/mutex.cc:1548
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition:
third_party/abseil-cpp/absl/base/config.h:171
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition:
iomgr/time_averaged_stats_test.cc:27
absl::Notification
Definition:
abseil-cpp/absl/synchronization/notification.h:66
benchmark::Condition
std::condition_variable Condition
Definition:
benchmark/src/mutex.h:69
absl::Milliseconds
constexpr Duration Milliseconds(T n)
Definition:
third_party/abseil-cpp/absl/time/time.h:415
absl::MutexLock
Definition:
abseil-cpp/absl/synchronization/mutex.h:525
start
static uint64_t start
Definition:
benchmark-pound.c:74
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition:
third_party/abseil-cpp/absl/base/config.h:170
absl::Microseconds
constexpr Duration Microseconds(T n)
Definition:
third_party/abseil-cpp/absl/time/time.h:411
worker
Definition:
worker.py:1
cond
static uv_cond_t cond
Definition:
threadpool.c:33
absl::Duration
Definition:
third_party/abseil-cpp/absl/time/time.h:159
absl::ThreadSafeCounter
Definition:
abseil-cpp/absl/synchronization/notification_test.cc:27
absl::BasicTests
static void BasicTests(bool notify_before_waiting, Notification *notification)
Definition:
abseil-cpp/absl/synchronization/notification_test.cc:69
n
int n
Definition:
abseil-cpp/absl/container/btree_test.cc:1080
absl::RunWorker
static void RunWorker(int i, ThreadSafeCounter *ready_counter, Notification *notification, ThreadSafeCounter *done_counter)
Definition:
abseil-cpp/absl/synchronization/notification_test.cc:55
absl::Seconds
constexpr Duration Seconds(T n)
Definition:
third_party/abseil-cpp/absl/time/time.h:419
absl::Now
ABSL_NAMESPACE_BEGIN Time Now()
Definition:
abseil-cpp/absl/time/clock.cc:39
notification
Definition:
alts_tsi_handshaker_test.cc:76
absl::ThreadSafeCounter::ThreadSafeCounter
ThreadSafeCounter()
Definition:
abseil-cpp/absl/synchronization/notification_test.cc:29
kNumThreads
const int kNumThreads
Definition:
thread_stress_test.cc:46
absl::ThreadSafeCounter::Increment
void Increment()
Definition:
abseil-cpp/absl/synchronization/notification_test.cc:31
EXPECT_TRUE
#define EXPECT_TRUE(condition)
Definition:
bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1967
absl::ThreadSafeCounter::count_
int count_
Definition:
abseil-cpp/absl/synchronization/notification_test.cc:49
workers
struct child_worker * workers
absl::ThreadSafeCounter::Get
int Get() const
Definition:
abseil-cpp/absl/synchronization/notification_test.cc:36
absl
Definition:
abseil-cpp/absl/algorithm/algorithm.h:31
absl::ThreadSafeCounter::mutex_
Mutex mutex_
Definition:
abseil-cpp/absl/synchronization/notification_test.cc:48
absl::ThreadSafeCounter::WaitUntilGreaterOrEqual
void WaitUntilGreaterOrEqual(int n)
Definition:
abseil-cpp/absl/synchronization/notification_test.cc:41
thread
static uv_thread_t thread
Definition:
test-async-null-cb.c:29
i
uint64_t i
Definition:
abseil-cpp/absl/container/btree_benchmark.cc:230
grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:32