libs/corosio/include/boost/corosio/detail/thread_local_ptr.hpp

100.0% Lines (5/5) 100.0% Functions (4/4) -% Branches (0/0)
libs/corosio/include/boost/corosio/detail/thread_local_ptr.hpp
Line Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/corosio
8 //
9
10 #ifndef BOOST_COROSIO_DETAIL_THREAD_LOCAL_PTR_HPP
11 #define BOOST_COROSIO_DETAIL_THREAD_LOCAL_PTR_HPP
12
13 #include <boost/corosio/detail/config.hpp>
14
15 #include <type_traits>
16
17 // Detect thread-local storage mechanism
18 #if !defined(BOOST_COROSIO_TLS_KEYWORD)
19 # if defined(_MSC_VER)
20 # define BOOST_COROSIO_TLS_KEYWORD __declspec(thread)
21 # elif defined(__GNUC__) || defined(__clang__)
22 # define BOOST_COROSIO_TLS_KEYWORD __thread
23 # endif
24 #endif
25
26 namespace boost::corosio::detail {
27
28 /** A thread-local pointer.
29
30 This class provides thread-local storage for a pointer to T.
31 Each thread has its own independent pointer value, initially
32 nullptr. The user is responsible for managing the lifetime
33 of the pointed-to objects.
34
35 The storage is static per type T. All instances of
36 `thread_local_ptr<T>` share the same underlying slot.
37
38 The implementation uses the most efficient available mechanism:
39 1. Compiler keyword (__declspec(thread) or __thread) - enforces POD
40 2. C++11 thread_local (fallback)
41
42 @tparam T The pointed-to type.
43
44 @par Declaration
45
46 Typically declared at namespace or class scope. The object
47 is stateless, so local variables work but are redundant.
48
49 @code
50 // Recommended: namespace scope
51 namespace {
52 thread_local_ptr<session> current_session;
53 }
54
55 // Also works: static class member
56 class server {
57 static thread_local_ptr<request> current_request_;
58 };
59
60 // Works but unusual: local variable (still accesses static storage)
61 void foo() {
62 thread_local_ptr<context> ctx; // same slot on every call
63 ctx = new context();
64 }
65 @endcode
66
67 @note The user is responsible for deleting pointed-to objects
68 before threads exit to avoid memory leaks.
69 */
70 template<class T>
71 class thread_local_ptr;
72
73 //------------------------------------------------------------------------------
74
75 #if defined(BOOST_COROSIO_TLS_KEYWORD)
76
77 // Use compiler-specific keyword (__declspec(thread) or __thread)
78 // Most efficient: static linkage, no dynamic init, enforces POD
79
80 template<class T>
81 class thread_local_ptr
82 {
83 static BOOST_COROSIO_TLS_KEYWORD T* ptr_;
84
85 public:
86 thread_local_ptr() = default;
87 ~thread_local_ptr() = default;
88
89 thread_local_ptr(thread_local_ptr const&) = delete;
90 thread_local_ptr& operator=(thread_local_ptr const&) = delete;
91
92 /** Return the pointer for this thread.
93
94 @return The stored pointer, or nullptr if not set.
95 */
96 T*
97 603819 get() const noexcept
98 {
99 603819 return ptr_;
100 }
101
102 /** Set the pointer for this thread.
103
104 @param p The pointer to store. The user manages its lifetime.
105 */
106 void
107 526 set(T* p) noexcept
108 {
109 526 ptr_ = p;
110 526 }
111
112 /** Dereference the stored pointer.
113
114 @pre get() != nullptr
115 */
116 T&
117 operator*() const noexcept
118 {
119 return *ptr_;
120 }
121
122 /** Member access through the stored pointer.
123
124 @pre get() != nullptr
125 */
126 T*
127 operator->() const noexcept
128 requires std::is_class_v<T>
129 {
130 return ptr_;
131 }
132
133 /** Assign a pointer value.
134
135 @param p The pointer to store.
136 @return The stored pointer.
137 */
138 T*
139 operator=(T* p) noexcept
140 {
141 ptr_ = p;
142 return p;
143 }
144 };
145
146 template<class T>
147 BOOST_COROSIO_TLS_KEYWORD T* thread_local_ptr<T>::ptr_ = nullptr;
148
149 //------------------------------------------------------------------------------
150
151 #else
152
153 // Use C++11 thread_local keyword (fallback)
154
155 template<class T>
156 class thread_local_ptr
157 {
158 static thread_local T* ptr_;
159
160 public:
161 thread_local_ptr() = default;
162 ~thread_local_ptr() = default;
163
164 thread_local_ptr(thread_local_ptr const&) = delete;
165 thread_local_ptr& operator=(thread_local_ptr const&) = delete;
166
167 T*
168 get() const noexcept
169 {
170 return ptr_;
171 }
172
173 void
174 set(T* p) noexcept
175 {
176 ptr_ = p;
177 }
178
179 T&
180 operator*() const noexcept
181 {
182 return *ptr_;
183 }
184
185 T*
186 operator->() const noexcept
187 requires std::is_class_v<T>
188 {
189 return ptr_;
190 }
191
192 T*
193 operator=(T* p) noexcept
194 {
195 ptr_ = p;
196 return p;
197 }
198 };
199
200 template<class T>
201 thread_local T* thread_local_ptr<T>::ptr_ = nullptr;
202
203 #endif
204
205 } // namespace boost::corosio::detail
206
207 #endif
208