1616
1717#include < atomic>
1818#include < unordered_map>
19- #include < typeinfo>
2019#include < cstdint>
20+ #include < new>
2121#include < stdexcept>
22- #include < cstdio>
2322#include < windows.h>
2423#ifdef min
2524# undef min
@@ -41,14 +40,93 @@ class win32_tls_error:
4140 }
4241};
4342
44- } }
43+ namespace detail
44+ {
45+ __declspec (noreturn) inline void raise_fail_fast (NTSTATUS status) noexcept
46+ {
47+ EXCEPTION_RECORD rec = {};
48+ rec.ExceptionCode = status;
49+ rec.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
50+ RaiseFailFastException (&rec, nullptr , 0 );
51+ BOOST_LEAF_UNREACHABLE;
52+ }
4553
46- // //////////////////////////////////////
54+ template <class T , class ... Args>
55+ T * heap_new (Args && ... args) noexcept
56+ {
57+ void * mem = HeapAlloc (GetProcessHeap (), 0 , sizeof (T));
58+ if (!mem)
59+ {
60+ raise_fail_fast (STATUS_NO_MEMORY);
61+ BOOST_LEAF_UNREACHABLE;
62+ }
63+ return new (mem) T (static_cast <Args &&>(args)...);
64+ }
4765
48- namespace boost { namespace leaf {
66+ template <class T >
67+ void heap_delete (T * p) noexcept
68+ {
69+ if (p)
70+ {
71+ p->~T ();
72+ BOOL r = HeapFree (GetProcessHeap (), 0 , p);
73+ BOOST_LEAF_ASSERT (r), (void ) r;
74+ }
75+ }
76+
77+ template <class T >
78+ class heap_allocator
79+ {
80+ public:
81+
82+ using value_type = T;
83+
84+ heap_allocator () noexcept = default ;
85+
86+ template <class U >
87+ heap_allocator (heap_allocator<U> const &) noexcept
88+ {
89+ }
90+
91+ T * allocate (std::size_t n) noexcept
92+ {
93+ if (void * p = HeapAlloc (GetProcessHeap (), 0 , n * sizeof (T)))
94+ return static_cast <T *>(p);
95+ raise_fail_fast (STATUS_NO_MEMORY);
96+ BOOST_LEAF_UNREACHABLE;
97+ }
98+
99+ void deallocate (T * p, std::size_t ) noexcept
100+ {
101+ BOOL r = HeapFree (GetProcessHeap (), 0 , p);
102+ BOOST_LEAF_ASSERT (r), (void ) r;
103+ }
104+
105+ friend bool operator ==(heap_allocator const &, heap_allocator const &) noexcept { return true ; }
106+ friend bool operator !=(heap_allocator const &, heap_allocator const &) noexcept { return false ; }
107+ };
108+
109+ class critical_section_lock
110+ {
111+ critical_section_lock (critical_section_lock const &) = delete ;
112+ critical_section_lock & operator =(critical_section_lock const &) = delete ;
113+
114+ CRITICAL_SECTION & cs_;
115+
116+ public:
117+
118+ explicit critical_section_lock (CRITICAL_SECTION & cs) noexcept :
119+ cs_(cs)
120+ {
121+ EnterCriticalSection (&cs_);
122+ }
123+
124+ ~critical_section_lock () noexcept
125+ {
126+ LeaveCriticalSection (&cs_);
127+ }
128+ };
49129
50- namespace detail
51- {
52130 using atomic_unsigned_int = std::atomic<unsigned int >;
53131
54132 template <int N, int I>
@@ -74,7 +152,7 @@ namespace detail
74152 {
75153 return cpp11_hash_step<N, N - 2 >::compute (str, 2166136261u ); // str[N-2] is the last character before the \0.
76154 }
77- }
155+ } // namespace detail
78156
79157namespace n
80158{
@@ -94,7 +172,7 @@ namespace detail
94172 }
95173}
96174
97- } }
175+ } } // namespace boost::leaf
98176
99177// //////////////////////////////////////
100178
@@ -107,13 +185,6 @@ namespace detail
107185 slot_map (slot_map const &) = delete ;
108186 slot_map & operator =(slot_map const &) = delete ;
109187
110- ~slot_map () noexcept
111- {
112- DeleteCriticalSection (&cs_);
113- BOOL r = CloseHandle (mapping_);
114- BOOST_LEAF_ASSERT (r), (void ) r;
115- }
116-
117188 class tls_slot_index
118189 {
119190 tls_slot_index (tls_slot_index const &) = delete ;
@@ -156,7 +227,12 @@ namespace detail
156227 HANDLE const mapping_;
157228 tls_slot_index const error_id_slot_;
158229 mutable CRITICAL_SECTION cs_;
159- std::unordered_map<std::uint32_t , tls_slot_index> map_;
230+ std::unordered_map<
231+ std::uint32_t ,
232+ tls_slot_index,
233+ std::hash<std::uint32_t >,
234+ std::equal_to<std::uint32_t >,
235+ heap_allocator<std::pair<std::uint32_t const , tls_slot_index>>> map_;
160236 atomic_unsigned_int error_id_storage_;
161237
162238 public:
@@ -170,6 +246,13 @@ namespace detail
170246 InitializeCriticalSection (&cs_);
171247 }
172248
249+ ~slot_map () noexcept
250+ {
251+ DeleteCriticalSection (&cs_);
252+ BOOL r = CloseHandle (mapping_);
253+ BOOST_LEAF_ASSERT (r), (void ) r;
254+ }
255+
173256 BOOST_LEAF_ALWAYS_INLINE void add_ref () noexcept
174257 {
175258 BOOST_LEAF_ASSERT (refcount_ >= 1 );
@@ -181,23 +264,20 @@ namespace detail
181264 --refcount_;
182265 BOOST_LEAF_ASSERT (refcount_ >= 0 );
183266 if (refcount_ == 0 )
184- delete this ;
267+ heap_delete ( this ) ;
185268 }
186269
187270 DWORD check (std::uint32_t type_hash) const noexcept
188271 {
189- EnterCriticalSection (& cs_);
272+ critical_section_lock lock ( cs_);
190273 auto it = map_.find (type_hash);
191- DWORD idx = (it != map_.end ()) ? it->second .get () : TLS_OUT_OF_INDEXES;
192- LeaveCriticalSection (&cs_);
193- return idx;
274+ return (it != map_.end ()) ? it->second .get () : TLS_OUT_OF_INDEXES;
194275 }
195276
196277 DWORD get (std::uint32_t type_hash)
197278 {
198- EnterCriticalSection (& cs_);
279+ critical_section_lock lock ( cs_);
199280 DWORD idx = map_[type_hash].get ();
200- LeaveCriticalSection (&cs_);
201281 BOOST_LEAF_ASSERT (idx != TLS_OUT_OF_INDEXES);
202282 return idx;
203283 }
@@ -220,7 +300,6 @@ namespace detail
220300
221301 static constexpr unsigned tls_failure_create_mapping = 0x01 ;
222302 static constexpr unsigned tls_failure_map_view = 0x02 ;
223- static constexpr unsigned tls_failure_slot_map = 0x04 ;
224303
225304 void * hinstance_;
226305 unsigned tls_failures_;
@@ -240,7 +319,6 @@ namespace detail
240319 BOOST_LEAF_ASSERT (hinstance_);
241320 BOOST_LEAF_ASSERT (!(tls_failures_ & tls_failure_create_mapping));
242321 BOOST_LEAF_ASSERT (!(tls_failures_ & tls_failure_map_view));
243- BOOST_LEAF_ASSERT (!(tls_failures_ & tls_failure_slot_map));
244322 BOOST_LEAF_ASSERT (sm_);
245323 return *sm_;
246324 }
@@ -250,16 +328,24 @@ namespace detail
250328 if (dwReason == DLL_PROCESS_ATTACH)
251329 {
252330 hinstance_ = hinstDLL;
253- char name[64 ];
254- int num_written = std::snprintf (name, sizeof (name), " Local\\ boost_leaf_tls_%lu" , GetCurrentProcessId ());
255- BOOST_LEAF_ASSERT (num_written >= 0 && num_written < int (sizeof (name))), (void ) num_written;
331+ char name[32 ] = " Local\\ boost_leaf_" ;
332+ {
333+ constexpr static char const hex[] = " 0123456789ABCDEF" ;
334+ DWORD pid = GetCurrentProcessId ();
335+ for (int i = 7 ; i >= 0 ; --i)
336+ {
337+ name[17 + i] = hex[pid & 0xf ];
338+ pid >>= 4 ;
339+ }
340+ name[25 ] = ' \0 ' ;
341+ }
256342 HANDLE mapping = CreateFileMappingA (INVALID_HANDLE_VALUE, nullptr , PAGE_READWRITE, 0 , sizeof (slot_map *), name);
343+ DWORD mapping_status = GetLastError ();
257344 if (!mapping)
258345 {
259346 tls_failures_ |= tls_failure_create_mapping;
260347 return ;
261348 }
262- DWORD mapping_status = GetLastError ();
263349 BOOST_LEAF_ASSERT (mapping_status == ERROR_ALREADY_EXISTS || mapping_status == ERROR_SUCCESS);
264350 bool is_first_module = (mapping_status == ERROR_SUCCESS);
265351 slot_map * * mapped_ptr = static_cast <slot_map * *>(MapViewOfFile (mapping, FILE_MAP_WRITE, 0 , 0 , sizeof (slot_map *)));
@@ -271,26 +357,7 @@ namespace detail
271357 return ;
272358 }
273359 if (is_first_module)
274- {
275- #ifndef BOOST_LEAF_NO_EXCEPTIONS
276- try
277- {
278- #endif
279- sm_ = *mapped_ptr = new slot_map (mapping);
280- #ifdef BOOST_LEAF_NO_EXCEPTIONS
281- if (!sm_)
282- #else
283- }
284- catch (...)
285- #endif
286- {
287- tls_failures_ |= tls_failure_slot_map;
288- EXCEPTION_RECORD rec = {};
289- rec.ExceptionCode = STATUS_NO_MEMORY;
290- rec.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
291- RaiseFailFastException (&rec, nullptr , 0 );
292- }
293- }
360+ sm_ = *mapped_ptr = heap_new<slot_map>(mapping);
294361 else
295362 {
296363 sm_ = *mapped_ptr;
0 commit comments