| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- /////////////////////////////////////////////////////////////////////////////
- // Name: wx/thrimpl.cpp
- // Purpose: common part of wxThread Implementations
- // Author: Vadim Zeitlin
- // Modified by:
- // Created: 04.06.02 (extracted from src/*/thread.cpp files)
- // Copyright: (c) Vadim Zeitlin (2002)
- // Licence: wxWindows licence
- /////////////////////////////////////////////////////////////////////////////
- // this file is supposed to be included only by the various thread.cpp
- // ----------------------------------------------------------------------------
- // wxMutex
- // ----------------------------------------------------------------------------
- wxMutex::wxMutex(wxMutexType mutexType)
- {
- m_internal = new wxMutexInternal(mutexType);
- if ( !m_internal->IsOk() )
- {
- delete m_internal;
- m_internal = NULL;
- }
- }
- wxMutex::~wxMutex()
- {
- delete m_internal;
- }
- bool wxMutex::IsOk() const
- {
- return m_internal != NULL;
- }
- wxMutexError wxMutex::Lock()
- {
- wxCHECK_MSG( m_internal, wxMUTEX_INVALID,
- wxT("wxMutex::Lock(): not initialized") );
- return m_internal->Lock();
- }
- wxMutexError wxMutex::LockTimeout(unsigned long ms)
- {
- wxCHECK_MSG( m_internal, wxMUTEX_INVALID,
- wxT("wxMutex::Lock(): not initialized") );
- return m_internal->Lock(ms);
- }
- wxMutexError wxMutex::TryLock()
- {
- wxCHECK_MSG( m_internal, wxMUTEX_INVALID,
- wxT("wxMutex::TryLock(): not initialized") );
- return m_internal->TryLock();
- }
- wxMutexError wxMutex::Unlock()
- {
- wxCHECK_MSG( m_internal, wxMUTEX_INVALID,
- wxT("wxMutex::Unlock(): not initialized") );
- return m_internal->Unlock();
- }
- // --------------------------------------------------------------------------
- // wxConditionInternal
- // --------------------------------------------------------------------------
- // Win32 and OS/2 don't have explicit support for the POSIX condition
- // variables and their events/event semaphores have quite different semantics,
- // so we reimplement the conditions from scratch using the mutexes and
- // semaphores
- #if defined(__WINDOWS__) || defined(__OS2__) || defined(__EMX__)
- class wxConditionInternal
- {
- public:
- wxConditionInternal(wxMutex& mutex);
- bool IsOk() const { return m_mutex.IsOk() && m_semaphore.IsOk(); }
- wxCondError Wait();
- wxCondError WaitTimeout(unsigned long milliseconds);
- wxCondError Signal();
- wxCondError Broadcast();
- private:
- // the number of threads currently waiting for this condition
- LONG m_numWaiters;
- // the critical section protecting m_numWaiters
- wxCriticalSection m_csWaiters;
- wxMutex& m_mutex;
- wxSemaphore m_semaphore;
- wxDECLARE_NO_COPY_CLASS(wxConditionInternal);
- };
- wxConditionInternal::wxConditionInternal(wxMutex& mutex)
- : m_mutex(mutex)
- {
- // another thread can't access it until we return from ctor, so no need to
- // protect access to m_numWaiters here
- m_numWaiters = 0;
- }
- wxCondError wxConditionInternal::Wait()
- {
- // increment the number of waiters
- {
- wxCriticalSectionLocker lock(m_csWaiters);
- m_numWaiters++;
- }
- m_mutex.Unlock();
- // after unlocking the mutex other threads may Signal() us, but it is ok
- // now as we had already incremented m_numWaiters so Signal() will post the
- // semaphore and decrement m_numWaiters back even if it is called before we
- // start to Wait()
- const wxSemaError err = m_semaphore.Wait();
- m_mutex.Lock();
- if ( err == wxSEMA_NO_ERROR )
- {
- // m_numWaiters was decremented by Signal()
- return wxCOND_NO_ERROR;
- }
- // but in case of an error we need to do it manually
- {
- wxCriticalSectionLocker lock(m_csWaiters);
- m_numWaiters--;
- }
- return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR;
- }
- wxCondError wxConditionInternal::WaitTimeout(unsigned long milliseconds)
- {
- {
- wxCriticalSectionLocker lock(m_csWaiters);
- m_numWaiters++;
- }
- m_mutex.Unlock();
- wxSemaError err = m_semaphore.WaitTimeout(milliseconds);
- m_mutex.Lock();
- if ( err == wxSEMA_NO_ERROR )
- return wxCOND_NO_ERROR;
- if ( err == wxSEMA_TIMEOUT )
- {
- // a potential race condition exists here: it happens when a waiting
- // thread times out but doesn't have time to decrement m_numWaiters yet
- // before Signal() is called in another thread
- //
- // to handle this particular case, check the semaphore again after
- // acquiring m_csWaiters lock -- this will catch the signals missed
- // during this window
- wxCriticalSectionLocker lock(m_csWaiters);
- err = m_semaphore.WaitTimeout(0);
- if ( err == wxSEMA_NO_ERROR )
- return wxCOND_NO_ERROR;
- // we need to decrement m_numWaiters ourselves as it wasn't done by
- // Signal()
- m_numWaiters--;
- return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR;
- }
- // undo m_numWaiters++ above in case of an error
- {
- wxCriticalSectionLocker lock(m_csWaiters);
- m_numWaiters--;
- }
- return wxCOND_MISC_ERROR;
- }
- wxCondError wxConditionInternal::Signal()
- {
- wxCriticalSectionLocker lock(m_csWaiters);
- if ( m_numWaiters > 0 )
- {
- // increment the semaphore by 1
- if ( m_semaphore.Post() != wxSEMA_NO_ERROR )
- return wxCOND_MISC_ERROR;
- m_numWaiters--;
- }
- return wxCOND_NO_ERROR;
- }
- wxCondError wxConditionInternal::Broadcast()
- {
- wxCriticalSectionLocker lock(m_csWaiters);
- while ( m_numWaiters > 0 )
- {
- if ( m_semaphore.Post() != wxSEMA_NO_ERROR )
- return wxCOND_MISC_ERROR;
- m_numWaiters--;
- }
- return wxCOND_NO_ERROR;
- }
- #endif // __WINDOWS__ || __OS2__ || __EMX__
- // ----------------------------------------------------------------------------
- // wxCondition
- // ----------------------------------------------------------------------------
- wxCondition::wxCondition(wxMutex& mutex)
- {
- m_internal = new wxConditionInternal(mutex);
- if ( !m_internal->IsOk() )
- {
- delete m_internal;
- m_internal = NULL;
- }
- }
- wxCondition::~wxCondition()
- {
- delete m_internal;
- }
- bool wxCondition::IsOk() const
- {
- return m_internal != NULL;
- }
- wxCondError wxCondition::Wait()
- {
- wxCHECK_MSG( m_internal, wxCOND_INVALID,
- wxT("wxCondition::Wait(): not initialized") );
- return m_internal->Wait();
- }
- wxCondError wxCondition::WaitTimeout(unsigned long milliseconds)
- {
- wxCHECK_MSG( m_internal, wxCOND_INVALID,
- wxT("wxCondition::Wait(): not initialized") );
- return m_internal->WaitTimeout(milliseconds);
- }
- wxCondError wxCondition::Signal()
- {
- wxCHECK_MSG( m_internal, wxCOND_INVALID,
- wxT("wxCondition::Signal(): not initialized") );
- return m_internal->Signal();
- }
- wxCondError wxCondition::Broadcast()
- {
- wxCHECK_MSG( m_internal, wxCOND_INVALID,
- wxT("wxCondition::Broadcast(): not initialized") );
- return m_internal->Broadcast();
- }
- // --------------------------------------------------------------------------
- // wxSemaphore
- // --------------------------------------------------------------------------
- wxSemaphore::wxSemaphore(int initialcount, int maxcount)
- {
- m_internal = new wxSemaphoreInternal( initialcount, maxcount );
- if ( !m_internal->IsOk() )
- {
- delete m_internal;
- m_internal = NULL;
- }
- }
- wxSemaphore::~wxSemaphore()
- {
- delete m_internal;
- }
- bool wxSemaphore::IsOk() const
- {
- return m_internal != NULL;
- }
- wxSemaError wxSemaphore::Wait()
- {
- wxCHECK_MSG( m_internal, wxSEMA_INVALID,
- wxT("wxSemaphore::Wait(): not initialized") );
- return m_internal->Wait();
- }
- wxSemaError wxSemaphore::TryWait()
- {
- wxCHECK_MSG( m_internal, wxSEMA_INVALID,
- wxT("wxSemaphore::TryWait(): not initialized") );
- return m_internal->TryWait();
- }
- wxSemaError wxSemaphore::WaitTimeout(unsigned long milliseconds)
- {
- wxCHECK_MSG( m_internal, wxSEMA_INVALID,
- wxT("wxSemaphore::WaitTimeout(): not initialized") );
- return m_internal->WaitTimeout(milliseconds);
- }
- wxSemaError wxSemaphore::Post()
- {
- wxCHECK_MSG( m_internal, wxSEMA_INVALID,
- wxT("wxSemaphore::Post(): not initialized") );
- return m_internal->Post();
- }
- // ----------------------------------------------------------------------------
- // wxThread
- // ----------------------------------------------------------------------------
- #include "wx/utils.h"
- #include "wx/private/threadinfo.h"
- #include "wx/scopeguard.h"
- void wxThread::Sleep(unsigned long milliseconds)
- {
- wxMilliSleep(milliseconds);
- }
- void *wxThread::CallEntry()
- {
- wxON_BLOCK_EXIT0(wxThreadSpecificInfo::ThreadCleanUp);
- return Entry();
- }
|