1*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors. 2*9356374aSAndroid Build Coastguard Worker // 3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*9356374aSAndroid Build Coastguard Worker // 7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*9356374aSAndroid Build Coastguard Worker // 9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*9356374aSAndroid Build Coastguard Worker // limitations under the License. 14*9356374aSAndroid Build Coastguard Worker 15*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/barrier.h" 16*9356374aSAndroid Build Coastguard Worker 17*9356374aSAndroid Build Coastguard Worker #include <thread> // NOLINT(build/c++11) 18*9356374aSAndroid Build Coastguard Worker #include <vector> 19*9356374aSAndroid Build Coastguard Worker 20*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h" 21*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/mutex.h" 22*9356374aSAndroid Build Coastguard Worker #include "absl/time/clock.h" 23*9356374aSAndroid Build Coastguard Worker 24*9356374aSAndroid Build Coastguard Worker TEST(Barrier,SanityTest)25*9356374aSAndroid Build Coastguard WorkerTEST(Barrier, SanityTest) { 26*9356374aSAndroid Build Coastguard Worker constexpr int kNumThreads = 10; 27*9356374aSAndroid Build Coastguard Worker absl::Barrier* barrier = new absl::Barrier(kNumThreads); 28*9356374aSAndroid Build Coastguard Worker 29*9356374aSAndroid Build Coastguard Worker absl::Mutex mutex; 30*9356374aSAndroid Build Coastguard Worker int counter = 0; // Guarded by mutex. 31*9356374aSAndroid Build Coastguard Worker 32*9356374aSAndroid Build Coastguard Worker auto thread_func = [&] { 33*9356374aSAndroid Build Coastguard Worker if (barrier->Block()) { 34*9356374aSAndroid Build Coastguard Worker // This thread is the last thread to reach the barrier so it is 35*9356374aSAndroid Build Coastguard Worker // responsible for deleting it. 36*9356374aSAndroid Build Coastguard Worker delete barrier; 37*9356374aSAndroid Build Coastguard Worker } 38*9356374aSAndroid Build Coastguard Worker 39*9356374aSAndroid Build Coastguard Worker // Increment the counter. 40*9356374aSAndroid Build Coastguard Worker absl::MutexLock lock(&mutex); 41*9356374aSAndroid Build Coastguard Worker ++counter; 42*9356374aSAndroid Build Coastguard Worker }; 43*9356374aSAndroid Build Coastguard Worker 44*9356374aSAndroid Build Coastguard Worker // Start (kNumThreads - 1) threads running thread_func. 45*9356374aSAndroid Build Coastguard Worker std::vector<std::thread> threads; 46*9356374aSAndroid Build Coastguard Worker for (int i = 0; i < kNumThreads - 1; ++i) { 47*9356374aSAndroid Build Coastguard Worker threads.push_back(std::thread(thread_func)); 48*9356374aSAndroid Build Coastguard Worker } 49*9356374aSAndroid Build Coastguard Worker 50*9356374aSAndroid Build Coastguard Worker // Give (kNumThreads - 1) threads a chance to reach the barrier. 51*9356374aSAndroid Build Coastguard Worker // This test assumes at least one thread will have run after the 52*9356374aSAndroid Build Coastguard Worker // sleep has elapsed. Sleeping in a test is usually bad form, but we 53*9356374aSAndroid Build Coastguard Worker // need to make sure that we are testing the barrier instead of some 54*9356374aSAndroid Build Coastguard Worker // other synchronization method. 55*9356374aSAndroid Build Coastguard Worker absl::SleepFor(absl::Seconds(1)); 56*9356374aSAndroid Build Coastguard Worker 57*9356374aSAndroid Build Coastguard Worker // The counter should still be zero since no thread should have 58*9356374aSAndroid Build Coastguard Worker // been able to pass the barrier yet. 59*9356374aSAndroid Build Coastguard Worker { 60*9356374aSAndroid Build Coastguard Worker absl::MutexLock lock(&mutex); 61*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(counter, 0); 62*9356374aSAndroid Build Coastguard Worker } 63*9356374aSAndroid Build Coastguard Worker 64*9356374aSAndroid Build Coastguard Worker // Start 1 more thread. This should make all threads pass the barrier. 65*9356374aSAndroid Build Coastguard Worker threads.push_back(std::thread(thread_func)); 66*9356374aSAndroid Build Coastguard Worker 67*9356374aSAndroid Build Coastguard Worker // All threads should now be able to proceed and finish. 68*9356374aSAndroid Build Coastguard Worker for (auto& thread : threads) { 69*9356374aSAndroid Build Coastguard Worker thread.join(); 70*9356374aSAndroid Build Coastguard Worker } 71*9356374aSAndroid Build Coastguard Worker 72*9356374aSAndroid Build Coastguard Worker // All threads should now have incremented the counter. 73*9356374aSAndroid Build Coastguard Worker absl::MutexLock lock(&mutex); 74*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(counter, kNumThreads); 75*9356374aSAndroid Build Coastguard Worker } 76