]> git.saurik.com Git - wxWidgets.git/blame_incremental - include/wx/thrimpl.cpp
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / include / wx / thrimpl.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: wx/thrimpl.cpp
3// Purpose: common part of wxThread Implementations
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 04.06.02 (extracted from src/*/thread.cpp files)
7// Copyright: (c) Vadim Zeitlin (2002)
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// this file is supposed to be included only by the various thread.cpp
12
13// ----------------------------------------------------------------------------
14// wxMutex
15// ----------------------------------------------------------------------------
16
17wxMutex::wxMutex(wxMutexType mutexType)
18{
19 m_internal = new wxMutexInternal(mutexType);
20
21 if ( !m_internal->IsOk() )
22 {
23 delete m_internal;
24 m_internal = NULL;
25 }
26}
27
28wxMutex::~wxMutex()
29{
30 delete m_internal;
31}
32
33bool wxMutex::IsOk() const
34{
35 return m_internal != NULL;
36}
37
38wxMutexError wxMutex::Lock()
39{
40 wxCHECK_MSG( m_internal, wxMUTEX_INVALID,
41 wxT("wxMutex::Lock(): not initialized") );
42
43 return m_internal->Lock();
44}
45
46wxMutexError wxMutex::LockTimeout(unsigned long ms)
47{
48 wxCHECK_MSG( m_internal, wxMUTEX_INVALID,
49 wxT("wxMutex::Lock(): not initialized") );
50
51 return m_internal->Lock(ms);
52}
53
54wxMutexError wxMutex::TryLock()
55{
56 wxCHECK_MSG( m_internal, wxMUTEX_INVALID,
57 wxT("wxMutex::TryLock(): not initialized") );
58
59 return m_internal->TryLock();
60}
61
62wxMutexError wxMutex::Unlock()
63{
64 wxCHECK_MSG( m_internal, wxMUTEX_INVALID,
65 wxT("wxMutex::Unlock(): not initialized") );
66
67 return m_internal->Unlock();
68}
69
70// --------------------------------------------------------------------------
71// wxConditionInternal
72// --------------------------------------------------------------------------
73
74// Win32 and OS/2 don't have explicit support for the POSIX condition
75// variables and their events/event semaphores have quite different semantics,
76// so we reimplement the conditions from scratch using the mutexes and
77// semaphores
78#if defined(__WINDOWS__) || defined(__OS2__) || defined(__EMX__)
79
80class wxConditionInternal
81{
82public:
83 wxConditionInternal(wxMutex& mutex);
84
85 bool IsOk() const { return m_mutex.IsOk() && m_semaphore.IsOk(); }
86
87 wxCondError Wait();
88 wxCondError WaitTimeout(unsigned long milliseconds);
89
90 wxCondError Signal();
91 wxCondError Broadcast();
92
93private:
94 // the number of threads currently waiting for this condition
95 LONG m_numWaiters;
96
97 // the critical section protecting m_numWaiters
98 wxCriticalSection m_csWaiters;
99
100 wxMutex& m_mutex;
101 wxSemaphore m_semaphore;
102
103 wxDECLARE_NO_COPY_CLASS(wxConditionInternal);
104};
105
106wxConditionInternal::wxConditionInternal(wxMutex& mutex)
107 : m_mutex(mutex)
108{
109 // another thread can't access it until we return from ctor, so no need to
110 // protect access to m_numWaiters here
111 m_numWaiters = 0;
112}
113
114wxCondError wxConditionInternal::Wait()
115{
116 // increment the number of waiters
117 {
118 wxCriticalSectionLocker lock(m_csWaiters);
119 m_numWaiters++;
120 }
121
122 m_mutex.Unlock();
123
124 // after unlocking the mutex other threads may Signal() us, but it is ok
125 // now as we had already incremented m_numWaiters so Signal() will post the
126 // semaphore and decrement m_numWaiters back even if it is called before we
127 // start to Wait()
128 const wxSemaError err = m_semaphore.Wait();
129
130 m_mutex.Lock();
131
132 if ( err == wxSEMA_NO_ERROR )
133 {
134 // m_numWaiters was decremented by Signal()
135 return wxCOND_NO_ERROR;
136 }
137
138 // but in case of an error we need to do it manually
139 {
140 wxCriticalSectionLocker lock(m_csWaiters);
141 m_numWaiters--;
142 }
143
144 return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR;
145}
146
147wxCondError wxConditionInternal::WaitTimeout(unsigned long milliseconds)
148{
149 {
150 wxCriticalSectionLocker lock(m_csWaiters);
151 m_numWaiters++;
152 }
153
154 m_mutex.Unlock();
155
156 wxSemaError err = m_semaphore.WaitTimeout(milliseconds);
157
158 m_mutex.Lock();
159
160 if ( err == wxSEMA_NO_ERROR )
161 return wxCOND_NO_ERROR;
162
163 if ( err == wxSEMA_TIMEOUT )
164 {
165 // a potential race condition exists here: it happens when a waiting
166 // thread times out but doesn't have time to decrement m_numWaiters yet
167 // before Signal() is called in another thread
168 //
169 // to handle this particular case, check the semaphore again after
170 // acquiring m_csWaiters lock -- this will catch the signals missed
171 // during this window
172 wxCriticalSectionLocker lock(m_csWaiters);
173
174 err = m_semaphore.WaitTimeout(0);
175 if ( err == wxSEMA_NO_ERROR )
176 return wxCOND_NO_ERROR;
177
178 // we need to decrement m_numWaiters ourselves as it wasn't done by
179 // Signal()
180 m_numWaiters--;
181
182 return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR;
183 }
184
185 // undo m_numWaiters++ above in case of an error
186 {
187 wxCriticalSectionLocker lock(m_csWaiters);
188 m_numWaiters--;
189 }
190
191 return wxCOND_MISC_ERROR;
192}
193
194wxCondError wxConditionInternal::Signal()
195{
196 wxCriticalSectionLocker lock(m_csWaiters);
197
198 if ( m_numWaiters > 0 )
199 {
200 // increment the semaphore by 1
201 if ( m_semaphore.Post() != wxSEMA_NO_ERROR )
202 return wxCOND_MISC_ERROR;
203
204 m_numWaiters--;
205 }
206
207 return wxCOND_NO_ERROR;
208}
209
210wxCondError wxConditionInternal::Broadcast()
211{
212 wxCriticalSectionLocker lock(m_csWaiters);
213
214 while ( m_numWaiters > 0 )
215 {
216 if ( m_semaphore.Post() != wxSEMA_NO_ERROR )
217 return wxCOND_MISC_ERROR;
218
219 m_numWaiters--;
220 }
221
222 return wxCOND_NO_ERROR;
223}
224
225#endif // __WINDOWS__ || __OS2__ || __EMX__
226
227// ----------------------------------------------------------------------------
228// wxCondition
229// ----------------------------------------------------------------------------
230
231wxCondition::wxCondition(wxMutex& mutex)
232{
233 m_internal = new wxConditionInternal(mutex);
234
235 if ( !m_internal->IsOk() )
236 {
237 delete m_internal;
238 m_internal = NULL;
239 }
240}
241
242wxCondition::~wxCondition()
243{
244 delete m_internal;
245}
246
247bool wxCondition::IsOk() const
248{
249 return m_internal != NULL;
250}
251
252wxCondError wxCondition::Wait()
253{
254 wxCHECK_MSG( m_internal, wxCOND_INVALID,
255 wxT("wxCondition::Wait(): not initialized") );
256
257 return m_internal->Wait();
258}
259
260wxCondError wxCondition::WaitTimeout(unsigned long milliseconds)
261{
262 wxCHECK_MSG( m_internal, wxCOND_INVALID,
263 wxT("wxCondition::Wait(): not initialized") );
264
265 return m_internal->WaitTimeout(milliseconds);
266}
267
268wxCondError wxCondition::Signal()
269{
270 wxCHECK_MSG( m_internal, wxCOND_INVALID,
271 wxT("wxCondition::Signal(): not initialized") );
272
273 return m_internal->Signal();
274}
275
276wxCondError wxCondition::Broadcast()
277{
278 wxCHECK_MSG( m_internal, wxCOND_INVALID,
279 wxT("wxCondition::Broadcast(): not initialized") );
280
281 return m_internal->Broadcast();
282}
283
284// --------------------------------------------------------------------------
285// wxSemaphore
286// --------------------------------------------------------------------------
287
288wxSemaphore::wxSemaphore(int initialcount, int maxcount)
289{
290 m_internal = new wxSemaphoreInternal( initialcount, maxcount );
291 if ( !m_internal->IsOk() )
292 {
293 delete m_internal;
294 m_internal = NULL;
295 }
296}
297
298wxSemaphore::~wxSemaphore()
299{
300 delete m_internal;
301}
302
303bool wxSemaphore::IsOk() const
304{
305 return m_internal != NULL;
306}
307
308wxSemaError wxSemaphore::Wait()
309{
310 wxCHECK_MSG( m_internal, wxSEMA_INVALID,
311 wxT("wxSemaphore::Wait(): not initialized") );
312
313 return m_internal->Wait();
314}
315
316wxSemaError wxSemaphore::TryWait()
317{
318 wxCHECK_MSG( m_internal, wxSEMA_INVALID,
319 wxT("wxSemaphore::TryWait(): not initialized") );
320
321 return m_internal->TryWait();
322}
323
324wxSemaError wxSemaphore::WaitTimeout(unsigned long milliseconds)
325{
326 wxCHECK_MSG( m_internal, wxSEMA_INVALID,
327 wxT("wxSemaphore::WaitTimeout(): not initialized") );
328
329 return m_internal->WaitTimeout(milliseconds);
330}
331
332wxSemaError wxSemaphore::Post()
333{
334 wxCHECK_MSG( m_internal, wxSEMA_INVALID,
335 wxT("wxSemaphore::Post(): not initialized") );
336
337 return m_internal->Post();
338}
339
340// ----------------------------------------------------------------------------
341// wxThread
342// ----------------------------------------------------------------------------
343
344#include "wx/utils.h"
345#include "wx/private/threadinfo.h"
346#include "wx/scopeguard.h"
347
348void wxThread::Sleep(unsigned long milliseconds)
349{
350 wxMilliSleep(milliseconds);
351}
352
353void *wxThread::CallEntry()
354{
355 wxON_BLOCK_EXIT0(wxThreadSpecificInfo::ThreadCleanUp);
356 return Entry();
357}