GCC Code Coverage Report


Directory: ./
File: libs/capy/include/boost/capy/core/thread_local_ptr.hpp
Date: 2026-01-15 20:40:20
Exec Total Coverage
Lines: 12 12 100.0%
Functions: 5 5 100.0%
Branches: 0 0 -%

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