GCC Code Coverage Report


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