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