1
// Copyright (C) 2001-2003
4
// Permission to use, copy, modify, distribute and sell this software
5
// and its documentation for any purpose is hereby granted without fee,
6
// provided that the above copyright notice appear in all copies and
7
// that both that copyright notice and this permission notice appear
8
// in supporting documentation. William E. Kempf makes no representations
9
// about the suitability of this software for any purpose.
10
// It is provided "as is" without express or implied warranty.
12
#include <boost/config.hpp>
14
#if defined(BOOST_HAS_WINTHREADS)
16
#if defined(BOOST_THREAD_BUILD_DLL)
18
#include <boost/thread/detail/threadmon.hpp>
20
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
24
# pragma warning(disable : 4786)
31
typedef void (__cdecl * handler)(void);
32
typedef std::list<handler> exit_handlers;
33
typedef std::set<exit_handlers*> registered_handlers;
39
registered_handlers registry;
42
#if defined(__BORLANDC__)
43
#define DllMain DllEntryPoint
47
BOOL WINAPI DllMain(HANDLE /*module*/, DWORD reason, LPVOID)
51
case DLL_PROCESS_ATTACH:
52
InitializeCriticalSection(&cs);
55
case DLL_THREAD_ATTACH:
57
case DLL_THREAD_DETACH:
59
// Call the thread's exit handlers.
60
exit_handlers* handlers =
61
static_cast<exit_handlers*>(TlsGetValue(key));
64
for (exit_handlers::iterator it = handlers->begin();
65
it != handlers->end(); ++it)
70
// Remove the exit handler list from the registered lists
71
// and then destroy it.
72
EnterCriticalSection(&cs);
73
registry.erase(handlers);
74
LeaveCriticalSection(&cs);
79
case DLL_PROCESS_DETACH:
81
// Assume the main thread is ending (call its handlers) and
82
// all other threads have already ended. If this DLL is
83
// loaded and unloaded dynamically at run time
84
// this is a bad assumption, but this is the best we can do.
85
exit_handlers* handlers =
86
static_cast<exit_handlers*>(TlsGetValue(key));
89
for (exit_handlers::iterator it = handlers->begin();
90
it != handlers->end(); ++it)
96
// Destroy any remaining exit handlers. Above we assumed
97
// there'd only be the main thread left, but to insure we
98
// don't get memory leaks we won't make that assumption
100
EnterCriticalSection(&cs);
101
for (registered_handlers::iterator it = registry.begin();
102
it != registry.end(); ++it)
106
LeaveCriticalSection(&cs);
107
DeleteCriticalSection(&cs);
115
extern "C" BOOST_THREAD_DECL int on_thread_exit(void (__cdecl * func)(void))
117
// Get the exit handlers for the current thread, creating and registering
118
// one if it doesn't exist.
119
exit_handlers* handlers = static_cast<exit_handlers*>(TlsGetValue(key));
124
handlers = new exit_handlers;
125
// Handle broken implementations of operator new that don't throw.
134
// Attempt to set a TLS value for the new handlers.
135
if (!TlsSetValue(key, handlers))
141
// Attempt to register this new handler so that memory can be properly
145
EnterCriticalSection(&cs);
146
registry.insert(handlers);
147
LeaveCriticalSection(&cs);
151
LeaveCriticalSection(&cs);
157
// Attempt to add the handler to the list of exit handlers. If it's been
158
// previously added just report success and exit.
161
handlers->push_front(func);
171
#endif // BOOST_THREAD_BUILD_DLL
173
#endif // BOOST_HAS_WINTHREADS