// Name: thread.h
// Purpose: interface of all thread-related wxWidgets classes
// Author: wxWidgets team
-// RCS-ID: $Id$
-// Licence: wxWindows license
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
{
m_mutex = mutex;
m_condition = condition;
-
- Create();
}
virtual ExitCode Entry()
*/
wxCondError Wait();
+ /**
+ Waits until the condition is signalled and the associated condition true.
+
+ This is a convenience overload that may be used to ignore spurious
+ awakenings while waiting for a specific condition to become true.
+
+ Equivalent to
+ @code
+ while ( !predicate() )
+ {
+ wxCondError e = Wait();
+ if ( e != wxCOND_NO_ERROR )
+ return e;
+ }
+ return wxCOND_NO_ERROR;
+ @endcode
+
+ The predicate would typically be a C++11 lambda:
+ @code
+ condvar.Wait([]{return value == 1;});
+ @endcode
+
+ @since 3.0
+ */
+ template<typename Functor>
+ wxCondError Wait(const Functor& predicate);
+
/**
Waits until the condition is signalled or the timeout has elapsed.
Example:
@code
- wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);
+ wxDECLARE_EVENT(myEVT_THREAD_UPDATE, wxThreadEvent);
class MyFrame : public wxFrame, public wxThreadHelper
{
char m_data[1024];
wxCriticalSection m_dataCS; // protects field above
- DECLARE_EVENT_TABLE()
+ wxDECLARE_EVENT_TABLE();
};
- wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent)
- BEGIN_EVENT_TABLE(MyFrame, wxFrame)
- EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_UPDATE, MyFrame::OnThreadUpdate)
+ wxDEFINE_EVENT(myEVT_THREAD_UPDATE, wxThreadEvent)
+ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
+ EVT_THREAD(wxID_ANY, myEVT_THREAD_UPDATE, MyFrame::OnThreadUpdate)
EVT_CLOSE(MyFrame::OnClose)
- END_EVENT_TABLE()
+ wxEND_EVENT_TABLE()
void MyFrame::DoStartALongTask()
{
download_chunk(buffer, 1024); // this takes time...
{
- // ensure noone reads m_data while we write it
+ // ensure no one reads m_data while we write it
wxCriticalSectionLocker lock(m_dataCS);
memcpy(m_data+offset, buffer, 1024);
offset += 1024;
*/
virtual ExitCode Entry() = 0;
+ /**
+ Callback called by Delete() before actually deleting the thread.
+
+ This function can be overridden by the derived class to perform some
+ specific task when the thread is gracefully destroyed. Notice that it
+ will be executed in the context of the thread that called Delete() and
+ <b>not</b> in this thread's context.
+
+ TestDestroy() will be true for the thread before OnDelete() gets
+ executed.
+
+ @since 2.9.2
+
+ @see OnKill()
+ */
+ virtual void OnDelete();
+
+ /**
+ Callback called by Kill() before actually killing the thread.
+
+ This function can be overridden by the derived class to perform some
+ specific task when the thread is terminated. Notice that it will be
+ executed in the context of the thread that called Kill() and <b>not</b>
+ in this thread's context.
+
+ @since 2.9.2
+
+ @see OnDelete()
+ */
+ virtual void OnKill();
+
/**
@deprecated
Use CreateThread() instead.
Finally, you should try to use wxCriticalSectionLocker class whenever
possible instead of directly using wxCriticalSection for the same reasons
- wxMutexLocker is preferrable to wxMutex - please see wxMutex for an example.
+ wxMutexLocker is preferable to wxMutex - please see wxMutex for an example.
@library{wxbase}
@category{threading}
*/
void Enter();
+ /**
+ Try to enter the critical section (same as trying to lock a mutex).
+ If it can't, immediately returns false.
+
+ @since 2.9.3
+ */
+ bool TryEnter();
+
/**
Leave the critical section allowing other threads use the global data
protected by it. There is no error return for this function.
void Leave();
};
+/**
+ The possible thread wait types.
+
+ @since 2.9.2
+*/
+enum wxThreadWait
+{
+ /**
+ No events are processed while waiting.
+
+ This is the default under all platforms except for wxMSW.
+ */
+ wxTHREAD_WAIT_BLOCK,
+
+ /**
+ Yield for event dispatching while waiting.
+
+ This flag is dangerous as it exposes the program using it to unexpected
+ reentrancies in the same way as calling wxYield() function does so you
+ are strongly advised to avoid its use and not wait for the thread
+ termination from the main (GUI) thread at all to avoid making your
+ application unresponsive.
+
+ Also notice that this flag is not portable as it is only implemented in
+ wxMSW and simply ignored under the other platforms.
+ */
+ wxTHREAD_WAIT_YIELD,
+
+ /**
+ Default wait mode for wxThread::Wait() and wxThread::Delete().
+
+ For compatibility reasons, the default wait mode is currently
+ wxTHREAD_WAIT_YIELD if WXWIN_COMPATIBILITY_2_8 is defined (and it is
+ by default). However, as mentioned above, you're strongly encouraged to
+ not use wxTHREAD_WAIT_YIELD and pass wxTHREAD_WAIT_BLOCK to wxThread
+ method explicitly.
+ */
+ wxTHREAD_WAIT_DEFAULT = wxTHREAD_WAIT_YIELD
+};
+
/**
The possible thread kinds.
*/
wxTHREAD_MISC_ERROR
};
-/**
- Defines the interval of priority
-*/
-enum
-{
- WXTHREAD_MIN_PRIORITY = 0u,
- WXTHREAD_DEFAULT_PRIORITY = 50u,
- WXTHREAD_MAX_PRIORITY = 100u
-};
-
-
/**
@class wxThread
@section thread_types Types of wxThreads
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 POSIX thread API. This is different from the Win32 API
where all threads are joinable.
- By default wxThreads in wxWidgets use the @b detached behavior.
+ By default wxThreads in wxWidgets use the @b detached behaviour.
Detached threads delete themselves once they have completed, either by themselves
when they complete processing or through a call to Delete(), and thus
@b must be created on the heap (through the new operator, for example).
MyThread *m_pThread;
wxCriticalSection m_pThreadCS; // protects the m_pThread pointer
- DECLARE_EVENT_TABLE()
+ wxDECLARE_EVENT_TABLE();
};
- BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_CLOSE(MyFrame::OnClose)
EVT_MENU(Minimal_Start, MyFrame::DoStartThread)
EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_UPDATE, MyFrame::OnThreadUpdate)
EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_COMPLETED, MyFrame::OnThreadCompletion)
- END_EVENT_TABLE()
+ wxEND_EVENT_TABLE()
wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_COMPLETED, wxThreadEvent)
wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent)
{
m_pThread = new MyThread(this);
- if ( m_pThread->Create() != wxTHREAD_NO_ERROR )
+ if ( m_pThread->Run() != 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.
- }
+ // 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.
}
wxThread::ExitCode MyThread::Entry()
if (m_pThread) // does the thread still exist?
{
- m_out.Printf("MYFRAME: deleting thread");
+ wxMessageOutputDebug().Printf("MYFRAME: deleting thread");
if (m_pThread->Delete() != wxTHREAD_NO_ERROR )
wxLogError("Can't delete the thread!");
All threads other than the "main application thread" (the one running
wxApp::OnInit() or the one your main function runs in, for example) are
- considered "secondary threads". These include all threads created by Create()
- or the corresponding constructors.
+ considered "secondary threads".
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.
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
IsRunning(), only to find that their application has run into problems
- because the thread is using the default behavior (i.e. it's @b detached) and
+ because the thread is using the default behaviour (i.e. it's @b detached) and
has already deleted itself.
Naturally, they instead attempt to use joinable threads in place of the previous
- behavior. However, polling a wxThread for when it has ended is in general a
+ behaviour. However, polling a wxThread for when it has ended is in general a
bad idea - in fact calling a routine on any running wxThread should be avoided
if possible. Instead, find a way to notify yourself when the thread has ended.
/**
This constructor creates a new detached (default) or joinable C++
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 Run() method.
The possible values for @a kind parameters are:
- @b wxTHREAD_DETACHED - Creates a detached thread.
to it (Ignored on platforms that don't support setting it explicitly,
eg. Unix system without @c pthread_attr_setstacksize).
- If you do not specify the stack size,the system's default value is used.
+ If you do not specify the stack size, the system's default value is used.
+
+ @note
+ It is not necessary to call this method since 2.9.5, Run() will create
+ the thread internally. You only need to call Create() if you need to do
+ something with the thread (e.g. pass its ID to an external library)
+ before it starts.
@warning
It is a good idea to explicitly specify a value as systems'
performance issues on those systems with small default stack since those
typically use fully committed memory for the stack.
On the contrary, if you use a lot of threads (say several hundred),
- virtual adress space can get tight unless you explicitly specify a
+ virtual address space can get tight unless you explicitly specify a
smaller amount of thread stack space for each thread.
@return One of:
Calling Delete() gracefully terminates a @b detached thread, either when
the thread calls TestDestroy() or when it finishes processing.
+ @param rc
+ The thread exit code, if rc is not NULL.
+
+ @param waitMode
+ As described in wxThreadWait documentation, wxTHREAD_WAIT_BLOCK
+ should be used as the wait mode even although currently
+ wxTHREAD_WAIT_YIELD is for compatibility reasons. This parameter is
+ new in wxWidgets 2.9.2.
+
@note
This function works on a joinable thread but in that case makes
the TestDestroy() function of the thread return @true and then
See @ref thread_deletion for a broader explanation of this routine.
*/
- wxThreadError Delete(void** rc = NULL);
+ wxThreadError Delete(ExitCode *rc = NULL,
+ wxThreadWait waitMode = wxTHREAD_WAIT_BLOCK);
/**
Returns the number of system CPUs or -1 if the value is unknown.
/**
Gets the thread identifier: this is a platform dependent number that uniquely
identifies the thread throughout the system during its existence
- (i.e. the thread identifiers may be reused).
+ (i.e.\ the thread identifiers may be reused).
*/
wxThreadIdType GetId() const;
static wxThreadIdType GetMainId();
/**
- Gets the priority of the thread, between zero and 100.
+ Gets the priority of the thread, between 0 (lowest) and 100 (highest).
- The following priorities are defined:
- - @b WXTHREAD_MIN_PRIORITY: 0
- - @b WXTHREAD_DEFAULT_PRIORITY: 50
- - @b WXTHREAD_MAX_PRIORITY: 100
+ @see SetPriority()
*/
unsigned int GetPriority() const;
/**
- 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
detached ones as the latter delete themselves and so when the real thread is
wxThreadError Resume();
/**
- Starts the thread execution. Should be called after Create().
+ Starts the thread execution.
Note that once you Run() a @b detached thread, @e any function call you do
on the thread pointer (you must allocate it on the heap) is @e "unsafe";
of detached threads.
This function can only be called from another thread context.
+
+ Finally, note that once a thread has completed and its Entry() function
+ returns, you cannot call Run() on it again (an assert will fail in debug
+ builds or @c wxTHREAD_RUNNING will be returned in release builds).
*/
wxThreadError Run();
static bool SetConcurrency(size_t level);
/**
- Sets the priority of the thread, between 0 and 100.
- It can only be set after calling Create() but before calling Run().
+ Sets the priority of the thread, between 0 (lowest) and 100 (highest).
- The following priorities are defined:
- - @b WXTHREAD_MIN_PRIORITY: 0
- - @b WXTHREAD_DEFAULT_PRIORITY: 50
- - @b WXTHREAD_MAX_PRIORITY: 100
+ The following symbolic constants can be used in addition to raw
+ values in 0..100 range:
+ - @c wxPRIORITY_MIN: 0
+ - @c wxPRIORITY_DEFAULT: 50
+ - @c wxPRIORITY_MAX: 100
*/
void SetPriority(unsigned int priority);
This function can only be called from another thread context.
+ @param flags
+ As described in wxThreadWait documentation, wxTHREAD_WAIT_BLOCK
+ should be used as the wait mode even although currently
+ wxTHREAD_WAIT_YIELD is for compatibility reasons. This parameter is
+ new in wxWidgets 2.9.2.
+
See @ref thread_deletion for a broader explanation of this routine.
*/
- ExitCode Wait();
+ ExitCode Wait(wxThreadWait flags = wxTHREAD_WAIT_BLOCK);
/**
Give the rest of the thread's time-slice to the system allowing the other