11#ifndef BOOST_LEAF_CONFIG_TLS_ARRAY_HPP_INCLUDED
22#define BOOST_LEAF_CONFIG_TLS_ARRAY_HPP_INCLUDED
33
4- // Copyright 2018-2024 Emil Dotchevski and Reverge Studios, Inc.
4+ // Copyright 2018-2025 Emil Dotchevski and Reverge Studios, Inc.
55// Distributed under the Boost Software License, Version 1.0. (See accompanying
66// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
77
88// Copyright (c) 2022 Khalil Estell
99
10- // LEAF requires thread local storage support for pointers and for uin32_t values.
11-
12- // This header implements thread local storage for pointers and for unsigned int
13- // values for platforms that support thread local pointers by index.
10+ // This header implements the TLS API specified in tls.hpp for platforms that
11+ // provide TLS by indexing an array (this is typical for embedded platforms).
12+ // The array is accessed via user-defined functions.
1413
1514namespace boost { namespace leaf {
1615
@@ -26,6 +25,7 @@ namespace tls
2625
2726// //////////////////////////////////////
2827
28+ #include < atomic>
2929#include < limits>
3030#include < cstdint>
3131#include < type_traits>
@@ -55,16 +55,22 @@ namespace boost { namespace leaf {
5555namespace detail
5656{
5757 using atomic_unsigned_int = std::atomic<unsigned int >;
58- }
5958
60- namespace tls
61- {
59+ template <class =void >
60+ struct BOOST_LEAF_SYMBOL_VISIBLE id_factory
61+ {
62+ static atomic_unsigned_int counter;
63+ };
64+
65+ template <class T >
66+ atomic_unsigned_int id_factory<T>::counter(1 );
67+
6268 template <class =void >
6369 class BOOST_LEAF_SYMBOL_VISIBLE index_counter
6470 {
6571 static int c_;
6672
67- static BOOST_LEAF_CFG_TLS_INDEX_TYPE next_ () noexcept
73+ BOOST_LEAF_ALWAYS_INLINE static BOOST_LEAF_CFG_TLS_INDEX_TYPE next_ () noexcept
6874 {
6975 int idx = ++c_;
7076 BOOST_LEAF_ASSERT (idx > (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX + 1 ));
@@ -75,76 +81,88 @@ namespace tls
7581 public:
7682
7783 template <class T >
78- static BOOST_LEAF_CFG_TLS_INDEX_TYPE next () noexcept
84+ BOOST_LEAF_ALWAYS_INLINE static BOOST_LEAF_CFG_TLS_INDEX_TYPE next () noexcept
7985 {
80- return next_ (); // Set breakpoint here to monitor TLS index allocation for T.
86+ return next_ ();
8187 }
8288 };
8389
90+ template <class T >
91+ int index_counter<T>::c_ = BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX + 1 ;
92+
8493 template <class T >
8594 struct BOOST_LEAF_SYMBOL_VISIBLE tls_index
8695 {
8796 static BOOST_LEAF_CFG_TLS_INDEX_TYPE idx;
8897 };
8998
99+ template <class T >
100+ BOOST_LEAF_CFG_TLS_INDEX_TYPE tls_index<T>::idx = BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX + 1 ;
101+
90102 template <class T >
91103 struct BOOST_LEAF_SYMBOL_VISIBLE alloc_tls_index
92104 {
93105 static BOOST_LEAF_CFG_TLS_INDEX_TYPE const idx;
94106 };
95107
96108 template <class T >
97- int index_counter<T>::c_ = BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX + 1 ;
109+ BOOST_LEAF_CFG_TLS_INDEX_TYPE const alloc_tls_index<T>::idx = tls_index<T>::idx = index_counter<>::next<T>();
110+ }
98111
99- template <class T >
100- BOOST_LEAF_CFG_TLS_INDEX_TYPE tls_index<T>::idx = BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX + 1 ;
112+ } }
101113
102- template <class T >
103- BOOST_LEAF_CFG_TLS_INDEX_TYPE const alloc_tls_index<T>::idx = tls_index<T>::idx = index_counter<>::next<T>();
114+ // //////////////////////////////////////
104115
105- // //////////////////////////////////////
116+ namespace boost { namespace leaf {
106117
107- template <class T >
108- T * read_ptr () noexcept
118+ namespace tls
119+ {
120+ BOOST_LEAF_ALWAYS_INLINE unsigned generate_next_error_id () noexcept
109121 {
110- int tls_idx = tls_index<T>::idx;
111- if ( tls_idx == (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX + 1 ) )
112- return nullptr ;
113- --tls_idx;
114- return reinterpret_cast <T *>(read_void_ptr (tls_idx));
122+ unsigned id = (detail::id_factory<>::counter += 4 );
123+ BOOST_LEAF_ASSERT ((id&3 ) == 1 );
124+ return id;
125+ }
126+
127+ BOOST_LEAF_ALWAYS_INLINE void write_current_error_id ( unsigned x ) noexcept
128+ {
129+ static_assert (sizeof (std::intptr_t ) >= sizeof (unsigned ), " Incompatible tls_array implementation" );
130+ write_void_ptr (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX, (void *) (std::intptr_t ) x);
131+ }
132+
133+ BOOST_LEAF_ALWAYS_INLINE unsigned read_current_error_id () noexcept
134+ {
135+ static_assert (sizeof (std::intptr_t ) >= sizeof (unsigned ), " Incompatible tls_array implementation" );
136+ return (unsigned ) (std::intptr_t ) read_void_ptr (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX);
115137 }
116138
117139 template <class T >
118- void alloc_write_ptr ( T * p ) noexcept
140+ BOOST_LEAF_ALWAYS_INLINE void write_ptr_alloc ( T * p )
119141 {
120- int tls_idx = alloc_tls_index<T>::idx;
142+ int tls_idx = detail:: alloc_tls_index<T>::idx;
121143 --tls_idx;
122144 write_void_ptr (tls_idx, p);
123145 BOOST_LEAF_ASSERT (read_void_ptr (tls_idx) == p);
124146 }
125147
126148 template <class T >
127- void write_ptr ( T * p ) noexcept
149+ BOOST_LEAF_ALWAYS_INLINE void write_ptr ( T * p ) noexcept
128150 {
129- int tls_idx = tls_index<T>::idx;
151+ int tls_idx = detail:: tls_index<T>::idx;
130152 BOOST_LEAF_ASSERT (tls_idx != (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX + 1 ));
131153 --tls_idx;
132154 write_void_ptr (tls_idx, p);
133155 BOOST_LEAF_ASSERT (read_void_ptr (tls_idx) == p);
134156 }
135157
136- // //////////////////////////////////////
137-
138- inline unsigned read_current_error_id () noexcept
139- {
140- static_assert (sizeof (std::intptr_t ) >= sizeof (unsigned ), " Incompatible tls_array implementation" );
141- return (unsigned ) (std::intptr_t ) read_void_ptr (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX);
142- }
143-
144- inline void write_current_error_id ( unsigned x ) noexcept
158+ template <class T >
159+ BOOST_LEAF_ALWAYS_INLINE T * read_ptr () noexcept
145160 {
146- static_assert (sizeof (std::intptr_t ) >= sizeof (unsigned ), " Incompatible tls_array implementation" );
147- write_void_ptr (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX, (void *) (std::intptr_t ) x);
161+ int tls_idx = detail::tls_index<T>::idx;
162+ if ( tls_idx == (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX + 1 ) )
163+ return nullptr ;
164+ --tls_idx;
165+ return reinterpret_cast <T *>(read_void_ptr (tls_idx));
148166 }
149167}
150168
0 commit comments