Allow recursive calls to wxEventLoop::Yield().

There doesn't seem to be any reason to forbid them and this change allows
wxExecute() without wxEXEC_NOEVENTS to work without assertion failures when
called from inside wxYield().

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@77650 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2014-09-10 16:51:06 +00:00
parent 36f51e1479
commit dc65fa8d5a
4 changed files with 20 additions and 22 deletions

View File

@@ -44,6 +44,7 @@ All:
- Allow specifying custom comparator for wxSortedArrayString (Catalin Raceanu).
- Add wxDateTime::GetWeekBasedYear().
- Specialize std::hash<> for wxString when using C++11.
- Allow recursive calls to wxYield().
Unix:

View File

@@ -145,8 +145,8 @@ public:
// process all currently pending events right now
//
// it is an error to call Yield() recursively unless the value of
// onlyIfNeeded is true
// if onlyIfNeeded is true, returns false without doing anything else if
// we're already inside Yield()
//
// WARNING: this function is dangerous as it can lead to unexpected
// reentrancies (i.e. when called from an event handler it
@@ -162,7 +162,7 @@ public:
// returns true if the main thread is inside a Yield() call
virtual bool IsYielding() const
{ return m_isInsideYield; }
{ return m_yieldLevel != 0; }
// returns true if events of the given event category should be immediately
// processed inside a wxApp::Yield() call or rather should be queued for
@@ -214,8 +214,10 @@ protected:
// should we exit the loop?
bool m_shouldExit;
// YieldFor() helpers:
bool m_isInsideYield;
// incremented each time on entering Yield() and decremented on leaving it
int m_yieldLevel;
// the argument of the last call to YieldFor()
long m_eventsToProcessInsideYield;
private:

View File

@@ -224,7 +224,6 @@ public:
user to perform actions which are not compatible with the current task.
Disabling menu items or whole menus during processing can avoid unwanted
reentrance of code: see ::wxSafeYield for a better function.
You can avoid unwanted reentrancies also using IsYielding().
Note that Yield() will not flush the message logs. This is intentional as
calling Yield() is usually done to quickly update the screen and popping up
@@ -232,10 +231,9 @@ public:
messages immediately (otherwise it will be done during the next idle loop
iteration), call wxLog::FlushActive.
Calling Yield() recursively is normally an error and an assert failure is
raised in debug build if such situation is detected. However if the
@a onlyIfNeeded parameter is @true, the method will just silently
return @false instead.
If @a onlyIfNeeded parameter is @true and the flow control is already
inside Yield(), i.e. IsYielding() returns @true, the method just
silently returns @false and doesn't do anything.
*/
bool Yield(bool onlyIfNeeded = false);

View File

@@ -34,7 +34,7 @@ wxEventLoopBase::wxEventLoopBase()
{
m_isInsideRun = false;
m_shouldExit = false;
m_isInsideYield = false;
m_yieldLevel = 0;
m_eventsToProcessInsideYield = wxEVT_CATEGORY_ALL;
}
@@ -100,15 +100,8 @@ bool wxEventLoopBase::ProcessIdle()
bool wxEventLoopBase::Yield(bool onlyIfNeeded)
{
if ( m_isInsideYield )
{
if ( !onlyIfNeeded )
{
wxFAIL_MSG( wxT("wxYield called recursively" ) );
}
if ( onlyIfNeeded && IsYielding() )
return false;
}
return YieldFor(wxEVT_CATEGORY_ALL);
}
@@ -124,10 +117,14 @@ bool wxEventLoopBase::YieldFor(long eventsToProcess)
#endif // wxUSE_THREADS
// set the flag and don't forget to reset it before returning
m_isInsideYield = true;
m_eventsToProcessInsideYield = eventsToProcess;
const int yieldLevelOld = m_yieldLevel;
const long eventsToProcessOld = m_eventsToProcessInsideYield;
wxON_BLOCK_EXIT_SET(m_isInsideYield, false);
m_yieldLevel++;
wxON_BLOCK_EXIT_SET(m_yieldLevel, yieldLevelOld);
m_eventsToProcessInsideYield = eventsToProcess;
wxON_BLOCK_EXIT_SET(m_eventsToProcessInsideYield, eventsToProcessOld);
#if wxUSE_LOG
// disable log flushing from here because a call to wxYield() shouldn't