mirror of https://github.com/PCSX2/pcsx2.git
Added some hourglass cursors for various things; renamed more Semaphore and Mutex APIs (I'm too indecisive >_<)
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2109 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
4e69680c81
commit
376a2c94b1
|
@ -170,8 +170,8 @@ namespace Threading
|
||||||
void Post();
|
void Post();
|
||||||
void Post( int multiple );
|
void Post( int multiple );
|
||||||
|
|
||||||
void WaitRaw();
|
void WaitWithoutYield();
|
||||||
bool WaitRaw( const wxTimeSpan& timeout );
|
bool WaitWithoutYield( const wxTimeSpan& timeout );
|
||||||
void WaitNoCancel();
|
void WaitNoCancel();
|
||||||
void WaitNoCancel( const wxTimeSpan& timeout );
|
void WaitNoCancel( const wxTimeSpan& timeout );
|
||||||
int Count();
|
int Count();
|
||||||
|
@ -199,8 +199,8 @@ namespace Threading
|
||||||
bool TryAcquire();
|
bool TryAcquire();
|
||||||
void Release();
|
void Release();
|
||||||
|
|
||||||
void FullBlockingAcquire();
|
void AcquireWithoutYield();
|
||||||
bool FullBlockingAcquire( const wxTimeSpan& timeout );
|
bool AcquireWithoutYield( const wxTimeSpan& timeout );
|
||||||
|
|
||||||
void Wait();
|
void Wait();
|
||||||
bool Wait( const wxTimeSpan& timeout );
|
bool Wait( const wxTimeSpan& timeout );
|
||||||
|
|
|
@ -15,7 +15,11 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#if wxUSE_GUI
|
||||||
|
|
||||||
#include "Dependencies.h"
|
#include "Dependencies.h"
|
||||||
|
#include "ScopedPtr.h"
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxGuiTools.h
|
// wxGuiTools.h
|
||||||
|
@ -122,6 +126,53 @@ protected:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// MoreStockCursors
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Because (inexplicably) the ArrowWait cursor isn't in wxWidgets stock list.
|
||||||
|
//
|
||||||
|
class MoreStockCursors
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
ScopedPtr<wxCursor> m_arrowWait;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MoreStockCursors() { }
|
||||||
|
virtual ~MoreStockCursors() throw() { }
|
||||||
|
const wxCursor& GetArrowWait();
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BusyCursorType
|
||||||
|
{
|
||||||
|
Cursor_NotBusy,
|
||||||
|
Cursor_KindaBusy,
|
||||||
|
Cursor_ReallyBusy,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern MoreStockCursors StockCursors;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// ScopedBusyCursor
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// ... because wxWidgets wxBusyCursor doesn't really do proper nesting (doesn't let me
|
||||||
|
// override a partially-busy cursor with a really busy one)
|
||||||
|
|
||||||
|
class ScopedBusyCursor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
static std::stack<BusyCursorType> m_cursorStack;
|
||||||
|
static BusyCursorType m_defBusyType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScopedBusyCursor( BusyCursorType busytype );
|
||||||
|
virtual ~ScopedBusyCursor() throw();
|
||||||
|
|
||||||
|
static void SetDefault( BusyCursorType busytype );
|
||||||
|
static void SetManualBusyCursor( BusyCursorType busytype );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
extern bool pxIsValidWindowPosition( const wxWindow& window, const wxPoint& windowPos );
|
extern bool pxIsValidWindowPosition( const wxWindow& window, const wxPoint& windowPos );
|
||||||
extern wxRect wxGetDisplayArea();
|
extern wxRect wxGetDisplayArea();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "Threading.h"
|
#include "Threading.h"
|
||||||
#include "wxBaseTools.h"
|
#include "wxBaseTools.h"
|
||||||
|
#include "wxGuiTools.h"
|
||||||
#include "ThreadingInternal.h"
|
#include "ThreadingInternal.h"
|
||||||
|
|
||||||
namespace Threading
|
namespace Threading
|
||||||
|
@ -112,12 +113,13 @@ bool Threading::Mutex::RecreateIfLocked()
|
||||||
// if used from the main GUI thread, since it typically results in an unresponsive program.
|
// if used from the main GUI thread, since it typically results in an unresponsive program.
|
||||||
// Call this method directly only if you know the code in question will be run from threads
|
// Call this method directly only if you know the code in question will be run from threads
|
||||||
// other than the main thread.
|
// other than the main thread.
|
||||||
void Threading::Mutex::FullBlockingAcquire()
|
void Threading::Mutex::AcquireWithoutYield()
|
||||||
{
|
{
|
||||||
|
pxAssertMsg( !wxThread::IsMain(), "Unyielding mutex acquire issued from the main/gui thread. Please use Acquire() instead." );
|
||||||
pthread_mutex_lock( &m_mutex );
|
pthread_mutex_lock( &m_mutex );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Threading::Mutex::FullBlockingAcquire( const wxTimeSpan& timeout )
|
bool Threading::Mutex::AcquireWithoutYield( const wxTimeSpan& timeout )
|
||||||
{
|
{
|
||||||
wxDateTime megafail( wxDateTime::UNow() + timeout );
|
wxDateTime megafail( wxDateTime::UNow() + timeout );
|
||||||
const timespec fail = { megafail.GetTicks(), megafail.GetMillisecond() * 1000000 };
|
const timespec fail = { megafail.GetTicks(), megafail.GetMillisecond() * 1000000 };
|
||||||
|
@ -134,7 +136,7 @@ bool Threading::Mutex::TryAcquire()
|
||||||
return EBUSY != pthread_mutex_trylock( &m_mutex );
|
return EBUSY != pthread_mutex_trylock( &m_mutex );
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a wxApp-safe rendition of FullBlockingAcquire, which makes sure to execute pending app events
|
// This is a wxApp-safe rendition of AcquireWithoutYield, which makes sure to execute pending app events
|
||||||
// and messages *if* the lock is performed from the main GUI thread.
|
// and messages *if* the lock is performed from the main GUI thread.
|
||||||
//
|
//
|
||||||
// Exceptions:
|
// Exceptions:
|
||||||
|
@ -145,20 +147,20 @@ void Threading::Mutex::Acquire()
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
if( !wxThread::IsMain() || (wxTheApp == NULL) )
|
if( !wxThread::IsMain() || (wxTheApp == NULL) )
|
||||||
{
|
{
|
||||||
FullBlockingAcquire();
|
pthread_mutex_lock( &m_mutex );
|
||||||
}
|
}
|
||||||
else if( _WaitGui_RecursionGuard( "Mutex::Acquire" ) )
|
else if( _WaitGui_RecursionGuard( "Mutex::Acquire" ) )
|
||||||
{
|
{
|
||||||
if( !FullBlockingAcquire(def_deadlock_timeout) )
|
if( !AcquireWithoutYield(def_deadlock_timeout) )
|
||||||
throw Exception::ThreadTimedOut();
|
throw Exception::ThreadTimedOut();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while( !FullBlockingAcquire(def_yieldgui_interval) )
|
while( !AcquireWithoutYield(def_yieldgui_interval) )
|
||||||
wxTheApp->Yield( true );
|
wxTheApp->Yield( true );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
FullBlockingAcquire();
|
pthread_mutex_lock( &m_mutex );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,23 +172,26 @@ bool Threading::Mutex::Acquire( const wxTimeSpan& timeout )
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
if( !wxThread::IsMain() || (wxTheApp == NULL) )
|
if( !wxThread::IsMain() || (wxTheApp == NULL) )
|
||||||
{
|
{
|
||||||
return FullBlockingAcquire(timeout);
|
return AcquireWithoutYield(timeout);
|
||||||
}
|
}
|
||||||
else if( _WaitGui_RecursionGuard( "Mutex::Acquire(timeout)" ) )
|
else if( _WaitGui_RecursionGuard( "Mutex::Acquire(timeout)" ) )
|
||||||
{
|
{
|
||||||
|
ScopedBusyCursor hourglass( Cursor_ReallyBusy );
|
||||||
|
|
||||||
if( timeout > def_deadlock_timeout )
|
if( timeout > def_deadlock_timeout )
|
||||||
{
|
{
|
||||||
if( FullBlockingAcquire(def_deadlock_timeout) ) return true;
|
if( AcquireWithoutYield(def_deadlock_timeout) ) return true;
|
||||||
throw Exception::ThreadTimedOut();
|
throw Exception::ThreadTimedOut();
|
||||||
}
|
}
|
||||||
return FullBlockingAcquire( timeout );
|
return AcquireWithoutYield( timeout );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
||||||
wxTimeSpan countdown( (timeout) );
|
wxTimeSpan countdown( (timeout) );
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if( FullBlockingAcquire( def_yieldgui_interval ) ) break;
|
if( AcquireWithoutYield( def_yieldgui_interval ) ) break;
|
||||||
wxTheApp->Yield(true);
|
wxTheApp->Yield(true);
|
||||||
countdown -= def_yieldgui_interval;
|
countdown -= def_yieldgui_interval;
|
||||||
} while( countdown.GetMilliseconds() > 0 );
|
} while( countdown.GetMilliseconds() > 0 );
|
||||||
|
@ -198,7 +203,7 @@ bool Threading::Mutex::Acquire( const wxTimeSpan& timeout )
|
||||||
throw Exception::ThreadTimedOut();
|
throw Exception::ThreadTimedOut();
|
||||||
|
|
||||||
#else
|
#else
|
||||||
return FullBlockingAcquire();
|
return AcquireWithoutYield();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "Threading.h"
|
#include "Threading.h"
|
||||||
#include "wxBaseTools.h"
|
#include "wxBaseTools.h"
|
||||||
|
#include "wxGuiTools.h"
|
||||||
#include "ThreadingInternal.h"
|
#include "ThreadingInternal.h"
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -59,12 +60,13 @@ void Threading::Semaphore::Post( int multiple )
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::Semaphore::WaitRaw()
|
void Threading::Semaphore::WaitWithoutYield()
|
||||||
{
|
{
|
||||||
|
pxAssertMsg( !wxThread::IsMain(), "Unyielding semaphore wait issued from the main/gui thread. Please use Wait() instead." );
|
||||||
sem_wait( &m_sema );
|
sem_wait( &m_sema );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Threading::Semaphore::WaitRaw( const wxTimeSpan& timeout )
|
bool Threading::Semaphore::WaitWithoutYield( const wxTimeSpan& timeout )
|
||||||
{
|
{
|
||||||
wxDateTime megafail( wxDateTime::UNow() + timeout );
|
wxDateTime megafail( wxDateTime::UNow() + timeout );
|
||||||
const timespec fail = { megafail.GetTicks(), megafail.GetMillisecond() * 1000000 };
|
const timespec fail = { megafail.GetTicks(), megafail.GetMillisecond() * 1000000 };
|
||||||
|
@ -85,24 +87,26 @@ void Threading::Semaphore::Wait()
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
if( !wxThread::IsMain() || (wxTheApp == NULL) )
|
if( !wxThread::IsMain() || (wxTheApp == NULL) )
|
||||||
{
|
{
|
||||||
WaitRaw();
|
sem_wait( &m_sema );
|
||||||
}
|
}
|
||||||
else if( _WaitGui_RecursionGuard( "Semaphore::Wait" ) )
|
else if( _WaitGui_RecursionGuard( "Semaphore::Wait" ) )
|
||||||
{
|
{
|
||||||
if( !WaitRaw(def_yieldgui_interval) ) // default is 4 seconds
|
ScopedBusyCursor hourglass( Cursor_ReallyBusy );
|
||||||
|
if( !WaitWithoutYield(def_yieldgui_interval) ) // default is 4 seconds
|
||||||
throw Exception::ThreadTimedOut();
|
throw Exception::ThreadTimedOut();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while( !WaitRaw( def_yieldgui_interval ) )
|
ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
||||||
|
while( !WaitWithoutYield( def_yieldgui_interval ) )
|
||||||
wxTheApp->Yield( true );
|
wxTheApp->Yield( true );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
WaitRaw();
|
sem_wait( &m_sema );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a wxApp-safe implementation of WaitRaw, which makes sure and executes the App's
|
// This is a wxApp-safe implementation of WaitWithoutYield, which makes sure and executes the App's
|
||||||
// pending messages *if* the Wait is performed on the Main/GUI thread. This ensures that
|
// pending messages *if* the Wait is performed on the Main/GUI thread. This ensures that
|
||||||
// user input continues to be handled and that windows continue to repaint. If the Wait is
|
// user input continues to be handled and that windows continue to repaint. If the Wait is
|
||||||
// called from another thread, no message pumping is performed.
|
// called from another thread, no message pumping is performed.
|
||||||
|
@ -119,23 +123,25 @@ bool Threading::Semaphore::Wait( const wxTimeSpan& timeout )
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
if( !wxThread::IsMain() || (wxTheApp == NULL) )
|
if( !wxThread::IsMain() || (wxTheApp == NULL) )
|
||||||
{
|
{
|
||||||
return WaitRaw( timeout );
|
return WaitWithoutYield( timeout );
|
||||||
}
|
}
|
||||||
else if( _WaitGui_RecursionGuard( "Semaphore::Wait(timeout)" ) )
|
else if( _WaitGui_RecursionGuard( "Semaphore::Wait(timeout)" ) )
|
||||||
{
|
{
|
||||||
|
ScopedBusyCursor hourglass( Cursor_ReallyBusy );
|
||||||
if( timeout > def_deadlock_timeout )
|
if( timeout > def_deadlock_timeout )
|
||||||
{
|
{
|
||||||
if( WaitRaw(def_deadlock_timeout) ) return true;
|
if( WaitWithoutYield(def_deadlock_timeout) ) return true;
|
||||||
throw Exception::ThreadTimedOut();
|
throw Exception::ThreadTimedOut();
|
||||||
}
|
}
|
||||||
return WaitRaw( timeout );
|
return WaitWithoutYield( timeout );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
||||||
wxTimeSpan countdown( (timeout) );
|
wxTimeSpan countdown( (timeout) );
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if( WaitRaw( def_yieldgui_interval ) ) break;
|
if( WaitWithoutYield( def_yieldgui_interval ) ) break;
|
||||||
wxTheApp->Yield(true);
|
wxTheApp->Yield(true);
|
||||||
countdown -= def_yieldgui_interval;
|
countdown -= def_yieldgui_interval;
|
||||||
} while( countdown.GetMilliseconds() > 0 );
|
} while( countdown.GetMilliseconds() > 0 );
|
||||||
|
@ -143,7 +149,7 @@ bool Threading::Semaphore::Wait( const wxTimeSpan& timeout )
|
||||||
return countdown.GetMilliseconds() > 0;
|
return countdown.GetMilliseconds() > 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return WaitRaw( timeout );
|
return WaitWithoutYield( timeout );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,14 +158,14 @@ bool Threading::Semaphore::Wait( const wxTimeSpan& timeout )
|
||||||
// the stack and passed to another thread via GUI message or such, avoiding complications where
|
// the stack and passed to another thread via GUI message or such, avoiding complications where
|
||||||
// the thread might be canceled and the stack value becomes invalid.
|
// the thread might be canceled and the stack value becomes invalid.
|
||||||
//
|
//
|
||||||
// Performance note: this function has quite a bit more overhead compared to Semaphore::WaitRaw(), so
|
// Performance note: this function has quite a bit more overhead compared to Semaphore::WaitWithoutYield(), so
|
||||||
// consider manually specifying the thread as uncancellable and using WaitRaw() instead if you need
|
// consider manually specifying the thread as uncancellable and using WaitWithoutYield() instead if you need
|
||||||
// to do a lot of no-cancel waits in a tight loop worker thread, for example.
|
// to do a lot of no-cancel waits in a tight loop worker thread, for example.
|
||||||
void Threading::Semaphore::WaitNoCancel()
|
void Threading::Semaphore::WaitNoCancel()
|
||||||
{
|
{
|
||||||
int oldstate;
|
int oldstate;
|
||||||
pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldstate );
|
pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldstate );
|
||||||
WaitRaw();
|
WaitWithoutYield();
|
||||||
pthread_setcancelstate( oldstate, NULL );
|
pthread_setcancelstate( oldstate, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +173,7 @@ void Threading::Semaphore::WaitNoCancel( const wxTimeSpan& timeout )
|
||||||
{
|
{
|
||||||
int oldstate;
|
int oldstate;
|
||||||
pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldstate );
|
pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldstate );
|
||||||
WaitRaw( timeout );
|
WaitWithoutYield( timeout );
|
||||||
pthread_setcancelstate( oldstate, NULL );
|
pthread_setcancelstate( oldstate, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -496,7 +496,7 @@ void Threading::BaseTaskThread::WaitForResult()
|
||||||
#ifdef wxUSE_GUI
|
#ifdef wxUSE_GUI
|
||||||
m_post_TaskComplete.Wait();
|
m_post_TaskComplete.Wait();
|
||||||
#else
|
#else
|
||||||
m_post_TaskComplete.WaitRaw();
|
m_post_TaskComplete.WaitWithoutYield();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_post_TaskComplete.Reset();
|
m_post_TaskComplete.Reset();
|
||||||
|
@ -507,7 +507,7 @@ void Threading::BaseTaskThread::ExecuteTaskInThread()
|
||||||
while( !m_Done )
|
while( !m_Done )
|
||||||
{
|
{
|
||||||
// Wait for a job -- or get a pthread_cancel. I'm easy.
|
// Wait for a job -- or get a pthread_cancel. I'm easy.
|
||||||
m_sem_event.WaitRaw();
|
m_sem_event.WaitWithoutYield();
|
||||||
|
|
||||||
Task();
|
Task();
|
||||||
m_lock_TaskComplete.Acquire();
|
m_lock_TaskComplete.Acquire();
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
#include "wxGuiTools.h"
|
#include "wxGuiTools.h"
|
||||||
|
|
||||||
|
#include <wx/app.h>
|
||||||
#include <wx/window.h>
|
#include <wx/window.h>
|
||||||
|
|
||||||
// Returns FALSE if the window position is considered invalid, which means that it's title
|
// Returns FALSE if the window position is considered invalid, which means that it's title
|
||||||
|
@ -39,3 +40,70 @@ wxRect wxGetDisplayArea()
|
||||||
return wxRect( wxPoint(), wxGetDisplaySize() );
|
return wxRect( wxPoint(), wxGetDisplaySize() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// ScopedBusyCursor Implementations
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
std::stack<BusyCursorType> ScopedBusyCursor::m_cursorStack;
|
||||||
|
BusyCursorType ScopedBusyCursor::m_defBusyType;
|
||||||
|
|
||||||
|
ScopedBusyCursor::ScopedBusyCursor( BusyCursorType busytype )
|
||||||
|
{
|
||||||
|
pxAssert( wxTheApp != NULL );
|
||||||
|
|
||||||
|
BusyCursorType curtype = Cursor_NotBusy;
|
||||||
|
if( !m_cursorStack.empty() )
|
||||||
|
curtype = m_cursorStack.top();
|
||||||
|
|
||||||
|
if( curtype < busytype )
|
||||||
|
SetManualBusyCursor( curtype=busytype );
|
||||||
|
|
||||||
|
m_cursorStack.push( curtype );
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedBusyCursor::~ScopedBusyCursor() throw()
|
||||||
|
{
|
||||||
|
if( !pxAssert( wxTheApp != NULL ) ) return;
|
||||||
|
|
||||||
|
if( !pxAssert( !m_cursorStack.empty() ) )
|
||||||
|
{
|
||||||
|
SetManualBusyCursor( m_defBusyType );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BusyCursorType curtype = m_cursorStack.top();
|
||||||
|
m_cursorStack.pop();
|
||||||
|
|
||||||
|
if( m_cursorStack.empty() )
|
||||||
|
SetManualBusyCursor( m_defBusyType );
|
||||||
|
else if( m_cursorStack.top() != curtype )
|
||||||
|
SetManualBusyCursor( m_cursorStack.top() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScopedBusyCursor::SetDefault( BusyCursorType busytype )
|
||||||
|
{
|
||||||
|
if( busytype == m_defBusyType ) return;
|
||||||
|
m_defBusyType = busytype;
|
||||||
|
|
||||||
|
if( m_cursorStack.empty() )
|
||||||
|
SetManualBusyCursor( busytype );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScopedBusyCursor::SetManualBusyCursor( BusyCursorType busytype )
|
||||||
|
{
|
||||||
|
switch( busytype )
|
||||||
|
{
|
||||||
|
case Cursor_NotBusy: wxSetCursor( wxNullCursor ); break;
|
||||||
|
case Cursor_KindaBusy: wxSetCursor( StockCursors.GetArrowWait() ); break;
|
||||||
|
case Cursor_ReallyBusy: wxSetCursor( *wxHOURGLASS_CURSOR ); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wxCursor& MoreStockCursors::GetArrowWait()
|
||||||
|
{
|
||||||
|
if( !m_arrowWait )
|
||||||
|
m_arrowWait = new wxCursor( wxCURSOR_ARROWWAIT );
|
||||||
|
return *m_arrowWait;
|
||||||
|
}
|
||||||
|
|
||||||
|
MoreStockCursors StockCursors;
|
||||||
|
|
|
@ -246,7 +246,7 @@ void mtgsThreadObject::ExecuteTaskInThread()
|
||||||
// is very optimized (only 1 instruction test in most cases), so no point in trying
|
// is very optimized (only 1 instruction test in most cases), so no point in trying
|
||||||
// to avoid it.
|
// to avoid it.
|
||||||
|
|
||||||
m_sem_event.WaitRaw();
|
m_sem_event.WaitWithoutYield();
|
||||||
StateCheckInThread();
|
StateCheckInThread();
|
||||||
|
|
||||||
m_RingBufferIsBusy = true;
|
m_RingBufferIsBusy = true;
|
||||||
|
|
|
@ -232,7 +232,7 @@ void SysCoreThread::ExecuteTaskInThread()
|
||||||
|
|
||||||
tls_coreThread = this;
|
tls_coreThread = this;
|
||||||
|
|
||||||
m_sem_event.WaitRaw();
|
m_sem_event.WaitWithoutYield();
|
||||||
PCSX2_PAGEFAULT_PROTECT {
|
PCSX2_PAGEFAULT_PROTECT {
|
||||||
StateCheckInThread();
|
StateCheckInThread();
|
||||||
Cpu->Execute();
|
Cpu->Execute();
|
||||||
|
|
|
@ -40,7 +40,7 @@ void SysThreadBase::Start()
|
||||||
|
|
||||||
Sleep( 1 );
|
Sleep( 1 );
|
||||||
|
|
||||||
if( !m_ResumeEvent.WaitRaw( wxTimeSpan(0, 0, 1, 500) ) )
|
if( !m_ResumeEvent.WaitWithoutYield( wxTimeSpan(0, 0, 1, 500) ) )
|
||||||
{
|
{
|
||||||
RethrowException();
|
RethrowException();
|
||||||
if( pxAssertDev( m_ExecMode == ExecMode_Closing, "Unexpected thread status during SysThread startup." ) )
|
if( pxAssertDev( m_ExecMode == ExecMode_Closing, "Unexpected thread status during SysThread startup." ) )
|
||||||
|
@ -103,16 +103,19 @@ bool SysThreadBase::Suspend( bool isBlocking )
|
||||||
{
|
{
|
||||||
ScopedLock locker( m_ExecModeMutex );
|
ScopedLock locker( m_ExecModeMutex );
|
||||||
|
|
||||||
// Check again -- status could have changed since above.
|
switch( m_ExecMode )
|
||||||
if( m_ExecMode == ExecMode_Closed ) return false;
|
|
||||||
|
|
||||||
if( m_ExecMode == ExecMode_Pausing || m_ExecMode == ExecMode_Paused )
|
|
||||||
throw Exception::CancelEvent( "Another thread is pausing the VM state." );
|
|
||||||
|
|
||||||
if( m_ExecMode == ExecMode_Opened )
|
|
||||||
{
|
{
|
||||||
m_ExecMode = ExecMode_Closing;
|
// Check again -- status could have changed since above.
|
||||||
retval = true;
|
case ExecMode_Closed: return false;
|
||||||
|
|
||||||
|
case ExecMode_Pausing:
|
||||||
|
case ExecMode_Paused:
|
||||||
|
throw Exception::CancelEvent( "Another thread is pausing the VM state." );
|
||||||
|
|
||||||
|
case ExecMode_Opened:
|
||||||
|
m_ExecMode = ExecMode_Closing;
|
||||||
|
retval = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxAssertDev( m_ExecMode == ExecMode_Closing, "ExecMode should be nothing other than Closing..." );
|
pxAssertDev( m_ExecMode == ExecMode_Closing, "ExecMode should be nothing other than Closing..." );
|
||||||
|
@ -198,7 +201,7 @@ void SysThreadBase::Resume()
|
||||||
// The entire state coming out of a Wait is indeterminate because of user input
|
// The entire state coming out of a Wait is indeterminate because of user input
|
||||||
// and pending messages being handled. So after each call we do some seemingly redundant
|
// and pending messages being handled. So after each call we do some seemingly redundant
|
||||||
// sanity checks against m_ExecMode/m_Running status, and if something doesn't feel
|
// sanity checks against m_ExecMode/m_Running status, and if something doesn't feel
|
||||||
// right, we should abort.
|
// right, we should abort; the user may have canceled the action before it even finished.
|
||||||
|
|
||||||
switch( m_ExecMode )
|
switch( m_ExecMode )
|
||||||
{
|
{
|
||||||
|
@ -206,10 +209,6 @@ void SysThreadBase::Resume()
|
||||||
|
|
||||||
case ExecMode_NoThreadYet:
|
case ExecMode_NoThreadYet:
|
||||||
{
|
{
|
||||||
/*static int __Guard = 0;
|
|
||||||
RecursionGuard guard( __Guard );
|
|
||||||
if( guard.IsReentrant() ) return;*/
|
|
||||||
|
|
||||||
Start();
|
Start();
|
||||||
if( !m_running || (m_ExecMode == ExecMode_NoThreadYet) )
|
if( !m_running || (m_ExecMode == ExecMode_NoThreadYet) )
|
||||||
throw Exception::ThreadCreationError();
|
throw Exception::ThreadCreationError();
|
||||||
|
@ -290,7 +289,7 @@ void SysThreadBase::StateCheckInThread()
|
||||||
|
|
||||||
case ExecMode_Paused:
|
case ExecMode_Paused:
|
||||||
while( m_ExecMode == ExecMode_Paused )
|
while( m_ExecMode == ExecMode_Paused )
|
||||||
m_ResumeEvent.WaitRaw();
|
m_ResumeEvent.WaitWithoutYield();
|
||||||
|
|
||||||
m_RunningLock.Acquire();
|
m_RunningLock.Acquire();
|
||||||
OnResumeInThread( false );
|
OnResumeInThread( false );
|
||||||
|
@ -307,7 +306,7 @@ void SysThreadBase::StateCheckInThread()
|
||||||
|
|
||||||
case ExecMode_Closed:
|
case ExecMode_Closed:
|
||||||
while( m_ExecMode == ExecMode_Closed )
|
while( m_ExecMode == ExecMode_Closed )
|
||||||
m_ResumeEvent.WaitRaw();
|
m_ResumeEvent.WaitWithoutYield();
|
||||||
|
|
||||||
m_RunningLock.Acquire();
|
m_RunningLock.Acquire();
|
||||||
OnResumeInThread( true );
|
OnResumeInThread( true );
|
||||||
|
|
|
@ -29,6 +29,8 @@ AppCoreThread::~AppCoreThread() throw()
|
||||||
|
|
||||||
void AppCoreThread::Reset()
|
void AppCoreThread::Reset()
|
||||||
{
|
{
|
||||||
|
ScopedBusyCursor::SetDefault( Cursor_KindaBusy );
|
||||||
|
|
||||||
_parent::Reset();
|
_parent::Reset();
|
||||||
|
|
||||||
wxCommandEvent evt( pxEVT_CoreThreadStatus );
|
wxCommandEvent evt( pxEVT_CoreThreadStatus );
|
||||||
|
@ -38,6 +40,7 @@ void AppCoreThread::Reset()
|
||||||
|
|
||||||
bool AppCoreThread::Suspend( bool isBlocking )
|
bool AppCoreThread::Suspend( bool isBlocking )
|
||||||
{
|
{
|
||||||
|
ScopedBusyCursor::SetDefault( Cursor_KindaBusy );
|
||||||
bool retval = _parent::Suspend( isBlocking );
|
bool retval = _parent::Suspend( isBlocking );
|
||||||
|
|
||||||
// Clear the sticky key statuses, because hell knows what'll change while the PAD
|
// Clear the sticky key statuses, because hell knows what'll change while the PAD
|
||||||
|
@ -67,6 +70,7 @@ void AppCoreThread::Resume()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScopedBusyCursor::SetDefault( Cursor_KindaBusy );
|
||||||
_parent::Resume();
|
_parent::Resume();
|
||||||
|
|
||||||
if( m_ExecMode != ExecMode_Opened )
|
if( m_ExecMode != ExecMode_Opened )
|
||||||
|
|
|
@ -138,6 +138,7 @@ void Pcsx2App::Ping() const
|
||||||
void Pcsx2App::OnCoreThreadStatus( wxCommandEvent& evt )
|
void Pcsx2App::OnCoreThreadStatus( wxCommandEvent& evt )
|
||||||
{
|
{
|
||||||
m_evtsrc_CoreThreadStatus.Dispatch( evt );
|
m_evtsrc_CoreThreadStatus.Dispatch( evt );
|
||||||
|
ScopedBusyCursor::SetDefault( Cursor_NotBusy );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pcsx2App::OnSemaphorePing( wxCommandEvent& evt )
|
void Pcsx2App::OnSemaphorePing( wxCommandEvent& evt )
|
||||||
|
@ -497,9 +498,11 @@ void Pcsx2App::SysExecute( CDVD_SourceType cdvdsrc, const wxString& elf_override
|
||||||
|
|
||||||
// This message performs actual system execution (as dictated by SysExecute variants).
|
// This message performs actual system execution (as dictated by SysExecute variants).
|
||||||
// It is implemented as a message handler so that it can be triggered in response to
|
// It is implemented as a message handler so that it can be triggered in response to
|
||||||
// the completion of other dependent activites, namely loading plugins.
|
// the completion of other dependent activities, namely loading plugins.
|
||||||
void Pcsx2App::OnSysExecute( wxCommandEvent& evt )
|
void Pcsx2App::OnSysExecute( wxCommandEvent& evt )
|
||||||
{
|
{
|
||||||
|
CoreThread.ReleaseResumeLock();
|
||||||
|
|
||||||
if( sys_resume_lock > 0 )
|
if( sys_resume_lock > 0 )
|
||||||
{
|
{
|
||||||
Console.WriteLn( "SysExecute: State is locked, ignoring Execute request!" );
|
Console.WriteLn( "SysExecute: State is locked, ignoring Execute request!" );
|
||||||
|
@ -520,7 +523,6 @@ void Pcsx2App::OnSysExecute( wxCommandEvent& evt )
|
||||||
if( !CoreThread.HasValidState() )
|
if( !CoreThread.HasValidState() )
|
||||||
CoreThread.SetElfOverride( _sysexec_elf_override );
|
CoreThread.SetElfOverride( _sysexec_elf_override );
|
||||||
|
|
||||||
CoreThread.ReleaseResumeLock();
|
|
||||||
CoreThread.Resume();
|
CoreThread.Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,6 +530,7 @@ void Pcsx2App::OnSysExecute( wxCommandEvent& evt )
|
||||||
void Pcsx2App::SysReset()
|
void Pcsx2App::SysReset()
|
||||||
{
|
{
|
||||||
CoreThread.Reset();
|
CoreThread.Reset();
|
||||||
|
CoreThread.ReleaseResumeLock();
|
||||||
m_CorePlugins = NULL;
|
m_CorePlugins = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -410,8 +410,8 @@ namespace Panels
|
||||||
SafeList<EnumeratedPluginInfo> Results; // array of plugin results.
|
SafeList<EnumeratedPluginInfo> Results; // array of plugin results.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PluginSelectorPanel& m_master;
|
PluginSelectorPanel& m_master;
|
||||||
|
ScopedBusyCursor m_hourglass;
|
||||||
public:
|
public:
|
||||||
virtual ~EnumThread() throw()
|
virtual ~EnumThread() throw()
|
||||||
{
|
{
|
||||||
|
|
|
@ -545,6 +545,7 @@ Panels::PluginSelectorPanel::EnumThread::EnumThread( PluginSelectorPanel& master
|
||||||
PersistentThread()
|
PersistentThread()
|
||||||
, Results( master.FileCount(), L"PluginSelectorResults" )
|
, Results( master.FileCount(), L"PluginSelectorResults" )
|
||||||
, m_master( master )
|
, m_master( master )
|
||||||
|
, m_hourglass( Cursor_KindaBusy )
|
||||||
{
|
{
|
||||||
Results.MatchLengthToAllocatedSize();
|
Results.MatchLengthToAllocatedSize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,10 +93,10 @@ public:
|
||||||
PluginManager* Result;
|
PluginManager* Result;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxString m_folders[PluginId_Count];
|
wxString m_folders[PluginId_Count];
|
||||||
|
ScopedBusyCursor m_hourglass;
|
||||||
public:
|
public:
|
||||||
LoadPluginsTask( const wxString (&folders)[PluginId_Count] ) : Result( NULL )
|
LoadPluginsTask( const wxString (&folders)[PluginId_Count] ) : Result( NULL ), m_hourglass( Cursor_KindaBusy )
|
||||||
{
|
{
|
||||||
for(int i=0; i<PluginId_Count; ++i )
|
for(int i=0; i<PluginId_Count; ++i )
|
||||||
m_folders[i] = folders[i];
|
m_folders[i] = folders[i];
|
||||||
|
|
Loading…
Reference in New Issue