tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

call_once_test.cc (3208B)


      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/base/call_once.h"
     16 
     17 #include <thread>
     18 #include <vector>
     19 
     20 #include "gtest/gtest.h"
     21 #include "absl/base/attributes.h"
     22 #include "absl/base/const_init.h"
     23 #include "absl/base/thread_annotations.h"
     24 #include "absl/synchronization/mutex.h"
     25 
     26 namespace absl {
     27 ABSL_NAMESPACE_BEGIN
     28 namespace {
     29 
     30 absl::once_flag once;
     31 
     32 ABSL_CONST_INIT Mutex counters_mu(absl::kConstInit);
     33 
     34 int running_thread_count ABSL_GUARDED_BY(counters_mu) = 0;
     35 int call_once_invoke_count ABSL_GUARDED_BY(counters_mu) = 0;
     36 int call_once_finished_count ABSL_GUARDED_BY(counters_mu) = 0;
     37 int call_once_return_count ABSL_GUARDED_BY(counters_mu) = 0;
     38 bool done_blocking ABSL_GUARDED_BY(counters_mu) = false;
     39 
     40 // Function to be called from absl::call_once.  Waits for a notification.
     41 void WaitAndIncrement() {
     42  counters_mu.Lock();
     43  ++call_once_invoke_count;
     44  counters_mu.Unlock();
     45 
     46  counters_mu.LockWhen(Condition(&done_blocking));
     47  ++call_once_finished_count;
     48  counters_mu.Unlock();
     49 }
     50 
     51 void ThreadBody() {
     52  counters_mu.Lock();
     53  ++running_thread_count;
     54  counters_mu.Unlock();
     55 
     56  absl::call_once(once, WaitAndIncrement);
     57 
     58  counters_mu.Lock();
     59  ++call_once_return_count;
     60  counters_mu.Unlock();
     61 }
     62 
     63 // Returns true if all threads are set up for the test.
     64 bool ThreadsAreSetup(void*) ABSL_EXCLUSIVE_LOCKS_REQUIRED(counters_mu) {
     65  // All ten threads must be running, and WaitAndIncrement should be blocked.
     66  return running_thread_count == 10 && call_once_invoke_count == 1;
     67 }
     68 
     69 TEST(CallOnceTest, ExecutionCount) {
     70  std::vector<std::thread> threads;
     71 
     72  // Start 10 threads all calling call_once on the same once_flag.
     73  for (int i = 0; i < 10; ++i) {
     74    threads.emplace_back(ThreadBody);
     75  }
     76 
     77 
     78  // Wait until all ten threads have started, and WaitAndIncrement has been
     79  // invoked.
     80  counters_mu.LockWhen(Condition(ThreadsAreSetup, nullptr));
     81 
     82  // WaitAndIncrement should have been invoked by exactly one call_once()
     83  // instance.  That thread should be blocking on a notification, and all other
     84  // call_once instances should be blocking as well.
     85  EXPECT_EQ(call_once_invoke_count, 1);
     86  EXPECT_EQ(call_once_finished_count, 0);
     87  EXPECT_EQ(call_once_return_count, 0);
     88 
     89  // Allow WaitAndIncrement to finish executing.  Once it does, the other
     90  // call_once waiters will be unblocked.
     91  done_blocking = true;
     92  counters_mu.Unlock();
     93 
     94  for (std::thread& thread : threads) {
     95    thread.join();
     96  }
     97 
     98  counters_mu.Lock();
     99  EXPECT_EQ(call_once_invoke_count, 1);
    100  EXPECT_EQ(call_once_finished_count, 1);
    101  EXPECT_EQ(call_once_return_count, 10);
    102  counters_mu.Unlock();
    103 }
    104 
    105 }  // namespace
    106 ABSL_NAMESPACE_END
    107 }  // namespace absl