Skip to content

Commit e9690b3

Browse files
committed
compile-time type hashing for tls_win32.hpp
1 parent 5c04fb7 commit e9690b3

File tree

1 file changed

+51
-39
lines changed

1 file changed

+51
-39
lines changed

include/boost/leaf/config/tls_win32.hpp

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <atomic>
1313
#include <stdexcept>
1414
#include <cstring>
15-
#include <string_view>
1615
#ifdef min
1716
# undef min
1817
#endif
@@ -36,6 +35,43 @@ namespace detail
3635
{
3736
using atomic_unsigned_int = std::atomic<unsigned int>;
3837

38+
template <int N, int I>
39+
struct cpp11_hash_step
40+
{
41+
BOOST_LEAF_ALWAYS_INLINE constexpr static std::uint32_t compute(char const (&str)[N], std::uint32_t hash) noexcept
42+
{
43+
return cpp11_hash_step<N, I - 1>::compute(str, (hash ^ static_cast<std::uint32_t>(str[I])) * 16777619u);
44+
}
45+
};
46+
47+
template <int N>
48+
struct cpp11_hash_step<N, -1>
49+
{
50+
BOOST_LEAF_ALWAYS_INLINE constexpr static std::uint32_t compute(char const (&)[N], std::uint32_t hash) noexcept
51+
{
52+
return hash;
53+
}
54+
};
55+
56+
template <int N>
57+
BOOST_LEAF_ALWAYS_INLINE constexpr std::uint32_t cpp11_hash_string(char const (&str)[N]) noexcept
58+
{
59+
return cpp11_hash_step<N, N - 2>::compute(str, 2166136261u); // str[N-2] is the last character before the \0.
60+
}
61+
}
62+
63+
namespace n
64+
{
65+
template <class T>
66+
BOOST_LEAF_ALWAYS_INLINE constexpr std::uint32_t h() noexcept
67+
{
68+
return detail::cpp11_hash_string(BOOST_LEAF_PRETTY_FUNCTION);
69+
}
70+
}
71+
72+
namespace detail
73+
{
74+
3975
class slot_map
4076
{
4177
slot_map(slot_map const &) = delete;
@@ -79,25 +115,9 @@ namespace detail
79115
}
80116
};
81117

82-
struct cstring_hash
83-
{
84-
std::size_t operator()(char const * s) const noexcept
85-
{
86-
return std::hash<std::string_view>{}(s);
87-
}
88-
};
89-
90-
struct cstring_equal
91-
{
92-
bool operator()(char const * a, char const * b) const noexcept
93-
{
94-
return a == b || std::strcmp(a, b) == 0;
95-
}
96-
};
97-
98118
tls_slot_index const error_id_slot_;
99119
mutable CRITICAL_SECTION cs_;
100-
std::unordered_map<char const *, tls_slot_index, cstring_hash, cstring_equal> map_;
120+
std::unordered_map<std::uint32_t, tls_slot_index> map_;
101121

102122
public:
103123

@@ -111,19 +131,19 @@ namespace detail
111131
DeleteCriticalSection(&cs_);
112132
}
113133

114-
DWORD check(char const * type_name) const noexcept
134+
DWORD check(std::uint32_t type_hash) const noexcept
115135
{
116136
EnterCriticalSection(&cs_);
117-
auto it = map_.find(type_name);
137+
auto it = map_.find(type_hash);
118138
DWORD idx = (it != map_.end()) ? it->second.get() : TLS_OUT_OF_INDEXES;
119139
LeaveCriticalSection(&cs_);
120140
return idx;
121141
}
122142

123-
DWORD get(char const * type_name)
143+
DWORD get(std::uint32_t type_hash)
124144
{
125145
EnterCriticalSection(&cs_);
126-
DWORD idx = map_[type_name].get();
146+
DWORD idx = map_[type_hash].get();
127147
LeaveCriticalSection(&cs_);
128148
BOOST_LEAF_ASSERT(idx != TLS_OUT_OF_INDEXES);
129149
return idx;
@@ -214,61 +234,53 @@ namespace detail
214234
PIMAGE_TLS_CALLBACK p_tls_callback __attribute__((section(".CRT$XLB"))) = tls_callback;
215235
#endif
216236

217-
inline DWORD check_tls_slot_for_type_name(char const * type_name) noexcept
237+
inline DWORD check_tls_slot_for_type_hash(std::uint32_t type_hash) noexcept
218238
{
219-
BOOST_LEAF_ASSERT(type_name && *type_name);
220239
slot_map const * sm = global_slot_map<>::ptr;
221240
BOOST_LEAF_ASSERT(sm);
222-
DWORD idx = sm->check(type_name);
241+
DWORD idx = sm->check(type_hash);
223242
return idx;
224243
}
225244

226-
inline DWORD get_existing_tls_slot_for_type_name(char const * type_name) noexcept
245+
inline DWORD get_existing_tls_slot_for_type_hash(std::uint32_t type_hash) noexcept
227246
{
228-
BOOST_LEAF_ASSERT(type_name && *type_name);
229247
slot_map const * sm = global_slot_map<>::ptr;
230248
BOOST_LEAF_ASSERT(sm);
231-
DWORD idx = sm->check(type_name);
249+
DWORD idx = sm->check(type_hash);
232250
BOOST_LEAF_ASSERT(idx != TLS_OUT_OF_INDEXES);
233251
return idx;
234252
}
235253

236-
inline DWORD get_tls_slot_for_type_name(char const * type_name)
254+
inline DWORD get_tls_slot_for_type_hash(std::uint32_t type_hash)
237255
{
238-
BOOST_LEAF_ASSERT(type_name && *type_name);
239256
slot_map * sm = global_slot_map<>::ptr;
240257
BOOST_LEAF_ASSERT(sm);
241-
DWORD idx = sm->get(type_name);
258+
DWORD idx = sm->get(type_hash);
242259
BOOST_LEAF_ASSERT(idx != TLS_OUT_OF_INDEXES);
243260
return idx;
244261
}
245262

246-
template <class>
247-
struct t_
248-
{
249-
};
250-
251263
template<class T>
252264
DWORD check_tls_index() noexcept
253265
{
254266
thread_local DWORD cached_idx = TLS_OUT_OF_INDEXES;
255267
if (cached_idx == TLS_OUT_OF_INDEXES)
256-
cached_idx = check_tls_slot_for_type_name(typeid(t_<T>).name());
268+
cached_idx = check_tls_slot_for_type_hash(n::h<T>());
257269
return cached_idx;
258270
}
259271

260272
template<class T>
261273
DWORD get_existing_tls_index() noexcept
262274
{
263-
thread_local DWORD const cached_idx = get_existing_tls_slot_for_type_name(typeid(t_<T>).name());
275+
thread_local DWORD const cached_idx = get_existing_tls_slot_for_type_hash(n::h<T>());
264276
BOOST_LEAF_ASSERT(cached_idx != TLS_OUT_OF_INDEXES);
265277
return cached_idx;
266278
}
267279

268280
template<class T>
269281
DWORD get_tls_index()
270282
{
271-
thread_local DWORD const cached_idx = get_tls_slot_for_type_name(typeid(t_<T>).name());
283+
thread_local DWORD const cached_idx = get_tls_slot_for_type_hash(n::h<T>());
272284
BOOST_LEAF_ASSERT(cached_idx != TLS_OUT_OF_INDEXES);
273285
return cached_idx;
274286
}

0 commit comments

Comments
 (0)