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