/[pcsx2_0.9.7]/trunk/common/src/Utilities/wxAppWithHelpers.cpp
ViewVC logotype

Diff of /trunk/common/src/Utilities/wxAppWithHelpers.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

--- trunk/common/src/Utilities/wxAppWithHelpers.cpp	2010/09/07 03:24:11	31
+++ trunk/common/src/Utilities/wxAppWithHelpers.cpp	2010/09/07 11:08:22	62
@@ -28,6 +28,18 @@
 
 IMPLEMENT_DYNAMIC_CLASS( pxSimpleEvent, wxEvent )
 
+ConsoleLogSource_App::ConsoleLogSource_App()
+{
+	static const TraceLogDescriptor myDesc =
+	{
+		L"AppEvents",		L"App Events",
+		wxLt("Includes idle event processing and some other uncommon event usages.")
+	};
+	
+	m_Descriptor = &myDesc;
+}
+
+ConsoleLogSource_App pxConLog_App;
 
 void BaseDeletableObject::DoDeletion()
 {
@@ -103,35 +115,35 @@
 }
 
 // --------------------------------------------------------------------------------------
-//  pxInvokeActionEvent Implementations
+//  pxActionEvent Implementations
 // --------------------------------------------------------------------------------------
 
-IMPLEMENT_DYNAMIC_CLASS( pxInvokeActionEvent, wxEvent )
+IMPLEMENT_DYNAMIC_CLASS( pxActionEvent, wxEvent )
 
-pxInvokeActionEvent::pxInvokeActionEvent( SynchronousActionState* sema, int msgtype )
+pxActionEvent::pxActionEvent( SynchronousActionState* sema, int msgtype )
 	: wxEvent( 0, msgtype )
 {
 	m_state = sema;
 }
 
-pxInvokeActionEvent::pxInvokeActionEvent( SynchronousActionState& sema, int msgtype )
+pxActionEvent::pxActionEvent( SynchronousActionState& sema, int msgtype )
 	: wxEvent( 0, msgtype )
 {
 	m_state = &sema;
 }
 
-pxInvokeActionEvent::pxInvokeActionEvent( const pxInvokeActionEvent& src )
+pxActionEvent::pxActionEvent( const pxActionEvent& src )
 	: wxEvent( src )
 {
 	m_state = src.m_state;
 }
 
-void pxInvokeActionEvent::SetException( const BaseException& ex )
+void pxActionEvent::SetException( const BaseException& ex )
 {
 	SetException( ex.Clone() );
 }
 
-void pxInvokeActionEvent::SetException( BaseException* ex )
+void pxActionEvent::SetException( BaseException* ex )
 {
 	const wxString& prefix( wxsFormat(L"(%s) ", GetClassInfo()->GetClassName()) );
 	ex->DiagMsg() = prefix + ex->DiagMsg();
@@ -205,39 +217,39 @@
 }
 
 // --------------------------------------------------------------------------------------
-//  pxInvokeMethodEvent
+//  pxRpcEvent
 // --------------------------------------------------------------------------------------
 // Unlike pxPingEvent, the Semaphore belonging to this event is typically posted when the
 // invoked method is completed.  If the method can be executed in non-blocking fashion then
 // it should leave the semaphore postback NULL.
 //
-class pxInvokeMethodEvent : public pxInvokeActionEvent
+class pxRpcEvent : public pxActionEvent
 {
-	DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxInvokeMethodEvent)
+	DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxRpcEvent)
 
-	typedef pxInvokeActionEvent _parent;
+	typedef pxActionEvent _parent;
 
 protected:
 	void (*m_Method)();
 
 public:
-	virtual ~pxInvokeMethodEvent() throw() { }
-	virtual pxInvokeMethodEvent *Clone() const { return new pxInvokeMethodEvent(*this); }
+	virtual ~pxRpcEvent() throw() { }
+	virtual pxRpcEvent *Clone() const { return new pxRpcEvent(*this); }
 
-	explicit pxInvokeMethodEvent( void (*method)()=NULL, SynchronousActionState* sema=NULL )
-		: pxInvokeActionEvent( sema )
+	explicit pxRpcEvent( void (*method)()=NULL, SynchronousActionState* sema=NULL )
+		: pxActionEvent( sema )
 	{
 		m_Method = method;
 	}
 
-	explicit pxInvokeMethodEvent( void (*method)(), SynchronousActionState& sema )
-		: pxInvokeActionEvent( sema )
+	explicit pxRpcEvent( void (*method)(), SynchronousActionState& sema )
+		: pxActionEvent( sema )
 	{
 		m_Method = method;
 	}
 	
-	pxInvokeMethodEvent( const pxInvokeMethodEvent& src )
-		: pxInvokeActionEvent( src )
+	pxRpcEvent( const pxRpcEvent& src )
+		: pxActionEvent( src )
 	{
 		m_Method = src.m_Method;
 	}
@@ -254,7 +266,7 @@
 	}
 };
 
