tor-browser

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

stdcpp_waiter.cc (2608B)


      1 // Copyright 2023 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/internal/stdcpp_waiter.h"
     16 
     17 #ifdef ABSL_INTERNAL_HAVE_STDCPP_WAITER
     18 
     19 #include <chrono>  // NOLINT(build/c++11)
     20 #include <condition_variable>  // NOLINT(build/c++11)
     21 #include <mutex>  // NOLINT(build/c++11)
     22 
     23 #include "absl/base/config.h"
     24 #include "absl/base/internal/raw_logging.h"
     25 #include "absl/base/internal/thread_identity.h"
     26 #include "absl/base/optimization.h"
     27 #include "absl/synchronization/internal/kernel_timeout.h"
     28 
     29 namespace absl {
     30 ABSL_NAMESPACE_BEGIN
     31 namespace synchronization_internal {
     32 
     33 StdcppWaiter::StdcppWaiter() : waiter_count_(0), wakeup_count_(0) {}
     34 
     35 bool StdcppWaiter::Wait(KernelTimeout t) {
     36  std::unique_lock<std::mutex> lock(mu_);
     37  ++waiter_count_;
     38 
     39  // Loop until we find a wakeup to consume or timeout.
     40  // Note that, since the thread ticker is just reset, we don't need to check
     41  // whether the thread is idle on the very first pass of the loop.
     42  bool first_pass = true;
     43  while (wakeup_count_ == 0) {
     44    if (!first_pass) MaybeBecomeIdle();
     45    // No wakeups available, time to wait.
     46    if (!t.has_timeout()) {
     47      cv_.wait(lock);
     48    } else {
     49      auto wait_result = t.SupportsSteadyClock() && t.is_relative_timeout()
     50                             ? cv_.wait_for(lock, t.ToChronoDuration())
     51                             : cv_.wait_until(lock, t.ToChronoTimePoint());
     52      if (wait_result == std::cv_status::timeout) {
     53        --waiter_count_;
     54        return false;
     55      }
     56    }
     57    first_pass = false;
     58  }
     59 
     60  // Consume a wakeup and we're done.
     61  --wakeup_count_;
     62  --waiter_count_;
     63  return true;
     64 }
     65 
     66 void StdcppWaiter::Post() {
     67  std::lock_guard<std::mutex> lock(mu_);
     68  ++wakeup_count_;
     69  InternalCondVarPoke();
     70 }
     71 
     72 void StdcppWaiter::Poke() {
     73  std::lock_guard<std::mutex> lock(mu_);
     74  InternalCondVarPoke();
     75 }
     76 
     77 void StdcppWaiter::InternalCondVarPoke() {
     78  if (waiter_count_ != 0) {
     79    cv_.notify_one();
     80  }
     81 }
     82 
     83 }  // namespace synchronization_internal
     84 ABSL_NAMESPACE_END
     85 }  // namespace absl
     86 
     87 #endif  // ABSL_INTERNAL_HAVE_STDCPP_WAITER