tor-browser

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

per_thread_sem.h (4897B)


      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 
     16 // PerThreadSem is a low-level synchronization primitive controlling the
     17 // runnability of a single thread, used internally by Mutex and CondVar.
     18 //
     19 // This is NOT a general-purpose synchronization mechanism, and should not be
     20 // used directly by applications.  Applications should use Mutex and CondVar.
     21 //
     22 // The semantics of PerThreadSem are the same as that of a counting semaphore.
     23 // Each thread maintains an abstract "count" value associated with its identity.
     24 
     25 #ifndef ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_
     26 #define ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_
     27 
     28 #include <atomic>
     29 
     30 #include "absl/base/internal/thread_identity.h"
     31 #include "absl/synchronization/internal/create_thread_identity.h"
     32 #include "absl/synchronization/internal/kernel_timeout.h"
     33 
     34 namespace absl {
     35 ABSL_NAMESPACE_BEGIN
     36 
     37 class Mutex;
     38 
     39 namespace synchronization_internal {
     40 
     41 class PerThreadSem {
     42 public:
     43  PerThreadSem() = delete;
     44  PerThreadSem(const PerThreadSem&) = delete;
     45  PerThreadSem& operator=(const PerThreadSem&) = delete;
     46 
     47  // Routine invoked periodically (once a second) by a background thread.
     48  // Has no effect on user-visible state.
     49  static void Tick(base_internal::ThreadIdentity* identity);
     50 
     51  // ---------------------------------------------------------------------------
     52  // Routines used by autosizing threadpools to detect when threads are
     53  // blocked.  Each thread has a counter pointer, initially zero.  If non-zero,
     54  // the implementation atomically increments the counter when it blocks on a
     55  // semaphore, a decrements it again when it wakes.  This allows a threadpool
     56  // to keep track of how many of its threads are blocked.
     57  // SetThreadBlockedCounter() should be used only by threadpool
     58  // implementations.  GetThreadBlockedCounter() should be used by modules that
     59  // block threads; if the pointer returned is non-zero, the location should be
     60  // incremented before the thread blocks, and decremented after it wakes.
     61  static void SetThreadBlockedCounter(std::atomic<int> *counter);
     62  static std::atomic<int> *GetThreadBlockedCounter();
     63 
     64 private:
     65  // Create the PerThreadSem associated with "identity".  Initializes count=0.
     66  // REQUIRES: May only be called by ThreadIdentity.
     67  static inline void Init(base_internal::ThreadIdentity* identity);
     68 
     69  // Increments "identity"'s count.
     70  static inline void Post(base_internal::ThreadIdentity* identity);
     71 
     72  // Waits until either our count > 0 or t has expired.
     73  // If count > 0, decrements count and returns true.  Otherwise returns false.
     74  // !t.has_timeout() => Wait(t) will return true.
     75  static inline bool Wait(KernelTimeout t);
     76 
     77  // Permitted callers.
     78  friend class PerThreadSemTest;
     79  friend class absl::Mutex;
     80  friend void OneTimeInitThreadIdentity(absl::base_internal::ThreadIdentity*);
     81 };
     82 
     83 }  // namespace synchronization_internal
     84 ABSL_NAMESPACE_END
     85 }  // namespace absl
     86 
     87 // In some build configurations we pass --detect-odr-violations to the
     88 // gold linker.  This causes it to flag weak symbol overrides as ODR
     89 // violations.  Because ODR only applies to C++ and not C,
     90 // --detect-odr-violations ignores symbols not mangled with C++ names.
     91 // By changing our extension points to be extern "C", we dodge this
     92 // check.
     93 extern "C" {
     94 void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemInit)(
     95    absl::base_internal::ThreadIdentity* identity);
     96 void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(
     97    absl::base_internal::ThreadIdentity* identity);
     98 bool ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(
     99    absl::synchronization_internal::KernelTimeout t);
    100 void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPoke)(
    101    absl::base_internal::ThreadIdentity* identity);
    102 }  // extern "C"
    103 
    104 void absl::synchronization_internal::PerThreadSem::Init(
    105    absl::base_internal::ThreadIdentity* identity) {
    106  ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemInit)(identity);
    107 }
    108 
    109 void absl::synchronization_internal::PerThreadSem::Post(
    110    absl::base_internal::ThreadIdentity* identity) {
    111  ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(identity);
    112 }
    113 
    114 bool absl::synchronization_internal::PerThreadSem::Wait(
    115    absl::synchronization_internal::KernelTimeout t) {
    116  return ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(t);
    117 }
    118 
    119 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_