-IMPLEMENT_DYNAMIC_CLASS( pxInvokeMethodEvent, pxInvokeActionEvent )
+IMPLEMENT_DYNAMIC_CLASS( pxRpcEvent, pxActionEvent )
 
 // --------------------------------------------------------------------------------------
 //  pxExceptionEvent implementations
@@ -285,25 +297,59 @@
 // main thread.
 void wxAppWithHelpers::PostMethod( FnType_Void* method )
 {
-	PostEvent( pxInvokeMethodEvent( method ) );
+	PostEvent( pxRpcEvent( method ) );
 }
 
 // Posts a method to the main thread; non-blocking.  Post occurs even when called from the
 // main thread.
 void wxAppWithHelpers::PostIdleMethod( FnType_Void* method )
 {
-	pxInvokeMethodEvent evt( method );
+	pxRpcEvent evt( method );
 	AddIdleEvent( evt );
 }
 
-bool wxAppWithHelpers::PostMethodMyself( void (*method)() )
+// Invokes the specified void method, or posts the method to the main thread if the calling
+// thread is not Main.  Action is blocking.  For non-blocking method execution, use
+// AppRpc_TryInvokeAsync.
+//
+// This function works something like setjmp/longjmp, in that the return value indicates if the
+// function actually executed the specified method or not.
+//
+// Returns:
+//   FALSE if the method was not invoked (meaning this IS the main thread!)
+//   TRUE if the method was invoked.
+//
+
+bool wxAppWithHelpers::Rpc_TryInvoke( FnType_Void* method )
 {
 	if( wxThread::IsMain() ) return false;
-	PostEvent( pxInvokeMethodEvent( method ) );
+
+	SynchronousActionState sync;
+	PostEvent( pxRpcEvent( method, sync ) );
+	sync.WaitForResult();
+
 	return true;
 }
 
-void wxAppWithHelpers::ProcessMethod( void (*method)() )
+// Invokes the specified void method, or posts the method to the main thread if the calling
+// thread is not Main.  Action is non-blocking (asynchronous).  For blocking method execution,
+// use AppRpc_TryInvoke.
+//
+// This function works something like setjmp/longjmp, in that the return value indicates if the
+// function actually executed the specified method or not.
+//
+// Returns:
+//   FALSE if the method was not posted to the main thread (meaning this IS the main thread!)
+//   TRUE if the method was posted.
+//
+bool wxAppWithHelpers::Rpc_TryInvokeAsync( FnType_Void* method )
+{
+	if( wxThread::IsMain() ) return false;
+	PostEvent( pxRpcEvent( method ) );
+	return true;
+}
+
+void wxAppWithHelpers::ProcessMethod( FnType_Void* method )
 {
 	if( wxThread::IsMain() )
 	{
@@ -312,7 +358,7 @@
 	}
 
 	SynchronousActionState sync;
-	PostEvent( pxInvokeMethodEvent( method, sync ) );
+	PostEvent( pxRpcEvent( method, sync ) );
 	sync.WaitForResult();
 }
 
@@ -345,7 +391,7 @@
 	return _parent::ProcessEvent( *deleteMe );
 }
 
-bool wxAppWithHelpers::ProcessEvent( pxInvokeActionEvent& evt )
+bool wxAppWithHelpers::ProcessEvent( pxActionEvent& evt )
 {
 	if( wxThread::IsMain() )
 		return _parent::ProcessEvent( evt );
@@ -359,7 +405,7 @@
 	}
 }
 
