Skip to content

Commit 94d05b0

Browse files
committed
TLS tweaks
1 parent 9f0d0f8 commit 94d05b0

File tree

8 files changed

+302
-176
lines changed

8 files changed

+302
-176
lines changed

include/boost/leaf/config.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@
9494
# error BOOST_LEAF_CFG_WIN32 must be 0 or 1 or 2.
9595
#endif
9696

97+
#if BOOST_LEAF_CFG_WIN32 && !defined(_WIN32)
98+
# warning "Ignoring BOOST_LEAF_CFG_WIN32 because _WIN32 is not defined"
99+
# define BOOST_LEAF_CFG_WIN32 0
100+
#endif
101+
97102
#if BOOST_LEAF_CFG_GNUC_STMTEXPR != 0 && BOOST_LEAF_CFG_GNUC_STMTEXPR != 1
98103
# error BOOST_LEAF_CFG_GNUC_STMTEXPR must be 0 or 1.
99104
#endif

include/boost/leaf/config/tls.hpp

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,66 @@
11
#ifndef BOOST_LEAF_CONFIG_TLS_HPP_INCLUDED
22
#define BOOST_LEAF_CONFIG_TLS_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

8-
#include <atomic>
8+
namespace boost { namespace leaf {
9+
10+
// The following declarations specify the thread local storage API used
11+
// internally by LEAF. To port LEAF to a new TLS API, provide definitions for
12+
// each of these functions.
13+
namespace tls
14+
{
15+
// Generate the next unique error_id. Values start at 1 and increment by 4.
16+
// Error ids must be unique for the lifetime of the process, and this
17+
// function must be thread-safe. Postcondition: (id & 3) == 1 && id != 0.
18+
//
19+
// This function may not fail.
20+
unsigned generate_next_error_id() noexcept;
21+
22+
// Write x to the TLS for the current error_id. The initial value for each
23+
// thread must be 0. Precondition: x == 0 or (x & 3) == 1.
24+
//
25+
// This function may not fail.
26+
void write_current_error_id( unsigned x ) noexcept;
27+
28+
// Read the current error_id for this thread. The initial value for each
29+
// thread must be 0.
30+
//
31+
// This function may not fail.
32+
unsigned read_current_error_id() noexcept;
33+
34+
// Write p to the TLS for T. The TLS may be allocated dynamically on the
35+
// first call to write_ptr_alloc<T>, but subsequent calls must reuse the
36+
// same TLS.
37+
//
38+
// This function may throw on allocation failure.
39+
template <class T>
40+
void write_ptr_alloc( T * p );
41+
42+
// Write p to the TLS previously allocated for T by a successful call to
43+
// write_ptr_alloc<T>.
44+
//
45+
// This function may not fail.
46+
template <class T>
47+
void write_ptr( T * p ) noexcept;
48+
49+
// Read the T * value previously written in the TLS for T. Returns nullptr
50+
// if TLS for T has not yet been allocated.
51+
//
52+
// This function may not fail.
53+
template <class T>
54+
T * read_ptr() noexcept;
55+
}
56+
57+
} }
958

1059
#if defined(BOOST_LEAF_TLS_FREERTOS)
1160
# include <boost/leaf/config/tls_freertos.hpp>
61+
# ifndef BOOST_LEAF_USE_TLS_ARRAY
62+
# define BOOST_LEAF_USE_TLS_ARRAY
63+
# endif
1264
#endif
1365

1466
#ifndef BOOST_LEAF_USE_TLS_ARRAY
@@ -23,40 +75,14 @@
2375
# endif
2476
#endif
2577

26-
#if BOOST_LEAF_CFG_WIN32 == 2
78+
#if defined BOOST_LEAF_USE_TLS_ARRAY
79+
# include <boost/leaf/config/tls_array.hpp>
80+
#elif BOOST_LEAF_CFG_WIN32 == 2
2781
# include <boost/leaf/config/tls_win32.hpp>
82+
#elif defined(BOOST_LEAF_NO_THREADS)
83+
# include <boost/leaf/config/tls_globals.hpp>
2884
#else
29-
# if defined BOOST_LEAF_USE_TLS_ARRAY
30-
# include <boost/leaf/config/tls_array.hpp>
31-
# elif defined(BOOST_LEAF_NO_THREADS)
32-
# include <boost/leaf/config/tls_globals.hpp>
33-
# else
34-
# include <boost/leaf/config/tls_cpp11.hpp>
35-
# endif
36-
37-
namespace boost { namespace leaf {
38-
39-
namespace detail
40-
{
41-
template <class=void>
42-
struct BOOST_LEAF_SYMBOL_VISIBLE id_factory
43-
{
44-
static atomic_unsigned_int counter;
45-
};
46-
47-
template <class T>
48-
atomic_unsigned_int id_factory<T>::counter(1);
49-
50-
inline unsigned generate_next_error_id() noexcept
51-
{
52-
unsigned id = (id_factory<>::counter += 4);
53-
BOOST_LEAF_ASSERT((id&3) == 1);
54-
return id;
55-
}
56-
}
57-
58-
} }
59-
85+
# include <boost/leaf/config/tls_cpp11.hpp>
6086
#endif
6187

6288
#endif // BOOST_LEAF_CONFIG_TLS_HPP_INCLUDED

include/boost/leaf/config/tls_array.hpp

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
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

1514
namespace 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 {
5555
namespace 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

Comments
 (0)