Null check, don't blithely assume we have type info.
[dyninst.git] / common / dthread-win.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #include "common/src/dthread.h"
31 #include <assert.h>
32
33 DThread::DThread()
34 {
35 }
36
37 DThread::~DThread()
38 {
39 }
40
41 long DThread::self()
42 {
43         return ::GetCurrentThreadId();
44 }
45 bool DThread::spawn(DThread::initial_func_t func, void *param)
46 {
47         thrd = ::CreateThread(NULL, 0, func, param, 0, &tid);
48         live = (thrd != INVALID_HANDLE_VALUE);
49         return live;
50 }
51 bool DThread::join()
52 {
53         assert(live && self() != id());
54         ::WaitForSingleObject(thrd, INFINITE);
55         return true;
56 }
57
58 long DThread::id()
59 {
60         return tid;
61 }
62
63
64 Mutex::Mutex(bool recursive)
65 {
66         mutex = ::CreateMutex(NULL, false, NULL);
67 }
68
69 Mutex::~Mutex()
70 {
71         ::CloseHandle(mutex);
72 }
73
74 bool Mutex::lock()
75 {
76 //      fprintf(stderr, "[%d]: Mutex::lock() waiting for 0x%lx\n", ::GetCurrentThreadId(), mutex);
77         bool ok = (::WaitForSingleObject(mutex, INFINITE) == WAIT_OBJECT_0);
78 //      fprintf(stderr, "[%d]: Mutex::lock() holding 0x%lx\n", ::GetCurrentThreadId(), mutex);
79         return ok;
80 }
81
82 bool Mutex::unlock()
83 {
84 //      fprintf(stderr, "[%d]: Mutex::unlock() for 0x%lx\n", ::GetCurrentThreadId(), mutex);
85         bool ok = (::ReleaseMutex(mutex) != 0);
86         if(!ok) {
87                 fprintf(stderr, "Failed to release mutex: %d\n", ::GetLastError());
88         }
89         return ok;
90 }
91
92 CondVar::CondVar(Mutex *m) :
93         numWaiting(0),
94         was_broadcast(false),
95         mutex(m),
96         created_mutex(false)
97 {
98         if(mutex == NULL)
99         {
100                 mutex = new Mutex();
101                 created_mutex = true;
102         }
103         wait_sema = ::CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
104         ::InitializeCriticalSection(&numWaitingLock);
105         wait_done = ::CreateEvent(NULL, false, false, NULL);
106 }
107 CondVar::~CondVar()
108 {
109         if(created_mutex)
110         {
111                 delete mutex;
112         }
113         ::CloseHandle(wait_sema);
114         ::CloseHandle(wait_done);
115         ::DeleteCriticalSection(&numWaitingLock);
116 }
117
118 bool CondVar::unlock()
119 {
120         bool ret = mutex->unlock();
121         return ret;
122 }
123 bool CondVar::lock()
124 {
125         bool ret = mutex->lock();
126         return ret;     
127 }
128 bool CondVar::signal()
129 {
130         ::EnterCriticalSection(&numWaitingLock);
131         bool waitingThreads = (numWaiting > 0);
132         ::LeaveCriticalSection(&numWaitingLock);
133         if(waitingThreads)
134         {
135                 long prev_count;
136                 ::ReleaseSemaphore(wait_sema, 1, &prev_count);
137 //              fprintf(stderr, "[%d]: CondVar::signal() signaled 0x%lx, prev_count = %d\n", ::GetCurrentThreadId(), wait_sema, prev_count);
138         }
139         return true;
140 }
141 bool CondVar::broadcast()
142 {
143         ::EnterCriticalSection(&numWaitingLock);
144         bool waitingThreads = (numWaiting > 0);
145         was_broadcast = true;
146         if(waitingThreads)
147         {
148                 long prev_count;
149                 ::ReleaseSemaphore(wait_sema, numWaiting, &prev_count);
150 //              fprintf(stderr, "[%d]: CondVar::broadcast() signaled 0x%lx, prev_count = %d\n", ::GetCurrentThreadId(), wait_sema, prev_count);
151                 ::LeaveCriticalSection(&numWaitingLock);
152                 ::WaitForSingleObject(wait_done, INFINITE);
153                 was_broadcast = false;
154         }
155         else
156         {
157                 ::LeaveCriticalSection(&numWaitingLock);
158         }
159         return true;
160 }
161 bool CondVar::wait()
162 {
163         ::EnterCriticalSection(&numWaitingLock);
164         numWaiting++;
165         ::LeaveCriticalSection(&numWaitingLock);
166 //      fprintf(stderr, "[%d]: CondVar::wait() signalling for 0x%lx, waiting for 0x%lx\n", ::GetCurrentThreadId(), mutex->mutex, wait_sema);
167         unsigned long result = ::SignalObjectAndWait(mutex->mutex, wait_sema, INFINITE, FALSE);
168         assert(result != WAIT_TIMEOUT);
169         ::EnterCriticalSection(&numWaitingLock);
170         numWaiting--;
171         bool last_waiter = (was_broadcast && (numWaiting == 0));
172         ::LeaveCriticalSection(&numWaitingLock);
173         if(last_waiter)
174         {
175 //              fprintf(stderr, "[%d]: CondVar::wait() waiting for 0x%lx, signaling 0x%lx\n", ::GetCurrentThreadId(), mutex->mutex, wait_done);
176                 result = ::SignalObjectAndWait(wait_done, mutex->mutex, INFINITE, FALSE);
177                 assert(result != WAIT_TIMEOUT);
178         }
179         else
180         {
181                 ::WaitForSingleObject(mutex->mutex, INFINITE);
182         }
183         return true;
184 }