tor-browser

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

blocking_counter.cc (2283B)


      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/blocking_counter.h"
     16 
     17 #include <atomic>
     18 
     19 #include "absl/base/internal/raw_logging.h"
     20 #include "absl/base/internal/tracing.h"
     21 
     22 namespace absl {
     23 ABSL_NAMESPACE_BEGIN
     24 
     25 namespace {
     26 
     27 // Return whether int *arg is true.
     28 bool IsDone(void *arg) { return *reinterpret_cast<bool *>(arg); }
     29 
     30 }  // namespace
     31 
     32 BlockingCounter::BlockingCounter(int initial_count)
     33    : count_(initial_count),
     34      num_waiting_(0),
     35      done_{initial_count == 0 ? true : false} {
     36  ABSL_RAW_CHECK(initial_count >= 0, "BlockingCounter initial_count negative");
     37 }
     38 
     39 bool BlockingCounter::DecrementCount() {
     40  int count = count_.fetch_sub(1, std::memory_order_acq_rel) - 1;
     41  ABSL_RAW_CHECK(count >= 0,
     42                 "BlockingCounter::DecrementCount() called too many times");
     43  if (count == 0) {
     44    base_internal::TraceSignal(this, TraceObjectKind());
     45    MutexLock l(&lock_);
     46    done_ = true;
     47    return true;
     48  }
     49  return false;
     50 }
     51 
     52 void BlockingCounter::Wait() {
     53  base_internal::TraceWait(this, TraceObjectKind());
     54  {
     55    MutexLock l(&this->lock_);
     56 
     57    // only one thread may call Wait(). To support more than one thread,
     58    // implement a counter num_to_exit, like in the Barrier class.
     59    ABSL_RAW_CHECK(num_waiting_ == 0, "multiple threads called Wait()");
     60    num_waiting_++;
     61 
     62    this->lock_.Await(Condition(IsDone, &this->done_));
     63 
     64    // At this point, we know that all threads executing DecrementCount
     65    // will not touch this object again.
     66    // Therefore, the thread calling this method is free to delete the object
     67    // after we return from this method.
     68  }
     69  base_internal::TraceContinue(this, TraceObjectKind());
     70 }
     71 
     72 ABSL_NAMESPACE_END
     73 }  // namespace absl