tor-browser

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

thread_local_storage.h (6389B)


      1 // Copyright 2012 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_THREADING_THREAD_LOCAL_STORAGE_H_
      6 #define BASE_THREADING_THREAD_LOCAL_STORAGE_H_
      7 
      8 #include <stdint.h>
      9 
     10 #include "base/base_export.h"
     11 #include "build/build_config.h"
     12 
     13 #if BUILDFLAG(IS_WIN)
     14 #include "base/win/windows_types.h"
     15 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
     16 #include <pthread.h>
     17 #endif
     18 
     19 namespace base {
     20 
     21 class SamplingHeapProfiler;
     22 
     23 namespace debug {
     24 class GlobalActivityTracker;
     25 }  // namespace debug
     26 
     27 namespace trace_event {
     28 class MallocDumpProvider;
     29 }  // namespace trace_event
     30 
     31 namespace internal {
     32 
     33 class ThreadLocalStorageTestInternal;
     34 
     35 // WARNING: You should *NOT* use this class directly.
     36 // PlatformThreadLocalStorage is a low-level abstraction of the OS's TLS
     37 // interface. Instead, you should use one of the following:
     38 // * ThreadLocalOwnedPointer (from thread_local.h) for unique_ptrs.
     39 // * ThreadLocalStorage::StaticSlot/Slot for more direct control of the slot.
     40 class BASE_EXPORT PlatformThreadLocalStorage {
     41 public:
     42 #if BUILDFLAG(IS_WIN)
     43  typedef unsigned long TLSKey;
     44  enum : unsigned { TLS_KEY_OUT_OF_INDEXES = TLS_OUT_OF_INDEXES };
     45 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
     46  typedef pthread_key_t TLSKey;
     47  // The following is a "reserved key" which is used in our generic Chromium
     48  // ThreadLocalStorage implementation.  We expect that an OS will not return
     49  // such a key, but if it is returned (i.e., the OS tries to allocate it) we
     50  // will just request another key.
     51  enum { TLS_KEY_OUT_OF_INDEXES = 0x7FFFFFFF };
     52 #endif
     53 
     54  // The following methods need to be supported on each OS platform, so that
     55  // the Chromium ThreadLocalStore functionality can be constructed.
     56  // Chromium will use these methods to acquire a single OS slot, and then use
     57  // that to support a much larger number of Chromium slots (independent of the
     58  // OS restrictions).
     59  // The following returns true if it successfully is able to return an OS
     60  // key in |key|.
     61  static bool AllocTLS(TLSKey* key);
     62  // Note: FreeTLS() doesn't have to be called, it is fine with this leak, OS
     63  // might not reuse released slot, you might just reset the TLS value with
     64  // SetTLSValue().
     65  static void FreeTLS(TLSKey key);
     66  static void SetTLSValue(TLSKey key, void* value);
     67  static void* GetTLSValue(TLSKey key) {
     68 #if BUILDFLAG(IS_WIN)
     69    return TlsGetValue(key);
     70 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
     71    return pthread_getspecific(key);
     72 #endif
     73  }
     74 
     75  // Each platform (OS implementation) is required to call this method on each
     76  // terminating thread when the thread is about to terminate.  This method
     77  // will then call all registered destructors for slots in Chromium
     78  // ThreadLocalStorage, until there are no slot values remaining as having
     79  // been set on this thread.
     80  // Destructors may end up being called multiple times on a terminating
     81  // thread, as other destructors may re-set slots that were previously
     82  // destroyed.
     83 #if BUILDFLAG(IS_WIN)
     84  // Since Windows which doesn't support TLS destructor, the implementation
     85  // should use GetTLSValue() to retrieve the value of TLS slot.
     86  static void OnThreadExit();
     87 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
     88  // |Value| is the data stored in TLS slot, The implementation can't use
     89  // GetTLSValue() to retrieve the value of slot as it has already been reset
     90  // in Posix.
     91  static void OnThreadExit(void* value);
     92 #endif
     93 };
     94 
     95 }  // namespace internal
     96 
     97 // Wrapper for thread local storage.  This class doesn't do much except provide
     98 // an API for portability.
     99 class BASE_EXPORT ThreadLocalStorage {
    100 public:
    101  // Prototype for the TLS destructor function, which can be optionally used to
    102  // cleanup thread local storage on thread exit.  'value' is the data that is
    103  // stored in thread local storage.
    104  typedef void (*TLSDestructorFunc)(void* value);
    105 
    106  // A key representing one value stored in TLS. Use as a class member or a
    107  // local variable. If you need a static storage duration variable, use the
    108  // following pattern with a NoDestructor<Slot>:
    109  // void MyDestructorFunc(void* value);
    110  // ThreadLocalStorage::Slot& ImportantContentTLS() {
    111  //   static NoDestructor<ThreadLocalStorage::Slot> important_content_tls(
    112  //       &MyDestructorFunc);
    113  //   return *important_content_tls;
    114  // }
    115  class BASE_EXPORT Slot final {
    116   public:
    117    // |destructor| is a pointer to a function to perform per-thread cleanup of
    118    // this object.  If set to nullptr, no cleanup is done for this TLS slot.
    119    explicit Slot(TLSDestructorFunc destructor = nullptr);
    120 
    121    Slot(const Slot&) = delete;
    122    Slot& operator=(const Slot&) = delete;
    123 
    124    // If a destructor was set for this slot, removes the destructor so that
    125    // remaining threads exiting will not free data.
    126    ~Slot();
    127 
    128    // Get the thread-local value stored in slot 'slot'.
    129    // Values are guaranteed to initially be zero.
    130    void* Get() const;
    131 
    132    // Set the thread-local value stored in slot 'slot' to
    133    // value 'value'.
    134    void Set(void* value);
    135 
    136   private:
    137    void Initialize(TLSDestructorFunc destructor);
    138    void Free();
    139 
    140    static constexpr size_t kInvalidSlotValue = static_cast<size_t>(-1);
    141    size_t slot_ = kInvalidSlotValue;
    142    uint32_t version_ = 0;
    143  };
    144 
    145  ThreadLocalStorage(const ThreadLocalStorage&) = delete;
    146  ThreadLocalStorage& operator=(const ThreadLocalStorage&) = delete;
    147 
    148 private:
    149  // In most cases, most callers should not need access to HasBeenDestroyed().
    150  // If you are working in code that runs during thread destruction, contact the
    151  // base OWNERs for advice and then make a friend request.
    152  //
    153  // Returns |true| if Chrome's implementation of TLS is being or has been
    154  // destroyed during thread destruction. Attempting to call Slot::Get() during
    155  // destruction is disallowed and will hit a DCHECK. Any code that relies on
    156  // TLS during thread destruction must first check this method before calling
    157  // Slot::Get().
    158  friend class SequenceCheckerImpl;
    159  friend class SamplingHeapProfiler;
    160  friend class ThreadCheckerImpl;
    161  friend class internal::ThreadLocalStorageTestInternal;
    162  friend class trace_event::MallocDumpProvider;
    163  friend class debug::GlobalActivityTracker;
    164  static bool HasBeenDestroyed();
    165 };
    166 
    167 }  // namespace base
    168 
    169 #endif  // BASE_THREADING_THREAD_LOCAL_STORAGE_H_