|
|
@@ -1,33 +1,104 @@
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Name: thread.h
|
|
|
|
// Name: thread.h
|
|
|
|
// Purpose: interface of wxCondition
|
|
|
|
// Purpose: interface of all thread-related wxWidgets classes
|
|
|
|
// Author: wxWidgets team
|
|
|
|
// Author: wxWidgets team
|
|
|
|
// RCS-ID: $Id$
|
|
|
|
// RCS-ID: $Id$
|
|
|
|
// Licence: wxWindows license
|
|
|
|
// Licence: wxWindows license
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** See wxCondition. */
|
|
|
|
|
|
|
|
enum wxCondError
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
wxCOND_NO_ERROR = 0,
|
|
|
|
|
|
|
|
wxCOND_INVALID,
|
|
|
|
|
|
|
|
wxCOND_TIMEOUT, //!< WaitTimeout() has timed out
|
|
|
|
|
|
|
|
wxCOND_MISC_ERROR
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@class wxCondition
|
|
|
|
@class wxCondition
|
|
|
|
|
|
|
|
|
|
|
|
wxCondition variables correspond to pthread conditions or to Win32 event
|
|
|
|
wxCondition variables correspond to pthread conditions or to Win32 event objects.
|
|
|
|
objects. They may be used in a multithreaded application to wait until the
|
|
|
|
They may be used in a multithreaded application to wait until the given condition
|
|
|
|
given condition becomes @true which happens when the condition becomes signaled.
|
|
|
|
becomes @true which happens when the condition becomes signaled.
|
|
|
|
|
|
|
|
|
|
|
|
For example, if a worker thread is doing some long task and another thread has
|
|
|
|
For example, if a worker thread is doing some long task and another thread has
|
|
|
|
to wait until it is finished, the latter thread will wait on the condition
|
|
|
|
to wait until it is finished, the latter thread will wait on the condition
|
|
|
|
object and the worker thread will signal it on exit (this example is not
|
|
|
|
object and the worker thread will signal it on exit (this example is not
|
|
|
|
perfect because in this particular case it would be much better to just
|
|
|
|
perfect because in this particular case it would be much better to just
|
|
|
|
wxThread::Wait for the worker thread, but if there are several
|
|
|
|
wxThread::Wait for the worker thread, but if there are several worker threads
|
|
|
|
worker threads it already makes much more sense).
|
|
|
|
it already makes much more sense).
|
|
|
|
|
|
|
|
|
|
|
|
Note that a call to wxCondition::Signal may happen before the
|
|
|
|
Note that a call to wxCondition::Signal may happen before the other thread calls
|
|
|
|
other thread calls wxCondition::Wait and, just as with the
|
|
|
|
wxCondition::Wait and, just as with the pthread conditions, the signal is then
|
|
|
|
pthread conditions, the signal is then lost and so if you want to be sure that
|
|
|
|
lost and so if you want to be sure that you don't miss it you must keep the
|
|
|
|
you don't miss it you must keep the mutex associated with the condition
|
|
|
|
mutex associated with the condition initially locked and lock it again before calling
|
|
|
|
initially locked and lock it again before calling
|
|
|
|
wxCondition::Signal. Of course, this means that this call is going to block
|
|
|
|
wxCondition::Signal. Of course, this means that this call is
|
|
|
|
until wxCondition::Wait is called by another thread.
|
|
|
|
going to block until wxCondition::Wait is called by another
|
|
|
|
|
|
|
|
thread.
|
|
|
|
@section condition_example Example
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This example shows how a main thread may launch a worker thread which starts
|
|
|
|
|
|
|
|
running and then waits until the main thread signals it to continue:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@code
|
|
|
|
|
|
|
|
class MySignallingThread : public wxThread
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
MySignallingThread(wxMutex *mutex, wxCondition *condition)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_mutex = mutex;
|
|
|
|
|
|
|
|
m_condition = condition;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Create();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual ExitCode Entry()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
... do our job ...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// tell the other(s) thread(s) that we're about to terminate: we must
|
|
|
|
|
|
|
|
// lock the mutex first or we might signal the condition before the
|
|
|
|
|
|
|
|
// waiting threads start waiting on it!
|
|
|
|
|
|
|
|
wxMutexLocker lock(*m_mutex);
|
|
|
|
|
|
|
|
m_condition->Broadcast(); // same as Signal() here -- one waiter only
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
wxCondition *m_condition;
|
|
|
|
|
|
|
|
wxMutex *m_mutex;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int main()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
wxMutex mutex;
|
|
|
|
|
|
|
|
wxCondition condition(mutex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// the mutex should be initially locked
|
|
|
|
|
|
|
|
mutex.Lock();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// create and run the thread but notice that it won't be able to
|
|
|
|
|
|
|
|
// exit (and signal its exit) before we unlock the mutex below
|
|
|
|
|
|
|
|
MySignallingThread *thread = new MySignallingThread(&mutex, &condition);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
thread->Run();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// wait for the thread termination: Wait() atomically unlocks the mutex
|
|
|
|
|
|
|
|
// which allows the thread to continue and starts waiting
|
|
|
|
|
|
|
|
condition.Wait();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// now we can exit
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Of course, here it would be much better to simply use a joinable thread and
|
|
|
|
|
|
|
|
call wxThread::Wait on it, but this example does illustrate the importance of
|
|
|
|
|
|
|
|
properly locking the mutex when using wxCondition.
|
|
|
|
|
|
|
|
|
|
|
|
@library{wxbase}
|
|
|
|
@library{wxbase}
|
|
|
|
@category{threading}
|
|
|
|
@category{threading}
|
|
|
@@ -38,23 +109,24 @@ class wxCondition
|
|
|
|
{
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Default and only constructor. The @a mutex must be locked by the caller
|
|
|
|
Default and only constructor.
|
|
|
|
before calling Wait() function.
|
|
|
|
The @a mutex must be locked by the caller before calling Wait() function.
|
|
|
|
Use IsOk() to check if the object was successfully
|
|
|
|
Use IsOk() to check if the object was successfully initialized.
|
|
|
|
initialized.
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxCondition(wxMutex& mutex);
|
|
|
|
wxCondition(wxMutex& mutex);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Destroys the wxCondition object. The destructor is not virtual so this class
|
|
|
|
Destroys the wxCondition object.
|
|
|
|
should not be used polymorphically.
|
|
|
|
|
|
|
|
|
|
|
|
The destructor is not virtual so this class should not be used polymorphically.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
~wxCondition();
|
|
|
|
~wxCondition();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Broadcasts to all waiting threads, waking all of them up. Note that this method
|
|
|
|
Broadcasts to all waiting threads, waking all of them up.
|
|
|
|
may be called whether the mutex associated with this condition is locked or
|
|
|
|
|
|
|
|
not.
|
|
|
|
Note that this method may be called whether the mutex associated with
|
|
|
|
|
|
|
|
this condition is locked or not.
|
|
|
|
|
|
|
|
|
|
|
|
@see Signal()
|
|
|
|
@see Signal()
|
|
|
|
*/
|
|
|
|
*/
|
|
|
@@ -67,10 +139,13 @@ public:
|
|
|
|
bool IsOk() const;
|
|
|
|
bool IsOk() const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Signals the object waking up at most one thread. If several threads are waiting
|
|
|
|
Signals the object waking up at most one thread.
|
|
|
|
on the same condition, the exact thread which is woken up is undefined. If no
|
|
|
|
|
|
|
|
threads are waiting, the signal is lost and the condition would have to be
|
|
|
|
If several threads are waiting on the same condition, the exact thread
|
|
|
|
signalled again to wake up any thread which may start waiting on it later.
|
|
|
|
which is woken up is undefined. If no threads are waiting, the signal is
|
|
|
|
|
|
|
|
lost and the condition would have to be signalled again to wake up any
|
|
|
|
|
|
|
|
thread which may start waiting on it later.
|
|
|
|
|
|
|
|
|
|
|
|
Note that this method may be called whether the mutex associated with this
|
|
|
|
Note that this method may be called whether the mutex associated with this
|
|
|
|
condition is locked or not.
|
|
|
|
condition is locked or not.
|
|
|
|
|
|
|
|
|
|
|
@@ -80,18 +155,18 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Waits until the condition is signalled.
|
|
|
|
Waits until the condition is signalled.
|
|
|
|
This method atomically releases the lock on the mutex associated with this
|
|
|
|
|
|
|
|
condition (this is why it must be locked prior to calling Wait) and puts the
|
|
|
|
|
|
|
|
thread to sleep until Signal() or
|
|
|
|
|
|
|
|
Broadcast() is called. It then locks the mutex
|
|
|
|
|
|
|
|
again and returns.
|
|
|
|
|
|
|
|
Note that even if Signal() had been called before
|
|
|
|
|
|
|
|
Wait without waking up any thread, the thread would still wait for another one
|
|
|
|
|
|
|
|
and so it is important to ensure that the condition will be signalled after
|
|
|
|
|
|
|
|
Wait or the thread may sleep forever.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@return Returns wxCOND_NO_ERROR on success, another value if an error
|
|
|
|
This method atomically releases the lock on the mutex associated with this
|
|
|
|
occurred.
|
|
|
|
condition (this is why it must be locked prior to calling Wait()) and puts the
|
|
|
|
|
|
|
|
thread to sleep until Signal() or Broadcast() is called.
|
|
|
|
|
|
|
|
It then locks the mutex again and returns.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note that even if Signal() had been called before Wait() without waking
|
|
|
|
|
|
|
|
up any thread, the thread would still wait for another one and so it is
|
|
|
|
|
|
|
|
important to ensure that the condition will be signalled after
|
|
|
|
|
|
|
|
Wait() or the thread may sleep forever.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@return Returns wxCOND_NO_ERROR on success, another value if an error occurred.
|
|
|
|
|
|
|
|
|
|
|
|
@see WaitTimeout()
|
|
|
|
@see WaitTimeout()
|
|
|
|
*/
|
|
|
|
*/
|
|
|
@@ -99,26 +174,47 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Waits until the condition is signalled or the timeout has elapsed.
|
|
|
|
Waits until the condition is signalled or the timeout has elapsed.
|
|
|
|
This method is identical to Wait() except that it
|
|
|
|
|
|
|
|
returns, with the return code of @c wxCOND_TIMEOUT as soon as the given
|
|
|
|
This method is identical to Wait() except that it returns, with the
|
|
|
|
timeout expires.
|
|
|
|
return code of @c wxCOND_TIMEOUT as soon as the given timeout expires.
|
|
|
|
|
|
|
|
|
|
|
|
@param milliseconds
|
|
|
|
@param milliseconds
|
|
|
|
Timeout in milliseconds
|
|
|
|
Timeout in milliseconds
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@return Returns wxCOND_NO_ERROR if the condition was signalled,
|
|
|
|
|
|
|
|
wxCOND_TIMEOUT if the timeout elapsed before this happened or
|
|
|
|
|
|
|
|
another error code from wxCondError enum.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxCondError WaitTimeout(unsigned long milliseconds);
|
|
|
|
wxCondError WaitTimeout(unsigned long milliseconds);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// There are 2 types of mutexes: normal mutexes and recursive ones. The attempt
|
|
|
|
|
|
|
|
// to lock a normal mutex by a thread which already owns it results in
|
|
|
|
|
|
|
|
// undefined behaviour (it always works under Windows, it will almost always
|
|
|
|
|
|
|
|
// result in a deadlock under Unix). Locking a recursive mutex in such
|
|
|
|
|
|
|
|
// situation always succeeds and it must be unlocked as many times as it has
|
|
|
|
|
|
|
|
// been locked.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// However recursive mutexes have several important drawbacks: first, in the
|
|
|
|
|
|
|
|
// POSIX implementation, they're less efficient. Second, and more importantly,
|
|
|
|
|
|
|
|
// they CAN NOT BE USED WITH CONDITION VARIABLES under Unix! Using them with
|
|
|
|
|
|
|
|
// wxCondition will work under Windows and some Unices (notably Linux) but will
|
|
|
|
|
|
|
|
// deadlock under other Unix versions (e.g. Solaris). As it might be difficult
|
|
|
|
|
|
|
|
// to ensure that a recursive mutex is not used with wxCondition, it is a good
|
|
|
|
|
|
|
|
// idea to avoid using recursive mutexes at all. Also, the last problem with
|
|
|
|
|
|
|
|
// them is that some (older) Unix versions don't support this at all -- which
|
|
|
|
|
|
|
|
// results in a configure warning when building and a deadlock when using them.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@class wxCriticalSectionLocker
|
|
|
|
@class wxCriticalSectionLocker
|
|
|
|
|
|
|
|
|
|
|
|
This is a small helper class to be used with wxCriticalSection
|
|
|
|
This is a small helper class to be used with wxCriticalSection objects.
|
|
|
|
objects. A wxCriticalSectionLocker enters the critical section in the
|
|
|
|
|
|
|
|
constructor and leaves it in the destructor making it much more difficult to
|
|
|
|
A wxCriticalSectionLocker enters the critical section in the constructor and
|
|
|
|
forget to leave a critical section (which, in general, will lead to serious
|
|
|
|
leaves it in the destructor making it much more difficult to forget to leave
|
|
|
|
and difficult to debug problems).
|
|
|
|
a critical section (which, in general, will lead to serious and difficult
|
|
|
|
|
|
|
|
to debug problems).
|
|
|
|
|
|
|
|
|
|
|
|
Example of using it:
|
|
|
|
Example of using it:
|
|
|
|
|
|
|
|
|
|
|
@@ -174,25 +270,23 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
The wxThreadHelper class is a mix-in class that manages a single background
|
|
|
|
The wxThreadHelper class is a mix-in class that manages a single background
|
|
|
|
thread. By deriving from wxThreadHelper, a class can implement the thread
|
|
|
|
thread. By deriving from wxThreadHelper, a class can implement the thread
|
|
|
|
code in its own wxThreadHelper::Entry method
|
|
|
|
code in its own wxThreadHelper::Entry() method and easily share data and
|
|
|
|
and easily share data and synchronization objects between the main thread
|
|
|
|
synchronization objects between the main thread and the worker thread.
|
|
|
|
and the worker thread. Doing this prevents the awkward passing of pointers
|
|
|
|
|
|
|
|
that is needed when the original object in the main thread needs to
|
|
|
|
|
|
|
|
synchronize with its worker thread in its own wxThread derived object.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For example, wxFrame may need to make some calculations
|
|
|
|
Doing this prevents the awkward passing of pointers that is needed when the
|
|
|
|
in a background thread and then display the results of those calculations in
|
|
|
|
original object in the main thread needs to synchronize with its worker thread
|
|
|
|
the main window.
|
|
|
|
in its own wxThread derived object.
|
|
|
|
|
|
|
|
|
|
|
|
Ordinarily, a wxThread derived object would be created
|
|
|
|
For example, wxFrame may need to make some calculations in a background thread
|
|
|
|
with the calculation code implemented in
|
|
|
|
and then display the results of those calculations in the main window.
|
|
|
|
wxThread::Entry. To access the inputs to the
|
|
|
|
|
|
|
|
calculation, the frame object would often to pass a pointer to itself to the
|
|
|
|
|
|
|
|
thread object. Similarly, the frame object would hold a pointer to the
|
|
|
|
|
|
|
|
thread object. Shared data and synchronization objects could be stored in
|
|
|
|
|
|
|
|
either object though the object without the data would have to access the
|
|
|
|
|
|
|
|
data through a pointer.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ordinarily, a wxThread derived object would be created with the calculation
|
|
|
|
|
|
|
|
code implemented in wxThread::Entry. To access the inputs to the calculation,
|
|
|
|
|
|
|
|
the frame object would often to pass a pointer to itself to the thread object.
|
|
|
|
|
|
|
|
Similarly, the frame object would hold a pointer to the thread object.
|
|
|
|
|
|
|
|
Shared data and synchronization objects could be stored in either object
|
|
|
|
|
|
|
|
though the object without the data would have to access the data through
|
|
|
|
|
|
|
|
a pointer.
|
|
|
|
However, with wxThreadHelper, the frame object and the thread object are
|
|
|
|
However, with wxThreadHelper, the frame object and the thread object are
|
|
|
|
treated as the same object. Shared data and synchronization variables are
|
|
|
|
treated as the same object. Shared data and synchronization variables are
|
|
|
|
stored in the single object, eliminating a layer of indirection and the
|
|
|
|
stored in the single object, eliminating a layer of indirection and the
|
|
|
@@ -217,22 +311,27 @@ public:
|
|
|
|
virtual ~wxThreadHelper();
|
|
|
|
virtual ~wxThreadHelper();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Creates a new thread. The thread object is created in the suspended state, and
|
|
|
|
Creates a new thread.
|
|
|
|
you
|
|
|
|
|
|
|
|
should call @ref wxThread::Run GetThread()-Run to start running
|
|
|
|
|
|
|
|
it. You may optionally specify the stack size to be allocated to it (Ignored on
|
|
|
|
|
|
|
|
platforms that don't support setting it explicitly, eg. Unix).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@return One of:
|
|
|
|
The thread object is created in the suspended state, and you
|
|
|
|
|
|
|
|
should call @ref wxThread::Run GetThread()-Run to start running it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
You may optionally specify the stack size to be allocated to it (ignored
|
|
|
|
|
|
|
|
on platforms that don't support setting it explicitly, eg. Unix).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@return One of the ::wxThreadError enum values.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxThreadError Create(unsigned int stackSize = 0);
|
|
|
|
wxThreadError Create(unsigned int stackSize = 0);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
This is the entry point of the thread. This function is pure virtual and must
|
|
|
|
This is the entry point of the thread.
|
|
|
|
be implemented by any derived class. The thread execution will start here.
|
|
|
|
|
|
|
|
|
|
|
|
This function is pure virtual and must be implemented by any derived class.
|
|
|
|
|
|
|
|
The thread execution will start here.
|
|
|
|
|
|
|
|
|
|
|
|
The returned value is the thread exit code which is only useful for
|
|
|
|
The returned value is the thread exit code which is only useful for
|
|
|
|
joinable threads and is the value returned by
|
|
|
|
joinable threads and is the value returned by @c "GetThread()->Wait()".
|
|
|
|
@ref wxThread::Wait GetThread()-Wait.
|
|
|
|
|
|
|
|
This function is called by wxWidgets itself and should never be called
|
|
|
|
This function is called by wxWidgets itself and should never be called
|
|
|
|
directly.
|
|
|
|
directly.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
@@ -243,11 +342,6 @@ public:
|
|
|
|
associated with the thread.
|
|
|
|
associated with the thread.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxThread* GetThread() const;
|
|
|
|
wxThread* GetThread() const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
wxThread * m_thread
|
|
|
|
|
|
|
|
the actual wxThread object.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@@ -266,13 +360,13 @@ enum wxCriticalSectionType
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@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 a wxMutex.
|
|
|
|
a wxMutex. The only difference is that under Windows platform
|
|
|
|
The only difference is that under Windows platform critical sections are only
|
|
|
|
critical sections are only visible inside one process, while mutexes may be
|
|
|
|
visible inside one process, while mutexes may be shared among processes,
|
|
|
|
shared among processes, so using critical sections is slightly more
|
|
|
|
so using critical sections is slightly more efficient.
|
|
|
|
efficient. The terminology is also slightly different: mutex may be locked
|
|
|
|
|
|
|
|
(or acquired) and unlocked (or released) while critical section is entered
|
|
|
|
The terminology is also slightly different: mutex may be locked (or acquired)
|
|
|
|
and left by the program.
|
|
|
|
and unlocked (or released) while critical section is entered and left by the program.
|
|
|
|
|
|
|
|
|
|
|
|
Finally, you should try to use wxCriticalSectionLocker class whenever
|
|
|
|
Finally, you should try to use wxCriticalSectionLocker class whenever
|
|
|
|
possible instead of directly using wxCriticalSection for the same reasons
|
|
|
|
possible instead of directly using wxCriticalSection for the same reasons
|
|
|
@@ -287,8 +381,8 @@ class wxCriticalSection
|
|
|
|
{
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Default constructor initializes critical section object. By default
|
|
|
|
Default constructor initializes critical section object.
|
|
|
|
critical sections are recursive under Unix and Windows.
|
|
|
|
By default critical sections are recursive under Unix and Windows.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxCriticalSection( wxCriticalSectionType critSecType = wxCRITSEC_DEFAULT );
|
|
|
|
wxCriticalSection( wxCriticalSectionType critSecType = wxCRITSEC_DEFAULT );
|
|
|
|
|
|
|
|
|
|
|
@@ -298,15 +392,17 @@ public:
|
|
|
|
~wxCriticalSection();
|
|
|
|
~wxCriticalSection();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Enter the critical section (same as locking a mutex). There is no error return
|
|
|
|
Enter the critical section (same as locking a mutex).
|
|
|
|
for this function. After entering the critical section protecting some global
|
|
|
|
|
|
|
|
|
|
|
|
There is no error return for this function.
|
|
|
|
|
|
|
|
After entering the critical section protecting some global
|
|
|
|
data the thread running in critical section may safely use/modify it.
|
|
|
|
data the thread running in critical section may safely use/modify it.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
void Enter();
|
|
|
|
void Enter();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Leave the critical section allowing other threads use the global data protected
|
|
|
|
Leave the critical section allowing other threads use the global data
|
|
|
|
by it. There is no error return for this function.
|
|
|
|
protected by it. There is no error return for this function.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
void Leave();
|
|
|
|
void Leave();
|
|
|
|
};
|
|
|
|
};
|
|
|
@@ -361,19 +457,20 @@ enum
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@class wxThread
|
|
|
|
@class wxThread
|
|
|
|
|
|
|
|
|
|
|
|
A thread is basically a path of execution through a program. Threads are
|
|
|
|
A thread is basically a path of execution through a program.
|
|
|
|
sometimes called @e light-weight processes, but the fundamental difference
|
|
|
|
Threads are sometimes called @e light-weight processes, but the fundamental difference
|
|
|
|
between threads and processes is that memory spaces of different processes are
|
|
|
|
between threads and processes is that memory spaces of different processes are
|
|
|
|
separated while all threads share the same address space.
|
|
|
|
separated while all threads share the same address space.
|
|
|
|
|
|
|
|
|
|
|
|
While it makes it much easier to share common data between several threads, it
|
|
|
|
While it makes it much easier to share common data between several threads, it
|
|
|
|
also makes it much easier to shoot oneself in the foot, so careful use of
|
|
|
|
also makes it much easier to shoot oneself in the foot, so careful use of
|
|
|
|
synchronization objects such as mutexes() or @ref wxCriticalSection
|
|
|
|
synchronization objects such as mutexes() or critical sections (see wxCriticalSection)
|
|
|
|
"critical sections" is recommended. In addition, don't create global thread
|
|
|
|
is recommended. In addition, don't create global thread objects because they
|
|
|
|
objects because they allocate memory in their constructor, which will cause
|
|
|
|
allocate memory in their constructor, which will cause problems for the memory
|
|
|
|
problems for the memory checking system.
|
|
|
|
checking system.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@section thread_types Types of wxThreads
|
|
|
|
|
|
|
|
|
|
|
|
@section overview_typeswxthread Types of wxThreads
|
|
|
|
|
|
|
|
There are two types of threads in wxWidgets: @e detached and @e joinable,
|
|
|
|
There are two types of threads in wxWidgets: @e detached and @e joinable,
|
|
|
|
modeled after the the POSIX thread API. This is different from the Win32 API
|
|
|
|
modeled after the the POSIX thread API. This is different from the Win32 API
|
|
|
|
where all threads are joinable.
|
|
|
|
where all threads are joinable.
|
|
|
@@ -394,13 +491,14 @@ enum
|
|
|
|
In contrast, detached threads are of the "fire-and-forget" kind: you only have to
|
|
|
|
In contrast, detached threads are of the "fire-and-forget" kind: you only have to
|
|
|
|
start a detached thread and it will terminate and destroy itself.
|
|
|
|
start a detached thread and it will terminate and destroy itself.
|
|
|
|
|
|
|
|
|
|
|
|
@section overview_deletionwxthread wxThread Deletion
|
|
|
|
|
|
|
|
Regardless of whether it has terminated or not, you should call
|
|
|
|
@section thread_deletion wxThread Deletion
|
|
|
|
Wait() on a joinable thread to release its memory, as outlined in
|
|
|
|
|
|
|
|
@ref overview_typeswxthread "Types of wxThreads". If you created
|
|
|
|
Regardless of whether it has terminated or not, you should call Wait() on a
|
|
|
|
a joinable thread on the heap, remember to delete it manually with the delete
|
|
|
|
joinable thread to release its memory, as outlined in @ref thread_types.
|
|
|
|
operator or similar means as only detached threads handle this type of memory
|
|
|
|
If you created a joinable thread on the heap, remember to delete it manually
|
|
|
|
management.
|
|
|
|
with the @c delete operator or similar means as only detached threads handle
|
|
|
|
|
|
|
|
this type of memory management.
|
|
|
|
|
|
|
|
|
|
|
|
Since detached threads delete themselves when they are finished processing,
|
|
|
|
Since detached threads delete themselves when they are finished processing,
|
|
|
|
you should take care when calling a routine on one. If you are certain the
|
|
|
|
you should take care when calling a routine on one. If you are certain the
|
|
|
@@ -422,9 +520,11 @@ enum
|
|
|
|
detached threads will still be deleted) and could leave the C runtime
|
|
|
|
detached threads will still be deleted) and could leave the C runtime
|
|
|
|
library in an undefined state.
|
|
|
|
library in an undefined state.
|
|
|
|
|
|
|
|
|
|
|
|
@section overview_secondarythreads wxWidgets Calls in Secondary Threads
|
|
|
|
|
|
|
|
|
|
|
|
@section thread_secondary wxWidgets Calls in Secondary Threads
|
|
|
|
|
|
|
|
|
|
|
|
All threads other than the "main application thread" (the one
|
|
|
|
All threads other than the "main application thread" (the one
|
|
|
|
wxApp::OnInit or your main function runs in, for example) are considered
|
|
|
|
wxApp::OnInit() or your main function runs in, for example) are considered
|
|
|
|
"secondary threads". These include all threads created by Create() or the
|
|
|
|
"secondary threads". These include all threads created by Create() or the
|
|
|
|
corresponding constructors.
|
|
|
|
corresponding constructors.
|
|
|
|
|
|
|
|
|
|
|
@@ -441,7 +541,9 @@ enum
|
|
|
|
This does not imply that calls to these classes are thread-safe, however,
|
|
|
|
This does not imply that calls to these classes are thread-safe, however,
|
|
|
|
as most wxWidgets classes are not thread-safe, including wxString.
|
|
|
|
as most wxWidgets classes are not thread-safe, including wxString.
|
|
|
|
|
|
|
|
|
|
|
|
@section overview_pollwxThread Don't Poll a wxThread
|
|
|
|
|
|
|
|
|
|
|
|
@section thread_poll Don't Poll a wxThread
|
|
|
|
|
|
|
|
|
|
|
|
A common problem users experience with wxThread is that in their main thread
|
|
|
|
A common problem users experience with wxThread is that in their main thread
|
|
|
|
they will check the thread every now and then to see if it has ended through
|
|
|
|
they will check the thread every now and then to see if it has ended through
|
|
|
|
IsRunning(), only to find that their application has run into problems
|
|
|
|
IsRunning(), only to find that their application has run into problems
|
|
|
@@ -453,14 +555,15 @@ enum
|
|
|
|
the thread has ended.
|
|
|
|
the thread has ended.
|
|
|
|
|
|
|
|
|
|
|
|
Usually you only need to notify the main thread, in which case you can
|
|
|
|
Usually you only need to notify the main thread, in which case you can
|
|
|
|
post an event to it via wxPostEvent() or wxEvtHandler::AddPendingEvent.
|
|
|
|
post an event to it via wxPostEvent() or wxEvtHandler::AddPendingEvent().
|
|
|
|
In the case of secondary threads you can call a routine of another class
|
|
|
|
In the case of secondary threads you can call a routine of another class
|
|
|
|
when the thread is about to complete processing and/or set the value of
|
|
|
|
when the thread is about to complete processing and/or set the value of
|
|
|
|
a variable, possibly using mutexes() and/or other synchronization means
|
|
|
|
a variable, possibly using mutexes (see wxMutex) and/or other synchronization
|
|
|
|
if necessary.
|
|
|
|
means if necessary.
|
|
|
|
|
|
|
|
|
|
|
|
@library{wxbase}
|
|
|
|
@library{wxbase}
|
|
|
|
@category{threading}
|
|
|
|
@category{threading}
|
|
|
|
|
|
|
|
|
|
|
|
@see wxMutex, wxCondition, wxCriticalSection
|
|
|
|
@see wxMutex, wxCondition, wxCriticalSection
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
class wxThread
|
|
|
|
class wxThread
|
|
|
@@ -468,7 +571,7 @@ class wxThread
|
|
|
|
public:
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
This constructor creates a new detached (default) or joinable C++
|
|
|
|
This constructor creates a new detached (default) or joinable C++
|
|
|
|
thread object. It does not create or start execution of the real thread --
|
|
|
|
thread object. It does not create or start execution of the real thread -
|
|
|
|
for this you should use the Create() and Run() methods.
|
|
|
|
for this you should use the Create() and Run() methods.
|
|
|
|
|
|
|
|
|
|
|
|
The possible values for @a kind parameters are:
|
|
|
|
The possible values for @a kind parameters are:
|
|
|
@@ -478,35 +581,38 @@ public:
|
|
|
|
wxThread(wxThreadKind kind = wxTHREAD_DETACHED);
|
|
|
|
wxThread(wxThreadKind kind = wxTHREAD_DETACHED);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
The destructor frees the resources associated with the thread. Notice that you
|
|
|
|
The destructor frees the resources associated with the thread.
|
|
|
|
should never delete a detached thread -- you may only call
|
|
|
|
Notice that you should never delete a detached thread -- you may only call
|
|
|
|
Delete() on it or wait until it terminates (and auto
|
|
|
|
Delete() on it or wait until it terminates (and auto destructs) itself.
|
|
|
|
destructs) itself. Because the detached threads delete themselves, they can
|
|
|
|
|
|
|
|
only be allocated on the heap.
|
|
|
|
Because the detached threads delete themselves, they can only be allocated on the heap.
|
|
|
|
Joinable threads should be deleted explicitly. The Delete() and Kill() functions
|
|
|
|
Joinable threads should be deleted explicitly. The Delete() and Kill() functions
|
|
|
|
will not delete the C++ thread object. It is also safe to allocate them on
|
|
|
|
will not delete the C++ thread object. It is also safe to allocate them on stack.
|
|
|
|
stack.
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
virtual ~wxThread();
|
|
|
|
virtual ~wxThread();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Creates a new thread. The thread object is created in the suspended state,
|
|
|
|
Creates a new thread.
|
|
|
|
and you should call Run() to start running it. You may optionally
|
|
|
|
|
|
|
|
specify the stack size to be allocated to it (Ignored on platforms that don't
|
|
|
|
The thread object is created in the suspended state, and you should call Run()
|
|
|
|
support setting it explicitly, eg. Unix system without
|
|
|
|
to start running it. You may optionally specify the stack size to be allocated
|
|
|
|
@c pthread_attr_setstacksize). If you do not specify the stack size,
|
|
|
|
to it (Ignored on platforms that don't support setting it explicitly,
|
|
|
|
the system's default value is used.
|
|
|
|
eg. Unix system without @c pthread_attr_setstacksize).
|
|
|
|
@b Warning: It is a good idea to explicitly specify a value as systems'
|
|
|
|
|
|
|
|
|
|
|
|
If you do not specify the stack size,the system's default value is used.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@warning
|
|
|
|
|
|
|
|
It is a good idea to explicitly specify a value as systems'
|
|
|
|
default values vary from just a couple of KB on some systems (BSD and
|
|
|
|
default values vary from just a couple of KB on some systems (BSD and
|
|
|
|
OS/2 systems) to one or several MB (Windows, Solaris, Linux). So, if you
|
|
|
|
OS/2 systems) to one or several MB (Windows, Solaris, Linux).
|
|
|
|
have a thread that requires more than just a few KB of memory, you will
|
|
|
|
So, if you have a thread that requires more than just a few KB of memory, you
|
|
|
|
have mysterious problems on some platforms but not on the common ones. On the
|
|
|
|
will have mysterious problems on some platforms but not on the common ones.
|
|
|
|
other hand, just indicating a large stack size by default will give you
|
|
|
|
On the other hand, just indicating a large stack size by default will give you
|
|
|
|
performance issues on those systems with small default stack since those
|
|
|
|
performance issues on those systems with small default stack since those
|
|
|
|
typically use fully committed memory for the stack. On the contrary, if
|
|
|
|
typically use fully committed memory for the stack.
|
|
|
|
use a lot of threads (say several hundred), virtual adress space can get tight
|
|
|
|
On the contrary, if you use a lot of threads (say several hundred),
|
|
|
|
unless you explicitly specify a smaller amount of thread stack space for each
|
|
|
|
virtual adress space can get tight unless you explicitly specify a
|
|
|
|
thread.
|
|
|
|
smaller amount of thread stack space for each thread.
|
|
|
|
|
|
|
|
|
|
|
|
@return One of:
|
|
|
|
@return One of:
|
|
|
|
- @b wxTHREAD_NO_ERROR - No error.
|
|
|
|
- @b wxTHREAD_NO_ERROR - No error.
|
|
|
@@ -516,20 +622,24 @@ public:
|
|
|
|
wxThreadError Create(unsigned int stackSize = 0);
|
|
|
|
wxThreadError Create(unsigned int stackSize = 0);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Calling Delete() gracefully terminates a
|
|
|
|
Calling Delete() gracefully terminates a detached thread, either when
|
|
|
|
detached thread, either when the thread calls TestDestroy() or finished
|
|
|
|
the thread calls TestDestroy() or finished processing.
|
|
|
|
processing.
|
|
|
|
|
|
|
|
(Note that while this could work on a joinable thread you simply should not
|
|
|
|
@note
|
|
|
|
|
|
|
|
While this could work on a joinable thread you simply should not
|
|
|
|
call this routine on one as afterwards you may not be able to call
|
|
|
|
call this routine on one as afterwards you may not be able to call
|
|
|
|
Wait() to free the memory of that thread).
|
|
|
|
Wait() to free the memory of that thread).
|
|
|
|
See @ref overview_deletionwxthread "wxThread deletion" for a broader
|
|
|
|
|
|
|
|
explanation of this routine.
|
|
|
|
See @ref thread_deletion for a broader explanation of this routine.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxThreadError Delete();
|
|
|
|
wxThreadError Delete();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
This is the entry point of the thread. This function is pure virtual and must
|
|
|
|
This is the entry point of the thread.
|
|
|
|
be implemented by any derived class. The thread execution will start here.
|
|
|
|
|
|
|
|
|
|
|
|
This function is pure virtual and must be implemented by any derived class.
|
|
|
|
|
|
|
|
The thread execution will start here.
|
|
|
|
|
|
|
|
|
|
|
|
The returned value is the thread exit code which is only useful for
|
|
|
|
The returned value is the thread exit code which is only useful for
|
|
|
|
joinable threads and is the value returned by Wait().
|
|
|
|
joinable threads and is the value returned by Wait().
|
|
|
|
This function is called by wxWidgets itself and should never be called
|
|
|
|
This function is called by wxWidgets itself and should never be called
|
|
|
@@ -541,6 +651,7 @@ public:
|
|
|
|
This is a protected function of the wxThread class and thus can only be called
|
|
|
|
This is a protected function of the wxThread class and thus can only be called
|
|
|
|
from a derived class. It also can only be called in the context of this
|
|
|
|
from a derived class. It also can only be called in the context of this
|
|
|
|
thread, i.e. a thread can only exit from itself, not from another thread.
|
|
|
|
thread, i.e. a thread can only exit from itself, not from another thread.
|
|
|
|
|
|
|
|
|
|
|
|
This function will terminate the OS thread (i.e. stop the associated path of
|
|
|
|
This function will terminate the OS thread (i.e. stop the associated path of
|
|
|
|
execution) and also delete the associated C++ object for detached threads.
|
|
|
|
execution) and also delete the associated C++ object for detached threads.
|
|
|
|
OnExit() will be called just before exiting.
|
|
|
|
OnExit() will be called just before exiting.
|
|
|
@@ -555,17 +666,15 @@ public:
|
|
|
|
static int GetCPUCount();
|
|
|
|
static int GetCPUCount();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Returns the platform specific thread ID of the current thread as a
|
|
|
|
Returns the platform specific thread ID of the current thread as a long.
|
|
|
|
long. This can be used to uniquely identify threads, even if they are
|
|
|
|
This can be used to uniquely identify threads, even if they are not wxThreads.
|
|
|
|
not wxThreads.
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static unsigned long GetCurrentId();
|
|
|
|
static unsigned long GetCurrentId();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Gets the thread identifier: this is a platform dependent number that uniquely
|
|
|
|
Gets the thread identifier: this is a platform dependent number that uniquely
|
|
|
|
identifies the
|
|
|
|
identifies the thread throughout the system during its existence
|
|
|
|
thread throughout the system during its existence (i.e. the thread identifiers
|
|
|
|
(i.e. the thread identifiers may be reused).
|
|
|
|
may be reused).
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
unsigned long GetId() const;
|
|
|
|
unsigned long GetId() const;
|
|
|
|
|
|
|
|
|
|
|
@@ -581,6 +690,7 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Returns @true if the thread is alive (i.e. started and not terminating).
|
|
|
|
Returns @true if the thread is alive (i.e. started and not terminating).
|
|
|
|
|
|
|
|
|
|
|
|
Note that this function can only safely be used with joinable threads, not
|
|
|
|
Note that this function can only safely be used with joinable threads, not
|
|
|
|
detached ones as the latter delete themselves and so when the real thread is
|
|
|
|
detached ones as the latter delete themselves and so when the real thread is
|
|
|
|
no longer alive, it is not possible to call this function because
|
|
|
|
no longer alive, it is not possible to call this function because
|
|
|
@@ -590,8 +700,7 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Returns @true if the thread is of the detached kind, @false if it is a
|
|
|
|
Returns @true if the thread is of the detached kind, @false if it is a
|
|
|
|
joinable
|
|
|
|
joinable one.
|
|
|
|
one.
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
bool IsDetached() const;
|
|
|
|
bool IsDetached() const;
|
|
|
|
|
|
|
|
|
|
|
@@ -607,25 +716,30 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Returns @true if the thread is running.
|
|
|
|
Returns @true if the thread is running.
|
|
|
|
|
|
|
|
|
|
|
|
This method may only be safely used for joinable threads, see the remark in
|
|
|
|
This method may only be safely used for joinable threads, see the remark in
|
|
|
|
IsAlive().
|
|
|
|
IsAlive().
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
bool IsRunning() const;
|
|
|
|
bool IsRunning() const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Immediately terminates the target thread. @b This function is dangerous and
|
|
|
|
Immediately terminates the target thread.
|
|
|
|
should
|
|
|
|
|
|
|
|
be used with extreme care (and not used at all whenever possible)! The resources
|
|
|
|
@b "This function is dangerous and should be used with extreme care"
|
|
|
|
allocated to the thread will not be freed and the state of the C runtime library
|
|
|
|
(and not used at all whenever possible)! The resources allocated to the
|
|
|
|
may become inconsistent. Use Delete() for detached
|
|
|
|
thread will not be freed and the state of the C runtime library may become
|
|
|
|
threads or Wait() for joinable threads instead.
|
|
|
|
inconsistent. Use Delete() for detached threads or Wait() for joinable
|
|
|
|
|
|
|
|
threads instead.
|
|
|
|
|
|
|
|
|
|
|
|
For detached threads Kill() will also delete the associated C++ object.
|
|
|
|
For detached threads Kill() will also delete the associated C++ object.
|
|
|
|
However this will not happen for joinable threads and this means that you will
|
|
|
|
However this will not happen for joinable threads and this means that you will
|
|
|
|
still have to delete the wxThread object yourself to avoid memory leaks.
|
|
|
|
still have to delete the wxThread object yourself to avoid memory leaks.
|
|
|
|
In neither case OnExit() of the dying thread will be
|
|
|
|
|
|
|
|
called, so no thread-specific cleanup will be performed.
|
|
|
|
In neither case OnExit() of the dying thread will be called, so no
|
|
|
|
|
|
|
|
thread-specific cleanup will be performed.
|
|
|
|
This function can only be called from another thread context, i.e. a thread
|
|
|
|
This function can only be called from another thread context, i.e. a thread
|
|
|
|
cannot kill itself.
|
|
|
|
cannot kill itself.
|
|
|
|
|
|
|
|
|
|
|
|
It is also an error to call this function for a thread which is not running or
|
|
|
|
It is also an error to call this function for a thread which is not running or
|
|
|
|
paused (in the latter case, the thread will be resumed first) -- if you do it,
|
|
|
|
paused (in the latter case, the thread will be resumed first) -- if you do it,
|
|
|
|
a @b wxTHREAD_NOT_RUNNING error will be returned.
|
|
|
|
a @b wxTHREAD_NOT_RUNNING error will be returned.
|
|
|
@@ -633,25 +747,31 @@ public:
|
|
|
|
wxThreadError Kill();
|
|
|
|
wxThreadError Kill();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Called when the thread exits. This function is called in the context of the
|
|
|
|
Called when the thread exits.
|
|
|
|
thread associated with the wxThread object, not in the context of the main
|
|
|
|
|
|
|
|
thread. This function will not be called if the thread was
|
|
|
|
This function is called in the context of the thread associated with the
|
|
|
|
@ref Kill() killed.
|
|
|
|
wxThread object, not in the context of the main thread.
|
|
|
|
|
|
|
|
This function will not be called if the thread was @ref Kill() killed.
|
|
|
|
|
|
|
|
|
|
|
|
This function should never be called directly.
|
|
|
|
This function should never be called directly.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
virtual void OnExit();
|
|
|
|
virtual void OnExit();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Suspends the thread. Under some implementations (Win32), the thread is
|
|
|
|
Suspends the thread.
|
|
|
|
suspended immediately, under others it will only be suspended when it calls
|
|
|
|
|
|
|
|
TestDestroy() for the next time (hence, if the
|
|
|
|
Under some implementations (Win32), the thread is suspended immediately,
|
|
|
|
thread doesn't call it at all, it won't be suspended).
|
|
|
|
under others it will only be suspended when it calls TestDestroy() for
|
|
|
|
|
|
|
|
the next time (hence, if the thread doesn't call it at all, it won't be
|
|
|
|
|
|
|
|
suspended).
|
|
|
|
|
|
|
|
|
|
|
|
This function can only be called from another thread context.
|
|
|
|
This function can only be called from another thread context.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxThreadError Pause();
|
|
|
|
wxThreadError Pause();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Resumes a thread suspended by the call to Pause().
|
|
|
|
Resumes a thread suspended by the call to Pause().
|
|
|
|
|
|
|
|
|
|
|
|
This function can only be called from another thread context.
|
|
|
|
This function can only be called from another thread context.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxThreadError Resume();
|
|
|
|
wxThreadError Resume();
|
|
|
@@ -659,23 +779,26 @@ public:
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Starts the thread execution. Should be called after
|
|
|
|
Starts the thread execution. Should be called after
|
|
|
|
Create().
|
|
|
|
Create().
|
|
|
|
|
|
|
|
|
|
|
|
This function can only be called from another thread context.
|
|
|
|
This function can only be called from another thread context.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxThreadError Run();
|
|
|
|
wxThreadError Run();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Sets the thread concurrency level for this process. This is, roughly, the
|
|
|
|
Sets the thread concurrency level for this process.
|
|
|
|
number of threads that the system tries to schedule to run in parallel.
|
|
|
|
|
|
|
|
|
|
|
|
This is, roughly, the number of threads that the system tries to schedule
|
|
|
|
|
|
|
|
to run in parallel.
|
|
|
|
The value of 0 for @a level may be used to set the default one.
|
|
|
|
The value of 0 for @a level may be used to set the default one.
|
|
|
|
Returns @true on success or @false otherwise (for example, if this function is
|
|
|
|
|
|
|
|
|
|
|
|
@return @true on success or @false otherwise (for example, if this function is
|
|
|
|
not implemented for this platform -- currently everything except Solaris).
|
|
|
|
not implemented for this platform -- currently everything except Solaris).
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static bool SetConcurrency(size_t level);
|
|
|
|
static bool SetConcurrency(size_t level);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Sets the priority of the thread, between 0 and 100. It can only be set
|
|
|
|
Sets the priority of the thread, between 0 and 100.
|
|
|
|
after calling Create() but before calling
|
|
|
|
It can only be set after calling Create() but before calling Run().
|
|
|
|
Run().
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The following priorities are defined:
|
|
|
|
The following priorities are defined:
|
|
|
|
- @b WXTHREAD_MIN_PRIORITY: 0
|
|
|
|
- @b WXTHREAD_MIN_PRIORITY: 0
|
|
|
@@ -693,19 +816,22 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
This function should be called periodically by the thread to ensure that
|
|
|
|
This function should be called periodically by the thread to ensure that
|
|
|
|
calls to Pause() and Delete() will work. If it returns @true, the thread
|
|
|
|
calls to Pause() and Delete() will work.
|
|
|
|
should exit as soon as possible. Notice that under some platforms (POSIX),
|
|
|
|
|
|
|
|
implementation of Pause() also relies on this function being called, so
|
|
|
|
If it returns @true, the thread should exit as soon as possible.
|
|
|
|
not calling it would prevent both stopping and suspending thread from working.
|
|
|
|
Notice that under some platforms (POSIX), implementation of Pause() also
|
|
|
|
|
|
|
|
relies on this function being called, so not calling it would prevent
|
|
|
|
|
|
|
|
both stopping and suspending thread from working.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
virtual bool TestDestroy();
|
|
|
|
virtual bool TestDestroy();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Return the thread object for the calling thread. @NULL is returned if
|
|
|
|
Return the thread object for the calling thread.
|
|
|
|
the calling thread is the main (GUI) thread, but IsMain() should be used
|
|
|
|
|
|
|
|
to test whether the thread is really the main one because @NULL may also
|
|
|
|
@NULL is returned if the calling thread is the main (GUI) thread, but
|
|
|
|
be returned for the thread not created with wxThread class. Generally
|
|
|
|
IsMain() should be used to test whether the thread is really the main one
|
|
|
|
speaking, the return value for such a thread is undefined.
|
|
|
|
because @NULL may also be returned for the thread not created with wxThread
|
|
|
|
|
|
|
|
class. Generally speaking, the return value for such a thread is undefined.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static wxThread* This();
|
|
|
|
static wxThread* This();
|
|
|
|
|
|
|
|
|
|
|
@@ -714,62 +840,80 @@ public:
|
|
|
|
returned from Entry() or @c (ExitCode)-1 on error. Notice that, unlike
|
|
|
|
returned from Entry() or @c (ExitCode)-1 on error. Notice that, unlike
|
|
|
|
Delete() doesn't cancel the thread in any way so the caller waits for as
|
|
|
|
Delete() doesn't cancel the thread in any way so the caller waits for as
|
|
|
|
long as it takes to the thread to exit.
|
|
|
|
long as it takes to the thread to exit.
|
|
|
|
|
|
|
|
|
|
|
|
You can only Wait() for joinable (not detached) threads.
|
|
|
|
You can only Wait() for joinable (not detached) threads.
|
|
|
|
This function can only be called from another thread context.
|
|
|
|
This function can only be called from another thread context.
|
|
|
|
See @ref overview_deletionwxthread "wxThread deletion" for a broader
|
|
|
|
|
|
|
|
explanation of this routine.
|
|
|
|
See @ref thread_deletion for a broader explanation of this routine.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
ExitCode Wait() const;
|
|
|
|
ExitCode Wait() const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Give the rest of the thread time slice to the system allowing the other
|
|
|
|
Give the rest of the thread time slice to the system allowing the other
|
|
|
|
threads to run.
|
|
|
|
threads to run.
|
|
|
|
|
|
|
|
|
|
|
|
Note that using this function is @b strongly discouraged, since in
|
|
|
|
Note that using this function is @b strongly discouraged, since in
|
|
|
|
many cases it indicates a design weakness of your threading model (as
|
|
|
|
many cases it indicates a design weakness of your threading model
|
|
|
|
does using Sleep functions).
|
|
|
|
(as does using Sleep() functions).
|
|
|
|
|
|
|
|
|
|
|
|
Threads should use the CPU in an efficient manner, i.e. they should
|
|
|
|
Threads should use the CPU in an efficient manner, i.e. they should
|
|
|
|
do their current work efficiently, then as soon as the work is done block
|
|
|
|
do their current work efficiently, then as soon as the work is done block
|
|
|
|
on a wakeup event (wxCondition, wxMutex, select(), poll(), ...)
|
|
|
|
on a wakeup event (wxCondition, wxMutex, select(), poll(), ...) which will
|
|
|
|
which will get signalled e.g. by other threads or a user device once further
|
|
|
|
get signalled e.g. by other threads or a user device once further thread
|
|
|
|
thread work is available. Using Yield or Sleep
|
|
|
|
work is available.
|
|
|
|
indicates polling-type behaviour, since we're fuzzily giving up our timeslice
|
|
|
|
Using Yield() or Sleep() indicates polling-type behaviour, since we're
|
|
|
|
and wait until sometime later we'll get reactivated, at which time we
|
|
|
|
fuzzily giving up our timeslice and wait until sometime later we'll get
|
|
|
|
realize that there isn't really much to do and Yield again...
|
|
|
|
reactivated, at which time we realize that there isn't really much to do
|
|
|
|
The most critical characteristic of Yield is that it's operating system
|
|
|
|
and Yield() again...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The most critical characteristic of Yield() is that it's operating system
|
|
|
|
specific: there may be scheduler changes which cause your thread to not
|
|
|
|
specific: there may be scheduler changes which cause your thread to not
|
|
|
|
wake up relatively soon again, but instead many seconds later,
|
|
|
|
wake up relatively soon again, but instead many seconds later,
|
|
|
|
causing huge performance issues for your application. @b with a
|
|
|
|
causing huge performance issues for your application.
|
|
|
|
well-behaving, CPU-efficient thread the operating system is likely to properly
|
|
|
|
|
|
|
|
care for its reactivation the moment it needs it, whereas with
|
|
|
|
<strong>
|
|
|
|
|
|
|
|
With a well-behaving, CPU-efficient thread the operating system is likely
|
|
|
|
|
|
|
|
to properly care for its reactivation the moment it needs it, whereas with
|
|
|
|
non-deterministic, Yield-using threads all bets are off and the system
|
|
|
|
non-deterministic, Yield-using threads all bets are off and the system
|
|
|
|
scheduler is free to penalize drastically, and this effect gets worse
|
|
|
|
scheduler is free to penalize drastically</strong>, and this effect gets worse
|
|
|
|
with increasing system load due to less free CPU resources available.
|
|
|
|
with increasing system load due to less free CPU resources available.
|
|
|
|
You may refer to various Linux kernel sched_yield discussions for more
|
|
|
|
You may refer to various Linux kernel @c sched_yield discussions for more
|
|
|
|
information.
|
|
|
|
information.
|
|
|
|
|
|
|
|
|
|
|
|
See also Sleep().
|
|
|
|
See also Sleep().
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static void Yield();
|
|
|
|
static void Yield();
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** See wxSemaphore. */
|
|
|
|
|
|
|
|
enum wxSemaError
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
wxSEMA_NO_ERROR = 0,
|
|
|
|
|
|
|
|
wxSEMA_INVALID, //!< semaphore hasn't been initialized successfully
|
|
|
|
|
|
|
|
wxSEMA_BUSY, //!< returned by TryWait() if Wait() would block
|
|
|
|
|
|
|
|
wxSEMA_TIMEOUT, //!< returned by WaitTimeout()
|
|
|
|
|
|
|
|
wxSEMA_OVERFLOW, //!< Post() would increase counter past the max
|
|
|
|
|
|
|
|
wxSEMA_MISC_ERROR
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@class wxSemaphore
|
|
|
|
@class wxSemaphore
|
|
|
|
|
|
|
|
|
|
|
|
wxSemaphore is a counter limiting the number of threads concurrently accessing
|
|
|
|
wxSemaphore is a counter limiting the number of threads concurrently accessing
|
|
|
|
a shared resource. This counter is always between 0 and the maximum value
|
|
|
|
a shared resource. This counter is always between 0 and the maximum value
|
|
|
|
specified during the semaphore creation. When the counter is strictly greater
|
|
|
|
specified during the semaphore creation. When the counter is strictly greater
|
|
|
|
than 0, a call to wxSemaphore::Wait returns immediately and
|
|
|
|
than 0, a call to wxSemaphore::Wait() returns immediately and decrements the
|
|
|
|
decrements the counter. As soon as it reaches 0, any subsequent calls to
|
|
|
|
counter. As soon as it reaches 0, any subsequent calls to wxSemaphore::Wait
|
|
|
|
wxSemaphore::Wait block and only return when the semaphore
|
|
|
|
block and only return when the semaphore counter becomes strictly positive
|
|
|
|
counter becomes strictly positive again as the result of calling
|
|
|
|
again as the result of calling wxSemaphore::Post which increments the counter.
|
|
|
|
wxSemaphore::Post which increments the counter.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In general, semaphores are useful to restrict access to a shared resource
|
|
|
|
In general, semaphores are useful to restrict access to a shared resource
|
|
|
|
which can only be accessed by some fixed number of clients at the same time. For
|
|
|
|
which can only be accessed by some fixed number of clients at the same time.
|
|
|
|
example, when modeling a hotel reservation system a semaphore with the counter
|
|
|
|
For example, when modeling a hotel reservation system a semaphore with the counter
|
|
|
|
equal to the total number of available rooms could be created. Each time a room
|
|
|
|
equal to the total number of available rooms could be created. Each time a room
|
|
|
|
is reserved, the semaphore should be acquired by calling
|
|
|
|
is reserved, the semaphore should be acquired by calling wxSemaphore::Wait
|
|
|
|
wxSemaphore::Wait and each time a room is freed it should be
|
|
|
|
and each time a room is freed it should be released by calling wxSemaphore::Post.
|
|
|
|
released by calling wxSemaphore::Post.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@library{wxbase}
|
|
|
|
@library{wxbase}
|
|
|
|
@category{threading}
|
|
|
|
@category{threading}
|
|
|
@@ -779,9 +923,10 @@ class wxSemaphore
|
|
|
|
public:
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Specifying a @a maxcount of 0 actually makes wxSemaphore behave as if
|
|
|
|
Specifying a @a maxcount of 0 actually makes wxSemaphore behave as if
|
|
|
|
there is no upper limit. If maxcount is 1, the semaphore behaves almost as a
|
|
|
|
there is no upper limit. If @a maxcount is 1, the semaphore behaves almost as a
|
|
|
|
mutex (but unlike a mutex it can be released by a thread different from the one
|
|
|
|
mutex (but unlike a mutex it can be released by a thread different from the one
|
|
|
|
which acquired it).
|
|
|
|
which acquired it).
|
|
|
|
|
|
|
|
|
|
|
|
@a initialcount is the initial value of the semaphore which must be between
|
|
|
|
@a initialcount is the initial value of the semaphore which must be between
|
|
|
|
0 and @a maxcount (if it is not set to 0).
|
|
|
|
0 and @a maxcount (if it is not set to 0).
|
|
|
|
*/
|
|
|
|
*/
|
|
|
@@ -794,10 +939,14 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Increments the semaphore count and signals one of the waiting
|
|
|
|
Increments the semaphore count and signals one of the waiting
|
|
|
|
threads in an atomic way. Returns wxSEMA_OVERFLOW if the count
|
|
|
|
threads in an atomic way. Returns @e wxSEMA_OVERFLOW if the count
|
|
|
|
would increase the counter past the maximum.
|
|
|
|
would increase the counter past the maximum.
|
|
|
|
|
|
|
|
|
|
|
|
@return One of:
|
|
|
|
@return One of:
|
|
|
|
|
|
|
|
- wxSEMA_NO_ERROR: There was no error.
|
|
|
|
|
|
|
|
- wxSEMA_INVALID : Semaphore hasn't been initialized successfully.
|
|
|
|
|
|
|
|
- wxSEMA_OVERFLOW: Post() would increase counter past the max.
|
|
|
|
|
|
|
|
- wxSEMA_MISC_ERROR: Miscellaneous error.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxSemaError Post();
|
|
|
|
wxSemaError Post();
|
|
|
|
|
|
|
|
|
|
|
@@ -805,6 +954,10 @@ public:
|
|
|
|
Same as Wait(), but returns immediately.
|
|
|
|
Same as Wait(), but returns immediately.
|
|
|
|
|
|
|
|
|
|
|
|
@return One of:
|
|
|
|
@return One of:
|
|
|
|
|
|
|
|
- wxSEMA_NO_ERROR: There was no error.
|
|
|
|
|
|
|
|
- wxSEMA_INVALID: Semaphore hasn't been initialized successfully.
|
|
|
|
|
|
|
|
- wxSEMA_BUSY: Returned by TryWait() if Wait() would block, i.e. the count is zero.
|
|
|
|
|
|
|
|
- wxSEMA_MISC_ERROR: Miscellaneous error.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxSemaError TryWait();
|
|
|
|
wxSemaError TryWait();
|
|
|
|
|
|
|
|
|
|
|
@@ -813,8 +966,22 @@ public:
|
|
|
|
and then decrement it and return.
|
|
|
|
and then decrement it and return.
|
|
|
|
|
|
|
|
|
|
|
|
@return One of:
|
|
|
|
@return One of:
|
|
|
|
|
|
|
|
- wxSEMA_NO_ERROR: There was no error.
|
|
|
|
|
|
|
|
- wxSEMA_INVALID: Semaphore hasn't been initialized successfully.
|
|
|
|
|
|
|
|
- wxSEMA_MISC_ERROR: Miscellaneous error.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
wxSemaError Wait();
|
|
|
|
wxSemaError Wait();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
Same as Wait(), but with a timeout limit.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@return One of:
|
|
|
|
|
|
|
|
- wxSEMA_NO_ERROR: There was no error.
|
|
|
|
|
|
|
|
- wxSEMA_INVALID: Semaphore hasn't been initialized successfully.
|
|
|
|
|
|
|
|
- wxSEMA_TIMEOUT: Timeout occurred without receiving semaphore.
|
|
|
|
|
|
|
|
- wxSEMA_MISC_ERROR: Miscellaneous error.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
wxSemaError WaitTimeout(unsigned longtimeout_millis);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -822,12 +989,12 @@ public:
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@class wxMutexLocker
|
|
|
|
@class wxMutexLocker
|
|
|
|
|
|
|
|
|
|
|
|
This is a small helper class to be used with wxMutex
|
|
|
|
This is a small helper class to be used with wxMutex objects.
|
|
|
|
objects. A wxMutexLocker acquires a mutex lock in the constructor and releases
|
|
|
|
|
|
|
|
|
|
|
|
A wxMutexLocker acquires a mutex lock in the constructor and releases
|
|
|
|
(or unlocks) the mutex in the destructor making it much more difficult to
|
|
|
|
(or unlocks) the mutex in the destructor making it much more difficult to
|
|
|
|
forget to release a mutex (which, in general, will promptly lead to serious
|
|
|
|
forget to release a mutex (which, in general, will promptly lead to serious
|
|
|
|
problems). See wxMutex for an example of wxMutexLocker
|
|
|
|
problems). See wxMutex for an example of wxMutexLocker usage.
|
|
|
|
usage.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@library{wxbase}
|
|
|
|
@library{wxbase}
|
|
|
|
@category{threading}
|
|
|
|
@category{threading}
|
|
|
@@ -896,7 +1063,6 @@ enum wxMutexError
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@class wxMutex
|
|
|
|
@class wxMutex
|
|
|
|
|
|
|
|
|
|
|
@@ -980,8 +1146,8 @@ public:
|
|
|
|
~wxMutex();
|
|
|
|
~wxMutex();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Locks the mutex object. This is equivalent to
|
|
|
|
Locks the mutex object.
|
|
|
|
LockTimeout() with infinite timeout.
|
|
|
|
This is equivalent to LockTimeout() with infinite timeout.
|
|
|
|
|
|
|
|
|
|
|
|
@return One of: @c wxMUTEX_NO_ERROR, @c wxMUTEX_DEAD_LOCK.
|
|
|
|
@return One of: @c wxMUTEX_NO_ERROR, @c wxMUTEX_DEAD_LOCK.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|