Add wxCRITSEC_DEFAULT and NON_RECURSIVE styles, updated and restored wxThread and related docs
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55465 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
aeab14d443
commit
3ad41c280f
@ -218,13 +218,22 @@ private:
|
|||||||
#define wxCRITSECT_INLINE
|
#define wxCRITSECT_INLINE
|
||||||
#endif // MSW/!MSW
|
#endif // MSW/!MSW
|
||||||
|
|
||||||
|
enum wxCriticalSectionType
|
||||||
|
{
|
||||||
|
// recursive critical section
|
||||||
|
wxCRITSEC_DEFAULT,
|
||||||
|
|
||||||
|
// non-recursive critical section
|
||||||
|
wxCRITSEC_NON_RECURSIVE
|
||||||
|
};
|
||||||
|
|
||||||
// you should consider wxCriticalSectionLocker whenever possible instead of
|
// you should consider wxCriticalSectionLocker whenever possible instead of
|
||||||
// directly working with wxCriticalSection class - it is safer
|
// directly working with wxCriticalSection class - it is safer
|
||||||
class WXDLLIMPEXP_BASE wxCriticalSection
|
class WXDLLIMPEXP_BASE wxCriticalSection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// ctor & dtor
|
// ctor & dtor
|
||||||
wxCRITSECT_INLINE wxCriticalSection();
|
wxCRITSECT_INLINE wxCriticalSection( wxCriticalSectionType critSecType = wxCRITSEC_DEFAULT );
|
||||||
wxCRITSECT_INLINE ~wxCriticalSection();
|
wxCRITSECT_INLINE ~wxCriticalSection();
|
||||||
// enter the section (the same as locking a mutex)
|
// enter the section (the same as locking a mutex)
|
||||||
wxCRITSECT_INLINE void Enter();
|
wxCRITSECT_INLINE void Enter();
|
||||||
@ -266,7 +275,8 @@ private:
|
|||||||
|
|
||||||
#if wxCRITSECT_IS_MUTEX && !defined(__WXMAC__)
|
#if wxCRITSECT_IS_MUTEX && !defined(__WXMAC__)
|
||||||
// implement wxCriticalSection using mutexes
|
// implement wxCriticalSection using mutexes
|
||||||
inline wxCriticalSection::wxCriticalSection() { }
|
inline wxCriticalSection::wxCriticalSection( wxCriticalSectionType critSecType )
|
||||||
|
: m_mutex( critSecType == wxCRITSEC_DEFAULT ? wxMUTEX_RECURSIVE : wxMUTEX_DEFAULT ) { }
|
||||||
inline wxCriticalSection::~wxCriticalSection() { }
|
inline wxCriticalSection::~wxCriticalSection() { }
|
||||||
|
|
||||||
inline void wxCriticalSection::Enter() { (void)m_mutex.Lock(); }
|
inline void wxCriticalSection::Enter() { (void)m_mutex.Lock(); }
|
||||||
|
@ -250,24 +250,33 @@ public:
|
|||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Possible critical section types
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum wxCriticalSectionType
|
||||||
|
{
|
||||||
|
wxCRITSEC_DEFAULT,
|
||||||
|
/** Recursive critical section under both Windows and Unix */
|
||||||
|
|
||||||
|
wxCRITSEC_NON_RECURSIVE
|
||||||
|
/** Non-recursive critical section under Unix, recursive under Windows */
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@class wxCriticalSection
|
@class wxCriticalSection
|
||||||
|
|
||||||
A critical section object is used for exactly the same purpose as
|
A critical section object is used for exactly the same purpose as
|
||||||
mutexes(). The only difference is that under Windows platform
|
a wxMutex. The only difference is that under Windows platform
|
||||||
critical sections are only visible inside one process, while mutexes may be
|
critical sections are only visible inside one process, while mutexes may be
|
||||||
shared among processes, so using critical sections is slightly more
|
shared among processes, so using critical sections is slightly more
|
||||||
efficient. The terminology is also slightly different: mutex may be locked (or
|
efficient. The terminology is also slightly different: mutex may be locked
|
||||||
acquired) and unlocked (or released) while critical section is entered and left
|
(or acquired) and unlocked (or released) while critical section is entered
|
||||||
by the program.
|
and left by the program.
|
||||||
|
|
||||||
Finally, you should try to use
|
Finally, you should try to use wxCriticalSectionLocker class whenever
|
||||||
wxCriticalSectionLocker class whenever
|
|
||||||
possible instead of directly using wxCriticalSection for the same reasons
|
possible instead of directly using wxCriticalSection for the same reasons
|
||||||
wxMutexLocker is preferrable to
|
wxMutexLocker is preferrable to wxMutex - please see wxMutex for an example.
|
||||||
wxMutex - please see wxMutex for an example.
|
|
||||||
|
|
||||||
@library{wxbase}
|
@library{wxbase}
|
||||||
@category{threading}
|
@category{threading}
|
||||||
@ -278,9 +287,10 @@ class wxCriticalSection
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Default constructor initializes critical section object.
|
Default constructor initializes critical section object. By default
|
||||||
|
critical sections are recursive under Unix and Windows.
|
||||||
*/
|
*/
|
||||||
wxCriticalSection();
|
wxCriticalSection( wxCriticalSectionType critSecType = wxCRITSEC_DEFAULT );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Destructor frees the resources.
|
Destructor frees the resources.
|
||||||
@ -301,6 +311,37 @@ public:
|
|||||||
void Leave();
|
void Leave();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
The possible thread kinds.
|
||||||
|
*/
|
||||||
|
enum wxThreadKind
|
||||||
|
{
|
||||||
|
wxTHREAD_DETACHED, /** Detached thread */
|
||||||
|
wxTHREAD_JOINABLE /** Joinable thread */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
The possible thread errors.
|
||||||
|
*/
|
||||||
|
enum wxThreadError
|
||||||
|
{
|
||||||
|
wxTHREAD_NO_ERROR = 0, /** No error */
|
||||||
|
wxTHREAD_NO_RESOURCE, /** No resource left to create a new thread */
|
||||||
|
wxTHREAD_RUNNING, /** The thread is already running */
|
||||||
|
wxTHREAD_NOT_RUNNING, /** The thread isn't running */
|
||||||
|
wxTHREAD_KILLED, /** Thread we waited for had to be killed */
|
||||||
|
wxTHREAD_MISC_ERROR /** Some other error */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Defines the interval of priority
|
||||||
|
*/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
WXTHREAD_MIN_PRIORITY = 0u,
|
||||||
|
WXTHREAD_DEFAULT_PRIORITY = 50u,
|
||||||
|
WXTHREAD_MAX_PRIORITY = 100u
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -801,6 +842,32 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
The possible wxMutex kinds.
|
||||||
|
*/
|
||||||
|
enum wxMutexType
|
||||||
|
{
|
||||||
|
wxMUTEX_DEFAULT, /** Normal mutex: try to always use this one. Recursive under Windows. */
|
||||||
|
|
||||||
|
wxMUTEX_RECURSIVE /** Recursive mutex: don't use these ones with wxCondition. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
The possible wxMutex errors.
|
||||||
|
*/
|
||||||
|
enum wxMutexError
|
||||||
|
{
|
||||||
|
wxMUTEX_NO_ERROR = 0, /** operation completed successfully */
|
||||||
|
wxMUTEX_INVALID, /** mutex hasn't been initialized */
|
||||||
|
wxMUTEX_DEAD_LOCK, /** mutex is already locked by the calling thread */
|
||||||
|
wxMUTEX_BUSY, /** mutex is already locked by another thread */
|
||||||
|
wxMUTEX_UNLOCKED, /** attempt to unlock a mutex which is not locked */
|
||||||
|
wxMUTEX_TIMEOUT, /** LockTimeout() has timed out */
|
||||||
|
wxMUTEX_MISC_ERROR /** any other error */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@class wxMutex
|
@class wxMutex
|
||||||
@ -816,14 +883,56 @@ public:
|
|||||||
thread is waiting) but using them is not recommended under Unix and they are
|
thread is waiting) but using them is not recommended under Unix and they are
|
||||||
@b not recursive there by default. The reason for this is that recursive
|
@b not recursive there by default. The reason for this is that recursive
|
||||||
mutexes are not supported by all Unix flavours and, worse, they cannot be used
|
mutexes are not supported by all Unix flavours and, worse, they cannot be used
|
||||||
with wxCondition. On the other hand, Win32 mutexes are
|
with wxCondition. On the other hand, Win32 mutexes are always recursive.
|
||||||
always recursive.
|
|
||||||
|
|
||||||
For example, when several threads use the data stored in the linked list,
|
For example, when several threads use the data stored in the linked list,
|
||||||
modifications to the list should only be allowed to one thread at a time
|
modifications to the list should only be allowed to one thread at a time
|
||||||
because during a new node addition the list integrity is temporarily broken
|
because during a new node addition the list integrity is temporarily broken
|
||||||
(this is also called @e program invariant).
|
(this is also called @e program invariant).
|
||||||
|
|
||||||
|
@code
|
||||||
|
// this variable has an "s_" prefix because it is static: seeing an "s_" in
|
||||||
|
// a multithreaded program is in general a good sign that you should use a
|
||||||
|
// mutex (or a critical section)
|
||||||
|
static wxMutex *s_mutexProtectingTheGlobalData;
|
||||||
|
|
||||||
|
// we store some numbers in this global array which is presumably used by
|
||||||
|
// several threads simultaneously
|
||||||
|
wxArrayInt s_data;
|
||||||
|
|
||||||
|
void MyThread::AddNewNode(int num)
|
||||||
|
{
|
||||||
|
// ensure that no other thread accesses the list
|
||||||
|
s_mutexProtectingTheGlobalList->Lock();
|
||||||
|
|
||||||
|
s_data.Add(num);
|
||||||
|
|
||||||
|
s_mutexProtectingTheGlobalList->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if the given number is greater than all array elements
|
||||||
|
bool MyThread::IsGreater(int num)
|
||||||
|
{
|
||||||
|
// before using the list we must acquire the mutex
|
||||||
|
wxMutexLocker lock(s_mutexProtectingTheGlobalData);
|
||||||
|
|
||||||
|
size_t count = s_data.Count();
|
||||||
|
for ( size_t n = 0; n < count; n++ )
|
||||||
|
{
|
||||||
|
if ( s_data[n] > num )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
Notice how wxMutexLocker was used in the second function to ensure that the
|
||||||
|
mutex is unlocked in any case: whether the function returns true or false
|
||||||
|
(because the destructor of the local object lock is always called). Using
|
||||||
|
this class instead of directly using wxMutex is, in general safer and is
|
||||||
|
even more so if your program uses C++ exceptions.
|
||||||
|
|
||||||
@library{wxbase}
|
@library{wxbase}
|
||||||
@category{threading}
|
@category{threading}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ static bool gs_waitingForThread = false;
|
|||||||
// wxCriticalSection
|
// wxCriticalSection
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxCriticalSection::wxCriticalSection()
|
wxCriticalSection::wxCriticalSection( wxCriticalSectionType WXUNUSED(critSecType) )
|
||||||
{
|
{
|
||||||
wxCOMPILE_TIME_ASSERT( sizeof(CRITICAL_SECTION) <= sizeof(wxCritSectBuffer),
|
wxCOMPILE_TIME_ASSERT( sizeof(CRITICAL_SECTION) <= sizeof(wxCritSectBuffer),
|
||||||
wxCriticalSectionBufferTooSmall );
|
wxCriticalSectionBufferTooSmall );
|
||||||
|
@ -106,7 +106,7 @@ MPCriticalRegionID gs_guiCritical = kInvalidID;
|
|||||||
// wxCriticalSection
|
// wxCriticalSection
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxCriticalSection::wxCriticalSection()
|
wxCriticalSection::wxCriticalSection( wxCriticalSectionType WXUNUSED(critSecType) )
|
||||||
{
|
{
|
||||||
MPCreateCriticalRegion( (MPCriticalRegionID*) &m_critRegion );
|
MPCreateCriticalRegion( (MPCriticalRegionID*) &m_critRegion );
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user