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