StartDrag() virtual methods changed. You will need to change them in your
derived renderer class too if you override them.
+- wxThread::Wait() and wxThread::Delete() used to dispatch the events while
+ waiting for the thread to exit in wxMSW. They still do it in default build
+ with WXWIN_COMPATIBILITY_2_8 defined but won't dispatch any events, i.e. the
+ default wait mode will become wxTHREAD_WAIT_BLOCK in the next wxWidgets
+ release so you are strongly encouraged to upgrade your code to stop relying
+ on this behaviour.
+
Changes in behaviour which may result in compilation errors
-----------------------------------------------------------
- Added wxIMAGE_OPTION_GIF_COMMENT to read and write GIF comments (troelsk).
- Added wxStack<> template class.
- Added precision parameter to wxString::From[C]Double().
+- Added wxThread::Wait() and Delete() "wait mode" parameter (Catalin Raceanu).
Unix:
// wait for the handle to be signaled, return WAIT_OBJECT_0 if it is or, in
// the GUI code, WAIT_OBJECT_0 + 1 if a Windows message arrived
- virtual WXDWORD WaitForThread(WXHANDLE hThread) = 0;
+ virtual WXDWORD WaitForThread(WXHANDLE hThread, int flags) = 0;
#ifndef __WXWINCE__
virtual wxTimerImpl *CreateTimerImpl(wxTimer *timer);
#endif
virtual bool DoMessageFromThreadWait();
- virtual WXDWORD WaitForThread(WXHANDLE hThread);
+ virtual WXDWORD WaitForThread(WXHANDLE hThread, int flags);
#ifndef __WXWINCE__
virtual bool CanUseStderr() { return true; }
virtual bool WriteToStderr(const wxString& text);
#endif
virtual bool DoMessageFromThreadWait();
virtual wxPortId GetToolkitVersion(int *majVer = NULL, int *minVer = NULL) const;
- virtual WXDWORD WaitForThread(WXHANDLE hThread);
+ virtual WXDWORD WaitForThread(WXHANDLE hThread, int flags);
#ifndef __WXWINCE__
virtual bool CanUseStderr();
wxTHREAD_JOINABLE
};
+enum wxThreadWait
+{
+ wxTHREAD_WAIT_BLOCK,
+ wxTHREAD_WAIT_YIELD, // process events while waiting; MSW only
+
+ // For compatibility reasons we use wxTHREAD_WAIT_YIELD by default as this
+ // was the default behaviour of wxMSW 2.8 but it should be avoided as it's
+ // dangerous and not portable.
+#if WXWIN_COMPATIBILITY_2_8
+ wxTHREAD_WAIT_DEFAULT = wxTHREAD_WAIT_YIELD
+#else
+ wxTHREAD_WAIT_DEFAULT = wxTHREAD_WAIT_BLOCK
+#endif
+};
+
// defines the interval of priority
enum
{
// does it!
//
// will fill the rc pointer with the thread exit code if it's !NULL
- wxThreadError Delete(ExitCode *rc = NULL);
+ wxThreadError Delete(ExitCode *rc = NULL,
+ wxThreadWait waitMode = wxTHREAD_WAIT_DEFAULT);
// waits for a joinable thread to finish and returns its exit code
//
// Returns (ExitCode)-1 on error (for example, if the thread is not
// joinable)
- ExitCode Wait();
+ ExitCode Wait(wxThreadWait waitMode = wxTHREAD_WAIT_DEFAULT);
// kills the thread without giving it any chance to clean up - should
// not be used under normal circumstances, use Delete() instead.
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.
*/
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.
This function can only be called from another thread context.
+ @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.
+
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
return evtLoop->Dispatch();
}
-DWORD wxGUIAppTraits::WaitForThread(WXHANDLE hThread)
+DWORD wxGUIAppTraits::WaitForThread(WXHANDLE hThread, int flags)
{
// We only ever dispatch messages from the main thread and, additionally,
// even from the main thread we shouldn't wait for the message if we don't
// have a running event loop as we would never remove them from the message
// queue then and so we would enter an infinite loop as
// MsgWaitForMultipleObjects() keeps returning WAIT_OBJECT_0 + 1.
- if ( !wxIsMainThread() || !wxEventLoop::GetActive() )
+ if ( flags == wxTHREAD_WAIT_BLOCK ||
+ !wxIsMainThread() ||
+ !wxEventLoop::GetActive() )
+ {
+ // Simple blocking wait.
return DoSimpleWaitForThread(hThread);
+ }
return ::MsgWaitForMultipleObjects
(
}
-WXDWORD wxConsoleAppTraits::WaitForThread(WXHANDLE hThread)
+WXDWORD wxConsoleAppTraits::WaitForThread(WXHANDLE hThread, int WXUNUSED(flags))
{
return DoSimpleWaitForThread(hThread);
}
// (politely, this is not Kill()!) to do it
wxThreadError WaitForTerminate(wxCriticalSection& cs,
wxThread::ExitCode *pRc,
+ wxThreadWait waitMode,
wxThread *threadToDelete = NULL);
// kill the thread unconditionally
wxThreadError
wxThreadInternal::WaitForTerminate(wxCriticalSection& cs,
wxThread::ExitCode *pRc,
+ wxThreadWait waitMode,
wxThread *threadToDelete)
{
// prevent the thread C++ object from disappearing as long as we are using
wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
if ( traits )
{
- result = traits->WaitForThread(m_hThread);
+ result = traits->WaitForThread(m_hThread, waitMode);
}
else // can't wait for the thread
{
// stopping thread
// ---------------
-wxThread::ExitCode wxThread::Wait()
+wxThread::ExitCode wxThread::Wait(wxThreadWait waitMode)
{
ExitCode rc = wxUIntToPtr(THREAD_ERROR_EXIT);
wxCHECK_MSG( !IsDetached(), rc,
wxT("wxThread::Wait(): can't wait for detached thread") );
- (void)m_internal->WaitForTerminate(m_critsect, &rc);
+ (void)m_internal->WaitForTerminate(m_critsect, &rc, waitMode);
return rc;
}
-wxThreadError wxThread::Delete(ExitCode *pRc)
+wxThreadError wxThread::Delete(ExitCode *pRc, wxThreadWait waitMode)
{
- return m_internal->WaitForTerminate(m_critsect, pRc, this);
+ return m_internal->WaitForTerminate(m_critsect, pRc, waitMode, this);
}
wxThreadError wxThread::Kill()
// stopping thread
// ---------------
-wxThread::ExitCode wxThread::Wait()
+wxThread::ExitCode wxThread::Wait(wxThreadWait waitMode)
{
// although under Windows we can wait for any thread, it's an error to
// wait for a detached one in wxWin API
wxCHECK_MSG( !IsDetached(), (ExitCode)-1,
wxT("can't wait for detached thread") );
ExitCode rc = (ExitCode)-1;
- (void)Delete(&rc);
+ (void)Delete(&rc, waitMode);
return(rc);
}
-wxThreadError wxThread::Delete(ExitCode *pRc)
+wxThreadError wxThread::Delete(ExitCode *pRc, wxThreadWait WXUNUSED(waitMode))
{
ExitCode rc = 0;
// exiting thread
// -----------------------------------------------------------------------------
-wxThread::ExitCode wxThread::Wait()
+wxThread::ExitCode wxThread::Wait(wxThreadWait WXUNUSED(waitMode))
{
wxCHECK_MSG( This() != this, (ExitCode)-1,
wxT("a thread can't wait for itself") );
return m_internal->GetExitCode();
}
-wxThreadError wxThread::Delete(ExitCode *rc)
+wxThreadError wxThread::Delete(ExitCode *rc, wxThreadWait WXUNUSED(waitMode))
{
wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
wxT("a thread can't delete itself") );
// stopping thread
// ---------------
-wxThread::ExitCode wxThread::Wait()
+wxThread::ExitCode wxThread::Wait(wxThreadWait WXUNUSED(waitMode))
{
return 0;
}
-wxThreadError wxThread::Delete(ExitCode *pRc)
+wxThreadError wxThread::Delete(ExitCode *pRc, wxThreadWait WXUNUSED(waitMode))
{
return wxTHREAD_NO_ERROR;
}
// exiting thread
// -----------------------------------------------------------------------------
-wxThread::ExitCode wxThread::Wait()
+wxThread::ExitCode wxThread::Wait(wxThreadWait WXUNUSED(waitMode))
{
wxCHECK_MSG( This() != this, (ExitCode)-1,
wxT("a thread can't wait for itself") );
return m_internal->GetExitCode();
}
-wxThreadError wxThread::Delete(ExitCode *rc)
+wxThreadError wxThread::Delete(ExitCode *rc, wxThreadWait WXUNUSED(waitMode))
{
wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
wxT("a thread can't delete itself") );