Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/synchronization/notification.h"
00016
00017 #include <thread>
00018 #include <vector>
00019
00020 #include "gtest/gtest.h"
00021 #include "absl/synchronization/mutex.h"
00022
00023 namespace absl {
00024
00025
00026 class ThreadSafeCounter {
00027 public:
00028 ThreadSafeCounter() : count_(0) {}
00029
00030 void Increment() {
00031 MutexLock lock(&mutex_);
00032 ++count_;
00033 }
00034
00035 int Get() const {
00036 MutexLock lock(&mutex_);
00037 return count_;
00038 }
00039
00040 void WaitUntilGreaterOrEqual(int n) {
00041 MutexLock lock(&mutex_);
00042 auto cond = [this, n]() { return count_ >= n; };
00043 mutex_.Await(Condition(&cond));
00044 }
00045
00046 private:
00047 mutable Mutex mutex_;
00048 int count_;
00049 };
00050
00051
00052
00053
00054 static void RunWorker(int i, ThreadSafeCounter* ready_counter,
00055 Notification* notification,
00056 ThreadSafeCounter* done_counter) {
00057 ready_counter->Increment();
00058 notification->WaitForNotification();
00059 done_counter->Increment();
00060 }
00061
00062
00063
00064
00065
00066
00067
00068 static void BasicTests(bool notify_before_waiting, Notification* notification) {
00069 EXPECT_FALSE(notification->HasBeenNotified());
00070 EXPECT_FALSE(
00071 notification->WaitForNotificationWithTimeout(absl::Milliseconds(0)));
00072 EXPECT_FALSE(notification->WaitForNotificationWithDeadline(absl::Now()));
00073
00074 const absl::Duration delay = absl::Milliseconds(50);
00075 const absl::Time start = absl::Now();
00076 EXPECT_FALSE(notification->WaitForNotificationWithTimeout(delay));
00077 const absl::Duration elapsed = absl::Now() - start;
00078
00079
00080
00081 const absl::Duration slop = absl::Microseconds(200);
00082 EXPECT_LE(delay - slop, elapsed)
00083 << "WaitForNotificationWithTimeout returned " << delay - elapsed
00084 << " early (with " << slop << " slop), start time was " << start;
00085
00086 ThreadSafeCounter ready_counter;
00087 ThreadSafeCounter done_counter;
00088
00089 if (notify_before_waiting) {
00090 notification->Notify();
00091 }
00092
00093
00094
00095 const int kNumThreads = 10;
00096 std::vector<std::thread> workers;
00097 for (int i = 0; i < kNumThreads; ++i) {
00098 workers.push_back(std::thread(&RunWorker, i, &ready_counter, notification,
00099 &done_counter));
00100 }
00101
00102 if (!notify_before_waiting) {
00103 ready_counter.WaitUntilGreaterOrEqual(kNumThreads);
00104
00105
00106
00107 EXPECT_EQ(0, done_counter.Get());
00108
00109 notification->Notify();
00110 }
00111
00112
00113
00114 notification->WaitForNotification();
00115 EXPECT_TRUE(notification->HasBeenNotified());
00116 EXPECT_TRUE(notification->WaitForNotificationWithTimeout(absl::Seconds(0)));
00117 EXPECT_TRUE(notification->WaitForNotificationWithDeadline(absl::Now()));
00118 for (std::thread& worker : workers) {
00119 worker.join();
00120 }
00121 EXPECT_EQ(kNumThreads, ready_counter.Get());
00122 EXPECT_EQ(kNumThreads, done_counter.Get());
00123 }
00124
00125 TEST(NotificationTest, SanityTest) {
00126 Notification local_notification1, local_notification2;
00127 BasicTests(false, &local_notification1);
00128 BasicTests(true, &local_notification2);
00129 }
00130
00131 }