-bool wxAppWithHelpers::ProcessEvent( pxInvokeActionEvent* evt )
+bool wxAppWithHelpers::ProcessEvent( pxActionEvent* evt )
 {
 	if( wxThread::IsMain() )
 	{
@@ -389,7 +435,11 @@
 	_parent::CleanUp();
 }
 
-void pxInvokeActionEvent::_DoInvokeEvent()
+// Executes the event with exception handling.  If the event throws an exception, the exception
+// will be neatly packaged and transported back to the thread that posted the event.
+// This function is virtual, however overloading it is not recommended.  Derrived classes
+// should overload InvokeEvent() instead.
+void pxActionEvent::_DoInvokeEvent()
 {
 	AffinityAssert_AllowFrom_MainUI();
 
@@ -412,6 +462,7 @@
 {
 	AffinityAssert_AllowFrom_MainUI();
 
+	pxAppLog.Write(L"(App) Executing command event synchronously...");
 	evt.SetEventType( evt.GetRealEventType() );
 
 	try {
@@ -468,36 +519,44 @@
 		lock.Release();
 		if( !Threading::AllowDeletions() && (deleteMe->GetEventType() == pxEvt_DeleteThread) )
 		{
+			// Threads that have active semaphores or mutexes (other threads are waiting on them) cannot
+			// be deleted because those mutex/sema objects will become invalid and cause the pending
+			// thread to crash.  So we disallow deletions when those waits are in action, and continue
+			// to postpone the deletion of the thread until such time that it is safe.
+
+			pxThreadLog.Write( ((pxThread*)((wxCommandEvent*)deleteMe.GetPtr())->GetClientData())->GetName(), L"Deletion postponed due to mutex or semaphore dependency." );
 			postponed.push_back(deleteMe.DetachPtr());
 		}
 		else
 		{
-			DbgCon.WriteLn( Color_Gray, L"(AppIdleQueue:%s) -> Dispatching event '%s'", action, deleteMe->GetClassInfo()->GetClassName() );
+			pxAppLog.Write( L"(AppIdleQueue%s) Dispatching event '%s'", action, deleteMe->GetClassInfo()->GetClassName() );
 			ProcessEvent( *deleteMe );		// dereference to prevent auto-deletion by ProcessEvent
 		}
 		lock.Acquire();
 	}
 
 	m_IdleEventQueue = postponed;
+	if( m_IdleEventQueue.size() > 0 )
+		pxAppLog.Write( L"(AppIdleQueue%s) %d events postponed due to dependencies.", action, m_IdleEventQueue.size() );
 }
 
 void wxAppWithHelpers::OnIdleEvent( wxIdleEvent& evt )
 {
 	m_IdleEventTimer.Stop();
-	IdleEventDispatcher( L"Idle" );
+	IdleEventDispatcher();
 }
 
 void wxAppWithHelpers::OnIdleEventTimeout( wxTimerEvent& evt )
 {
-	IdleEventDispatcher( L"Timeout" );
+	IdleEventDispatcher( L"[Timeout]" );
 }
 
 void wxAppWithHelpers::Ping()
 {
-	DbgCon.WriteLn( Color_Gray, L"App Event Ping Requested from %s thread.", pxGetCurrentThreadName().c_str() );
+	pxThreadLog.Write( pxGetCurrentThreadName().c_str(), L"App Event Ping Requested." );
 
 	SynchronousActionState sync;
-	pxInvokeActionEvent evt( sync );
+	pxActionEvent evt( sync );
 	AddIdleEvent( evt );
 	sync.WaitForResult();
 }
@@ -537,12 +596,12 @@
 	return ProcessCommand( NULL, evtType, intParam, longParam, stringParam );
 }
 
-void wxAppWithHelpers::PostAction( const pxInvokeActionEvent& evt )
+void wxAppWithHelpers::PostAction( const pxActionEvent& evt )
 {
 	PostEvent( evt );
 }
 
-void wxAppWithHelpers::ProcessAction( pxInvokeActionEvent& evt )
+void wxAppWithHelpers::ProcessAction( pxActionEvent& evt )
 {
 	if( !wxThread::IsMain() )
 	{
@@ -558,21 +617,21 @@
 
 void wxAppWithHelpers::DeleteObject( BaseDeletableObject& obj )
 {
-	pxAssume( !obj.IsBeingDeleted() );
+	pxAssert( !obj.IsBeingDeleted() );
 	wxCommandEvent evt( pxEvt_DeleteObject );
 	evt.SetClientData( (void*)&obj );
 	AddIdleEvent( evt );
 }
 
-void wxAppWithHelpers::DeleteThread( PersistentThread& obj )
+void wxAppWithHelpers::DeleteThread( pxThread& obj )
 {
-	//pxAssume( obj.IsBeingDeleted() );
+	pxThreadLog.Write(obj.GetName(), L"Scheduling for deletion...");
 	wxCommandEvent evt( pxEvt_DeleteThread );
 	evt.SetClientData( (void*)&obj );
 	AddIdleEvent( evt );
 }
 
-typedef void (wxEvtHandler::*pxInvokeActionEventFunction)(pxInvokeActionEvent&);
+typedef void (wxEvtHandler::*pxInvokeActionEventFunction)(pxActionEvent&);
 
 bool wxAppWithHelpers::OnInit()
 {
@@ -594,7 +653,7 @@
 	return _parent::OnInit();
 }
 
-void wxAppWithHelpers::OnInvokeAction( pxInvokeActionEvent& evt )
+void wxAppWithHelpers::OnInvokeAction( pxActionEvent& evt )
 {
 	evt._DoInvokeEvent();		// wow this is easy!
 }
@@ -609,9 +668,14 @@
 // (thus we have a fairly automatic threaded exception system!)
 void wxAppWithHelpers::OnDeleteThread( wxCommandEvent& evt )
 {
-	ScopedPtr<PersistentThread> thr( (PersistentThread*)evt.GetClientData() );
-	if( !thr ) return;
+	ScopedPtr<pxThread> thr( (pxThread*)evt.GetClientData() );
+	if( !thr )
+	{
+		pxThreadLog.Write( L"null", L"OnDeleteThread: NULL thread object received (and ignored)." );
+		return;
+	}
 
+	pxThreadLog.Write(thr->GetName(), (wxString)L"Thread object deleted successfully" + (thr->HasPendingException() ? wxEmptyString : L"[exception pending!]"));
 	thr->RethrowException();
 }
 

 

  ViewVC Help
Powered by ViewVC 1.1.22