xref: /aosp_15_r20/external/cronet/base/threading/thread_local.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker // WARNING: Thread local storage is a bit tricky to get right. Please make sure
6*6777b538SAndroid Build Coastguard Worker // that this is really the proper solution for what you're trying to achieve.
7*6777b538SAndroid Build Coastguard Worker // Don't prematurely optimize, most likely you can just use a Lock.
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #ifndef BASE_THREADING_THREAD_LOCAL_H_
10*6777b538SAndroid Build Coastguard Worker #define BASE_THREADING_THREAD_LOCAL_H_
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include <memory>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "base/dcheck_is_on.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_local_internal.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_local_storage.h"
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker namespace base {
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker // `thread_local` is only allowed for trivially-destructible types (see
22*6777b538SAndroid Build Coastguard Worker // //styleguide/c++/c++.md#thread_local-variables). This class provides
23*6777b538SAndroid Build Coastguard Worker // thread-scoped management of non-trivially-destructible types. Pointers handed
24*6777b538SAndroid Build Coastguard Worker // to it are owned and automatically deleted during their associated thread's
25*6777b538SAndroid Build Coastguard Worker // exit phase (or when replaced if Set() is invoked multiple times on the same
26*6777b538SAndroid Build Coastguard Worker // thread).
27*6777b538SAndroid Build Coastguard Worker //
28*6777b538SAndroid Build Coastguard Worker // The ThreadLocalOwnedPointer instance itself can only be destroyed when no
29*6777b538SAndroid Build Coastguard Worker // threads, other than the one it is destroyed on, have remaining state set in
30*6777b538SAndroid Build Coastguard Worker // it. Typically this means that ThreadLocalOwnedPointer instances are held in
31*6777b538SAndroid Build Coastguard Worker // static storage or at the very least only recycled in the single-threaded
32*6777b538SAndroid Build Coastguard Worker // phase between tests in the same process.
33*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
34*6777b538SAndroid Build Coastguard Worker template <typename T>
35*6777b538SAndroid Build Coastguard Worker using ThreadLocalOwnedPointer = internal::CheckedThreadLocalOwnedPointer<T>;
36*6777b538SAndroid Build Coastguard Worker #else   // DCHECK_IS_ON()
37*6777b538SAndroid Build Coastguard Worker template <typename T>
38*6777b538SAndroid Build Coastguard Worker class ThreadLocalOwnedPointer {
39*6777b538SAndroid Build Coastguard Worker  public:
40*6777b538SAndroid Build Coastguard Worker   ThreadLocalOwnedPointer() = default;
41*6777b538SAndroid Build Coastguard Worker 
42*6777b538SAndroid Build Coastguard Worker   ThreadLocalOwnedPointer(const ThreadLocalOwnedPointer&) = delete;
43*6777b538SAndroid Build Coastguard Worker   ThreadLocalOwnedPointer& operator=(const ThreadLocalOwnedPointer&) = delete;
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker   ~ThreadLocalOwnedPointer() {
46*6777b538SAndroid Build Coastguard Worker     // Assume that this thread is the only one with potential state left. This
47*6777b538SAndroid Build Coastguard Worker     // is verified in ~CheckedThreadLocalOwnedPointer().
48*6777b538SAndroid Build Coastguard Worker     Set(nullptr);
49*6777b538SAndroid Build Coastguard Worker   }
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker   T* Get() const { return static_cast<T*>(slot_.Get()); }
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker   // Sets a new value, returns the old.
54*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<T> Set(std::unique_ptr<T> ptr) {
55*6777b538SAndroid Build Coastguard Worker     auto existing = WrapUnique(Get());
56*6777b538SAndroid Build Coastguard Worker     slot_.Set(const_cast<void*>(static_cast<const void*>(ptr.release())));
57*6777b538SAndroid Build Coastguard Worker     return existing;
58*6777b538SAndroid Build Coastguard Worker   }
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker   T& operator*() { return *Get(); }
61*6777b538SAndroid Build Coastguard Worker 
62*6777b538SAndroid Build Coastguard Worker  private:
63*6777b538SAndroid Build Coastguard Worker   static void DeleteTlsPtr(void* ptr) { delete static_cast<T*>(ptr); }
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker   ThreadLocalStorage::Slot slot_{&DeleteTlsPtr};
66*6777b538SAndroid Build Coastguard Worker };
67*6777b538SAndroid Build Coastguard Worker #endif  // DCHECK_IS_ON()
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker }  // namespace base
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker #endif  // BASE_THREADING_THREAD_LOCAL_H_
72