documented ExitCode typedef; revised wxThread and wxThreadHelper docs, also adding two usage examples; remove useless comment added by error in previous commits; linked threading overview from wxThread
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@56921 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -188,23 +188,6 @@ public:
|
|||||||
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
|
||||||
@@ -269,7 +252,8 @@ public:
|
|||||||
@class wxThreadHelper
|
@class wxThreadHelper
|
||||||
|
|
||||||
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, either detached or joinable (see wxThread for the differences).
|
||||||
|
By deriving from wxThreadHelper, a class can implement the thread
|
||||||
code in its own wxThreadHelper::Entry() method and easily share data and
|
code in its own wxThreadHelper::Entry() method and easily share data and
|
||||||
synchronization objects between the main thread and the worker thread.
|
synchronization objects between the main thread and the worker thread.
|
||||||
|
|
||||||
@@ -282,16 +266,74 @@ public:
|
|||||||
|
|
||||||
Ordinarily, a wxThread derived object would be created with the calculation
|
Ordinarily, a wxThread derived object would be created with the calculation
|
||||||
code implemented in wxThread::Entry. To access the inputs to 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.
|
the frame object would often need to pass a pointer to itself to the thread object.
|
||||||
Similarly, the frame object would hold a pointer 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
|
Shared data and synchronization objects could be stored in either object
|
||||||
though the object without the data would have to access the data through
|
though the object without the data would have to access the data through
|
||||||
a pointer.
|
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
|
||||||
associated pointers.
|
associated pointers.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
@code
|
||||||
|
class MyFrame : public wxFrame, public wxThreadHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyFrame() : wxThreadHelper(wxTHREAD_JOINABLE) {}
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
virtual ExitCode Entry()
|
||||||
|
{
|
||||||
|
// here we do our long task, periodically calling TestDestroy():
|
||||||
|
while (!TestDestroy())
|
||||||
|
{
|
||||||
|
// ...do another bit of work here...
|
||||||
|
|
||||||
|
// post an update message to the frame
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDestroy() returned true (which means the main thread
|
||||||
|
// asked us to terminate as soon as possible) or we ended the
|
||||||
|
// long task...
|
||||||
|
return (ExitCode)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~MyFrame()
|
||||||
|
{
|
||||||
|
// important: before terminating, we _must_ wait for our
|
||||||
|
// joinable thread to end, if it's running!
|
||||||
|
if (GetThread()->IsRunning())
|
||||||
|
GetThread()->Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
void DoStartALongTask();
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyFrame::DoStartALongTask()
|
||||||
|
{
|
||||||
|
// we want to start a long task, but we don't want our GUI to block
|
||||||
|
// while it's executed, so we use a thread to do it.
|
||||||
|
if (Create() != wxTHREAD_NO_ERROR)
|
||||||
|
{
|
||||||
|
wxLogError("Could not create the worker thread!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// go!
|
||||||
|
if (Run() != wxTHREAD_NO_ERROR)
|
||||||
|
{
|
||||||
|
wxLogError("Could not run the worker thread!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
@library{wxbase}
|
@library{wxbase}
|
||||||
@category{threading}
|
@category{threading}
|
||||||
|
|
||||||
@@ -301,12 +343,19 @@ class wxThreadHelper
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
This constructor simply initializes a member variable.
|
This constructor simply initializes internal member variables and tells
|
||||||
|
wxThreadHelper which type the thread internally managed should be.
|
||||||
*/
|
*/
|
||||||
wxThreadHelper(wxThreadKind kind = wxTHREAD_JOINABLE);
|
wxThreadHelper(wxThreadKind kind = wxTHREAD_JOINABLE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The destructor frees the resources associated with the thread.
|
The destructor frees the resources associated with the thread, forcing
|
||||||
|
it to terminate (it uses wxThread::Kill function).
|
||||||
|
|
||||||
|
Because of the wxThread::Kill unsafety, you should always wait
|
||||||
|
(with wxThread::Wait) for joinable threads to end or call wxThread::Delete
|
||||||
|
on detached threads, instead of relying on this destructor for stopping
|
||||||
|
the thread.
|
||||||
*/
|
*/
|
||||||
virtual ~wxThreadHelper();
|
virtual ~wxThreadHelper();
|
||||||
|
|
||||||
@@ -328,18 +377,21 @@ public:
|
|||||||
Creates a new thread.
|
Creates a new thread.
|
||||||
|
|
||||||
The thread object is created in the suspended state, and you
|
The thread object is created in the suspended state, and you
|
||||||
should call @ref wxThread::Run GetThread()-Run to start running it.
|
should call @ref wxThread::Run "GetThread()->Run()" to start running it.
|
||||||
|
|
||||||
You may optionally specify the stack size to be allocated to it (ignored
|
You may optionally specify the stack size to be allocated to it (ignored
|
||||||
on platforms that don't support setting it explicitly, eg. Unix).
|
on platforms that don't support setting it explicitly, eg. Unix).
|
||||||
|
|
||||||
|
Note that the type of the thread which is created is defined in the
|
||||||
|
constructor.
|
||||||
|
|
||||||
@return One of the ::wxThreadError enum values.
|
@return One of the ::wxThreadError enum values.
|
||||||
*/
|
*/
|
||||||
wxThreadError Create(unsigned int stackSize = 0);
|
wxThreadError Create(unsigned int stackSize = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This is a public function that returns the wxThread object
|
This is a public function that returns the wxThread object associated with
|
||||||
associated with the thread.
|
the thread.
|
||||||
*/
|
*/
|
||||||
wxThread* GetThread() const;
|
wxThread* GetThread() const;
|
||||||
};
|
};
|
||||||
@@ -464,10 +516,11 @@ enum
|
|||||||
|
|
||||||
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 critical sections (see wxCriticalSection)
|
synchronization objects such as mutexes (see wxMutex) or critical sections
|
||||||
is recommended. In addition, don't create global thread objects because they
|
(see wxCriticalSection) is recommended.
|
||||||
allocate memory in their constructor, which will cause problems for the memory
|
In addition, don't create global thread objects because they allocate memory
|
||||||
checking system.
|
in their constructor, which will cause problems for the memory checking system.
|
||||||
|
|
||||||
|
|
||||||
@section thread_types Types of wxThreads
|
@section thread_types Types of wxThreads
|
||||||
|
|
||||||
@@ -475,45 +528,177 @@ enum
|
|||||||
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.
|
||||||
|
|
||||||
By default wxThreads in wxWidgets use the detached behavior. Detached threads
|
By default wxThreads in wxWidgets use the @b detached behavior.
|
||||||
delete themselves once they have completed, either by themselves when they
|
Detached threads delete themselves once they have completed, either by themselves
|
||||||
complete processing or through a call to Delete(), and thus
|
when they complete processing or through a call to Delete(), and thus
|
||||||
must be created on the heap (through the new operator, for example).
|
@b must be created on the heap (through the new operator, for example).
|
||||||
Conversely, joinable threads do not delete themselves when they are done
|
|
||||||
|
Typically you'll want to store the instances of the detached wxThreads you
|
||||||
|
allocate, so that you can call functions on them.
|
||||||
|
Because of their nature however you'll need to always use a critical section
|
||||||
|
when accessing them:
|
||||||
|
|
||||||
|
@code
|
||||||
|
// declare a new type of event, to be used by our MyThread class:
|
||||||
|
extern const wxEventType wxEVT_COMMAND_MYTHREAD_COMPLETED;
|
||||||
|
|
||||||
|
class MyThread : public wxThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyThread(wxEvtHandler *handler) : wxThread(wxTHREAD_DETACHED)
|
||||||
|
{ m_pHandler = handler; }
|
||||||
|
|
||||||
|
ExitCode Entry()
|
||||||
|
{
|
||||||
|
while (!TestDestroy())
|
||||||
|
{
|
||||||
|
// ... do a bit of work...
|
||||||
|
}
|
||||||
|
|
||||||
|
// signal the event handler that this thread is going to be destroyed
|
||||||
|
// NOTE: here we assume that using the m_pHandler pointer is safe,
|
||||||
|
// (in this case it's assured by the MyFrame destructor)
|
||||||
|
wxQueueEvent(m_pHandler, new wxCommandEvent(wxEVT_COMMAND_MYTHREAD_COMPLETED));
|
||||||
|
|
||||||
|
return (ExitCode)0; // success
|
||||||
|
}
|
||||||
|
|
||||||
|
wxEvtHandler *m_pHandler;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MyFrame : public wxFrame
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
...
|
||||||
|
~MyFrame();
|
||||||
|
...
|
||||||
|
void DoStartThread();
|
||||||
|
void DoPauseThread();
|
||||||
|
|
||||||
|
// a resume routine would be mostly identic to DoPauseThread()
|
||||||
|
void DoResumeThread() { ... }
|
||||||
|
|
||||||
|
void OnThreadExit(wxCommandEvent&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MyThread *m_pThread;
|
||||||
|
|
||||||
|
// this is _required_ for writing safe code!
|
||||||
|
wxCriticalSection m_critSection;
|
||||||
|
};
|
||||||
|
|
||||||
|
void MyFrame::DoStartThread()
|
||||||
|
{
|
||||||
|
m_pThread = new wxThread();
|
||||||
|
|
||||||
|
if ( m_pThread->Create() != wxTHREAD_NO_ERROR )
|
||||||
|
{
|
||||||
|
wxLogError("Can't create the thread!");
|
||||||
|
delete m_pThread;
|
||||||
|
m_pThread = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_pThread->Run() != wxTHREAD_NO_ERROR )
|
||||||
|
{
|
||||||
|
wxLogError("Can't create the thread!");
|
||||||
|
delete m_pThread;
|
||||||
|
m_pThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// after the call to wxThread::Run(), the m_pThread pointer is "unsafe":
|
||||||
|
// at any moment the thread may cease to exist (because it completes its work).
|
||||||
|
// To avoid dangling pointers OnThreadExit() will set m_pThread
|
||||||
|
// to NULL when the thread dies.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyFrame::OnThreadExit(wxCommandEvent&)
|
||||||
|
{
|
||||||
|
// the thread just ended; make sure not to leave dangling pointers around
|
||||||
|
m_pThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyFrame::DoPauseThread()
|
||||||
|
{
|
||||||
|
// anytime we access the m_pThread pointer we must ensure that it won't
|
||||||
|
// be modified in the meanwhile; inside a critical section we are sure
|
||||||
|
// that we are the only thread running, so that's what we need.
|
||||||
|
wxCriticalSectionLocker enter(m_critSection);
|
||||||
|
|
||||||
|
if (m_pThread) // does the thread still exist?
|
||||||
|
{
|
||||||
|
// without a critical section, once reached this point it may happen
|
||||||
|
// that the OS scheduler gives control to the MyThread::Entry() function,
|
||||||
|
// which in turn may return (because it completes its work) making
|
||||||
|
// invalid the m_pThread pointer; the critical section above
|
||||||
|
// makes this code safe.
|
||||||
|
|
||||||
|
if (m_pThread->Pause() != wxTHREAD_NO_ERROR )
|
||||||
|
wxLogError("Can't pause the thread!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyFrame::~MyFrame()
|
||||||
|
{
|
||||||
|
wxCriticalSectionLocker enter(m_critSection);
|
||||||
|
|
||||||
|
if (m_pThread) // does the thread still exist?
|
||||||
|
{
|
||||||
|
if (m_pThread->Delete() != wxTHREAD_NO_ERROR )
|
||||||
|
wxLogError("Can't delete the thread!");
|
||||||
|
|
||||||
|
// as soon as we exit the critical section and the MyThread::Entry
|
||||||
|
// function calls TestDestroy(), the thread will exit and thus
|
||||||
|
// call OnExitThread(); we need to maintain MyFrame object alive
|
||||||
|
// until then:
|
||||||
|
wxEventLoopBase* p = wxEventLoopBase::GetActive();
|
||||||
|
while (p->Pending() && m_pThread)
|
||||||
|
p->Dispatch();
|
||||||
|
|
||||||
|
// the wxEVT_COMMAND_MYTHREAD_COMPLETED event was posted, we can
|
||||||
|
// safely exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
Conversely, @b joinable threads do not delete themselves when they are done
|
||||||
processing and as such are safe to create on the stack. Joinable threads
|
processing and as such are safe to create on the stack. Joinable threads
|
||||||
also provide the ability for one to get value it returned from Entry()
|
also provide the ability for one to get value it returned from Entry()
|
||||||
through Wait().
|
through Wait().
|
||||||
|
|
||||||
You shouldn't hurry to create all the threads joinable, however, because this
|
You shouldn't hurry to create all the threads joinable, however, because this
|
||||||
has a disadvantage as well: you @b must Wait() for a joinable thread or the
|
has a disadvantage as well: you @b must Wait() for a joinable thread or the
|
||||||
system resources used by it will never be freed, and you also must delete the
|
system resources used by it will never be freed, and you also must delete the
|
||||||
corresponding wxThread object yourself if you did not create it on the stack.
|
corresponding wxThread object yourself if you did not create it on the stack.
|
||||||
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
|
||||||
start a detached thread and it will terminate and destroy itself.
|
to start a detached thread and it will terminate and destroy itself.
|
||||||
|
|
||||||
|
|
||||||
@section thread_deletion wxThread Deletion
|
@section thread_deletion wxThread Deletion
|
||||||
|
|
||||||
Regardless of whether it has terminated or not, you should call Wait() on a
|
Regardless of whether it has terminated or not, you should call Wait() on a
|
||||||
joinable thread to release its memory, as outlined in @ref thread_types.
|
@b joinable thread to release its memory, as outlined in @ref thread_types.
|
||||||
If you created a joinable thread on the heap, remember to delete it manually
|
If you created a joinable thread on the heap, remember to delete it manually
|
||||||
with the @c delete operator or similar means as only detached threads handle
|
with the @c delete operator or similar means as only detached threads handle
|
||||||
this type of memory management.
|
this type of memory management.
|
||||||
|
|
||||||
Since detached threads delete themselves when they are finished processing,
|
Since @b 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
|
||||||
thread is still running and would like to end it, you may call Delete()
|
thread is still running and would like to end it, you may call Delete()
|
||||||
to gracefully end it (which implies that the thread will be deleted after
|
to gracefully end it (which implies that the thread will be deleted after
|
||||||
that call to Delete()). It should be implied that you should never attempt
|
that call to Delete()). It should be implied that you should @b never attempt
|
||||||
to delete a detached thread with the delete operator or similar means.
|
to delete a detached thread with the @c delete operator or similar means.
|
||||||
As mentioned, Wait() or Delete() attempts to gracefully terminate a
|
|
||||||
joinable and detached thread, respectively. It does this by waiting until
|
As mentioned, Wait() or Delete() functions attempt to gracefully terminate a
|
||||||
the thread in question calls TestDestroy() or ends processing (returns
|
joinable and a detached thread, respectively. They do this by waiting until
|
||||||
|
the thread in question calls TestDestroy() or ends processing (i.e. returns
|
||||||
from wxThread::Entry).
|
from wxThread::Entry).
|
||||||
|
|
||||||
Obviously, if the thread does call TestDestroy() and does not end the calling
|
Obviously, if the thread does call TestDestroy() and does not end, the
|
||||||
thread will come to halt. This is why it is important to call TestDestroy() in
|
thread which called Wait() or Delete() will come to halt.
|
||||||
the Entry() routine of your threads as often as possible.
|
This is why it's important to call TestDestroy() in the Entry() routine of
|
||||||
|
your threads as often as possible and immediately exit when it returns @true.
|
||||||
|
|
||||||
As a last resort you can end the thread immediately through Kill(). It is
|
As a last resort you can end the thread immediately through Kill(). It is
|
||||||
strongly recommended that you do not do this, however, as it does not free
|
strongly recommended that you do not do this, however, as it does not free
|
||||||
the resources associated with the object (although the wxThread object of
|
the resources associated with the object (although the wxThread object of
|
||||||
@@ -523,10 +708,10 @@ enum
|
|||||||
|
|
||||||
@section thread_secondary 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 running
|
||||||
wxApp::OnInit() or your main function runs in, for example) are considered
|
wxApp::OnInit() or the one your main function runs in, for example) are
|
||||||
"secondary threads". These include all threads created by Create() or the
|
considered "secondary threads". These include all threads created by Create()
|
||||||
corresponding constructors.
|
or the corresponding constructors.
|
||||||
|
|
||||||
GUI calls, such as those to a wxWindow or wxBitmap are explicitly not safe
|
GUI calls, such as those to a wxWindow or wxBitmap are explicitly not safe
|
||||||
at all in secondary threads and could end your application prematurely.
|
at all in secondary threads and could end your application prematurely.
|
||||||
@@ -537,7 +722,7 @@ enum
|
|||||||
A workaround for some wxWidgets ports is calling wxMutexGUIEnter()
|
A workaround for some wxWidgets ports is calling wxMutexGUIEnter()
|
||||||
before any GUI calls and then calling wxMutexGUILeave() afterwords. However,
|
before any GUI calls and then calling wxMutexGUILeave() afterwords. However,
|
||||||
the recommended way is to simply process the GUI calls in the main thread
|
the recommended way is to simply process the GUI calls in the main thread
|
||||||
through an event that is posted by either wxQueueEvent().
|
through an event that is posted by wxQueueEvent().
|
||||||
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.
|
||||||
|
|
||||||
@@ -547,15 +732,15 @@ enum
|
|||||||
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
|
||||||
because the thread is using the default behavior and has already deleted
|
because the thread is using the default behavior (i.e. it's @b detached) and
|
||||||
itself. Naturally, they instead attempt to use joinable threads in place
|
has already deleted itself.
|
||||||
of the previous behavior. However, polling a wxThread for when it has ended
|
Naturally, they instead attempt to use joinable threads in place of the previous
|
||||||
is in general a bad idea - in fact calling a routine on any running wxThread
|
behavior. However, polling a wxThread for when it has ended is in general a
|
||||||
should be avoided if possible. Instead, find a way to notify yourself when
|
bad idea - in fact calling a routine on any running wxThread should be avoided
|
||||||
the thread has ended.
|
if possible. Instead, find a way to notify yourself when 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 wxQueueEvent().
|
||||||
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 (see wxMutex) and/or other synchronization
|
a variable, possibly using mutexes (see wxMutex) and/or other synchronization
|
||||||
@@ -564,11 +749,17 @@ enum
|
|||||||
@library{wxbase}
|
@library{wxbase}
|
||||||
@category{threading}
|
@category{threading}
|
||||||
|
|
||||||
@see wxMutex, wxCondition, wxCriticalSection
|
@see wxThreadHelper, wxMutex, wxCondition, wxCriticalSection,
|
||||||
|
@ref overview_thread
|
||||||
*/
|
*/
|
||||||
class wxThread
|
class wxThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
The return type for the thread functions.
|
||||||
|
*/
|
||||||
|
typedef void* ExitCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
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 -
|
||||||
@@ -622,13 +813,13 @@ public:
|
|||||||
wxThreadError Create(unsigned int stackSize = 0);
|
wxThreadError Create(unsigned int stackSize = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Calling Delete() gracefully terminates a detached thread, either when
|
Calling Delete() gracefully terminates a @b detached thread, either when
|
||||||
the thread calls TestDestroy() or finished processing.
|
the thread calls TestDestroy() or when it finishes processing.
|
||||||
|
|
||||||
@note
|
@note
|
||||||
While this could work on a joinable thread you simply should not
|
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 them 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 thread_deletion for a broader explanation of this routine.
|
See @ref thread_deletion for a broader explanation of this routine.
|
||||||
*/
|
*/
|
||||||
@@ -813,11 +1004,11 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Waits for a joinable thread to terminate and returns the value the thread
|
Waits for a joinable thread to terminate and returns the value the thread
|
||||||
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(), this function doesn't cancel the thread in any way so the caller
|
||||||
long as it takes to the thread to exit.
|
waits for as long as it takes to the thread to exit.
|
||||||
|
|
||||||
You can only Wait() for joinable (not detached) threads.
|
You can only Wait() for @b 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 thread_deletion for a broader explanation of this routine.
|
See @ref thread_deletion for a broader explanation of this routine.
|
||||||
@@ -1084,7 +1275,7 @@ enum wxMutexError
|
|||||||
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 @e invariant).
|
||||||
|
|
||||||
@code
|
@code
|
||||||
// this variable has an "s_" prefix because it is static: seeing an "s_" in
|
// this variable has an "s_" prefix because it is static: seeing an "s_" in
|
||||||
@@ -1125,9 +1316,9 @@ enum wxMutexError
|
|||||||
|
|
||||||
Notice how wxMutexLocker was used in the second function to ensure that the
|
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
|
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
|
(because the destructor of the local object @e lock is always called).
|
||||||
this class instead of directly using wxMutex is, in general safer and is
|
Using this class instead of directly using wxMutex is, in general, safer
|
||||||
even more so if your program uses C++ exceptions.
|
and is even more so if your program uses C++ exceptions.
|
||||||
|
|
||||||
@library{wxbase}
|
@library{wxbase}
|
||||||
@category{threading}
|
@category{threading}
|
||||||
|
Reference in New Issue
Block a user