~ubuntu-branches/ubuntu/breezy/aqsis/breezy

« back to all changes in this revision

Viewing changes to boost/libs/thread/src/threadmon.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Will Newton
  • Date: 2004-12-07 20:06:49 UTC
  • Revision ID: james.westby@ubuntu.com-20041207200649-fccswkrvp4oc8lmn
Tags: upstream-0.9.3
ImportĀ upstreamĀ versionĀ 0.9.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2001-2003
 
2
// William E. Kempf
 
3
//
 
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.
 
11
 
 
12
#include <boost/config.hpp>
 
13
 
 
14
#if defined(BOOST_HAS_WINTHREADS)
 
15
 
 
16
#if defined(BOOST_THREAD_BUILD_DLL)
 
17
 
 
18
#include <boost/thread/detail/threadmon.hpp>
 
19
 
 
20
#define WIN32_LEAN_AND_MEAN  // Exclude rarely-used stuff from Windows headers
 
21
#include <windows.h>
 
22
 
 
23
#ifdef BOOST_MSVC
 
24
#   pragma warning(disable : 4786)
 
25
#endif
 
26
 
 
27
#include <list>
 
28
#include <set>
 
29
#include <algorithm>
 
30
 
 
31
typedef void (__cdecl * handler)(void);
 
32
typedef std::list<handler> exit_handlers;
 
33
typedef std::set<exit_handlers*> registered_handlers;
 
34
 
 
35
namespace
 
36
{
 
37
CRITICAL_SECTION cs;
 
38
DWORD key;
 
39
registered_handlers registry;
 
40
}
 
41
 
 
42
#if defined(__BORLANDC__)
 
43
#define DllMain DllEntryPoint
 
44
#endif
 
45
 
 
46
extern "C"
 
47
BOOL WINAPI DllMain(HANDLE /*module*/, DWORD reason, LPVOID)
 
48
{
 
49
    switch (reason)
 
50
    {
 
51
    case DLL_PROCESS_ATTACH:
 
52
        InitializeCriticalSection(&cs);
 
53
        key = TlsAlloc();
 
54
        break;
 
55
    case DLL_THREAD_ATTACH:
 
56
        break;
 
57
    case DLL_THREAD_DETACH:
 
58
    {
 
59
        // Call the thread's exit handlers.
 
60
        exit_handlers* handlers =
 
61
            static_cast<exit_handlers*>(TlsGetValue(key));
 
62
        if (handlers)
 
63
        {
 
64
            for (exit_handlers::iterator it = handlers->begin();
 
65
                 it != handlers->end(); ++it)
 
66
            {
 
67
                (*it)();
 
68
            }
 
69
 
 
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);
 
75
            delete handlers;
 
76
        }
 
77
    }
 
78
    break;
 
79
    case DLL_PROCESS_DETACH:
 
80
    {
 
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));
 
87
        if (handlers)
 
88
        {
 
89
            for (exit_handlers::iterator it = handlers->begin();
 
90
                 it != handlers->end(); ++it)
 
91
            {
 
92
                (*it)();
 
93
            }
 
94
        }
 
95
 
 
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
 
99
        // here.
 
100
        EnterCriticalSection(&cs);
 
101
        for (registered_handlers::iterator it = registry.begin();
 
102
             it != registry.end(); ++it)
 
103
        {
 
104
            delete (*it);
 
105
        }
 
106
        LeaveCriticalSection(&cs);
 
107
        DeleteCriticalSection(&cs);
 
108
        TlsFree(key);
 
109
    }
 
110
    break;
 
111
    }
 
112
    return TRUE;
 
113
}
 
114
 
 
115
extern "C" BOOST_THREAD_DECL int on_thread_exit(void (__cdecl * func)(void))
 
116
{
 
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));
 
120
    if (!handlers)
 
121
    {
 
122
        try
 
123
        {
 
124
            handlers = new exit_handlers;
 
125
            // Handle broken implementations of operator new that don't throw.
 
126
            if (!handlers)
 
127
                return -1;
 
128
        }
 
129
        catch (...)
 
130
        {
 
131
            return -1;
 
132
        }
 
133
 
 
134
        // Attempt to set a TLS value for the new handlers.
 
135
        if (!TlsSetValue(key, handlers))
 
136
        {
 
137
            delete handlers;
 
138
            return -1;
 
139
        }
 
140
 
 
141
        // Attempt to register this new handler so that memory can be properly
 
142
        // cleaned up.
 
143
        try
 
144
        {
 
145
            EnterCriticalSection(&cs);
 
146
            registry.insert(handlers);
 
147
            LeaveCriticalSection(&cs);
 
148
        }
 
149
        catch (...)
 
150
        {
 
151
            LeaveCriticalSection(&cs);
 
152
            delete handlers;
 
153
            return -1;
 
154
        }
 
155
    }
 
156
 
 
157
    // Attempt to add the handler to the list of exit handlers. If it's been
 
158
    // previously added just report success and exit.
 
159
    try
 
160
    {
 
161
        handlers->push_front(func);
 
162
    }
 
163
    catch (...)
 
164
    {
 
165
        return -1;
 
166
    }
 
167
 
 
168
    return 0;
 
169
}
 
170
 
 
171
#endif // BOOST_THREAD_BUILD_DLL
 
172
 
 
173
#endif // BOOST_HAS_WINTHREADS