wxwidgets/include/wx/thrimpl.cpp
Vadim Zeitlin 4f4c5fcfdf Use nullptr instead of NULL in the code and documentation
This is a combination of running clang-tidy with modernize-use-nullptr
check for some ports (GTK, X11, OSX) and manual changes to the ports for
which it couldn't be used easily (MSW, DFB) and also manually updating
the docs.

Also replace NULL with null or nullptr in the comments as this is more
consistent with the use of nullptr in the code and makes it simpler to
grep for the remaining occurrences of NULL itself.

And also use null in the assert messages.

Only a few occurrences of "NULL" are still left in non-C files, mostly
corresponding to unclear comments or string output which it might not be
safe to change.
2022-10-18 01:25:25 +02:00

349 lines
8.5 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// 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 = nullptr;
}
}
wxMutex::~wxMutex()
{
delete m_internal;
}
bool wxMutex::IsOk() const
{
return m_internal != nullptr;
}
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 doesn't have explicit support for the POSIX condition
// variables and its events/event semaphores have quite different semantics,
// so we reimplement the conditions from scratch using the mutexes and
// semaphores
#if defined(__WINDOWS__)
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__
// ----------------------------------------------------------------------------
// wxCondition
// ----------------------------------------------------------------------------
wxCondition::wxCondition(wxMutex& mutex)
{
m_internal = new wxConditionInternal(mutex);
if ( !m_internal->IsOk() )
{
delete m_internal;
m_internal = nullptr;
}
}
wxCondition::~wxCondition()
{
delete m_internal;
}
bool wxCondition::IsOk() const
{
return m_internal != nullptr;
}
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 = nullptr;
}
}
wxSemaphore::~wxSemaphore()
{
delete m_internal;
}
bool wxSemaphore::IsOk() const
{
return m_internal != nullptr;
}
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"
void wxThread::Sleep(unsigned long milliseconds)
{
wxMilliSleep(milliseconds);
}