/[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

revision 31 by william, Tue Sep 7 03:24:11 2010 UTC revision 62 by william, Tue Sep 7 11:08:22 2010 UTC
# Line 28  DEFINE_EVENT_TYPE( pxEvt_SynchronousComm Line 28  DEFINE_EVENT_TYPE( pxEvt_SynchronousComm
28    
29  IMPLEMENT_DYNAMIC_CLASS( pxSimpleEvent, wxEvent )  IMPLEMENT_DYNAMIC_CLASS( pxSimpleEvent, wxEvent )
30    
31    ConsoleLogSource_App::ConsoleLogSource_App()
32    {
33            static const TraceLogDescriptor myDesc =
34            {
35                    L"AppEvents",           L"App Events",
36                    wxLt("Includes idle event processing and some other uncommon event usages.")
37            };
38            
39            m_Descriptor = &myDesc;
40    }
41    
42    ConsoleLogSource_App pxConLog_App;
43    
44  void BaseDeletableObject::DoDeletion()  void BaseDeletableObject::DoDeletion()
45  {  {
# Line 103  void SynchronousActionState::PostResult( Line 115  void SynchronousActionState::PostResult(
115  }  }
116    
117  // --------------------------------------------------------------------------------------  // --------------------------------------------------------------------------------------
118  //  pxInvokeActionEvent Implementations  //  pxActionEvent Implementations
119  // --------------------------------------------------------------------------------------  // --------------------------------------------------------------------------------------
120    
121  IMPLEMENT_DYNAMIC_CLASS( pxInvokeActionEvent, wxEvent )  IMPLEMENT_DYNAMIC_CLASS( pxActionEvent, wxEvent )
122    
123  pxInvokeActionEvent::pxInvokeActionEvent( SynchronousActionState* sema, int msgtype )  pxActionEvent::pxActionEvent( SynchronousActionState* sema, int msgtype )
124          : wxEvent( 0, msgtype )          : wxEvent( 0, msgtype )
125  {  {
126          m_state = sema;          m_state = sema;
127  }  }
128    
129  pxInvokeActionEvent::pxInvokeActionEvent( SynchronousActionState& sema, int msgtype )  pxActionEvent::pxActionEvent( SynchronousActionState& sema, int msgtype )
130          : wxEvent( 0, msgtype )          : wxEvent( 0, msgtype )
131  {  {
132          m_state = &sema;          m_state = &sema;
133  }  }
134    
135  pxInvokeActionEvent::pxInvokeActionEvent( const pxInvokeActionEvent& src )  pxActionEvent::pxActionEvent( const pxActionEvent& src )
136          : wxEvent( src )          : wxEvent( src )
137  {  {
138          m_state = src.m_state;          m_state = src.m_state;
139  }  }
140    
141  void pxInvokeActionEvent::SetException( const BaseException& ex )  void pxActionEvent::SetException( const BaseException& ex )
142  {  {
143          SetException( ex.Clone() );          SetException( ex.Clone() );
144  }  }
145    
146  void pxInvokeActionEvent::SetException( BaseException* ex )  void pxActionEvent::SetException( BaseException* ex )
147  {  {
148          const wxString& prefix( wxsFormat(L"(%s) ", GetClassInfo()->GetClassName()) );          const wxString& prefix( wxsFormat(L"(%s) ", GetClassInfo()->GetClassName()) );
149          ex->DiagMsg() = prefix + ex->DiagMsg();          ex->DiagMsg() = prefix + ex->DiagMsg();
# Line 205  void pxSynchronousCommandEvent::SetExcep Line 217  void pxSynchronousCommandEvent::SetExcep
217  }  }
218    
219  // --------------------------------------------------------------------------------------  // --------------------------------------------------------------------------------------
220  //  pxInvokeMethodEvent  //  pxRpcEvent
221  // --------------------------------------------------------------------------------------  // --------------------------------------------------------------------------------------
222  // Unlike pxPingEvent, the Semaphore belonging to this event is typically posted when the  // Unlike pxPingEvent, the Semaphore belonging to this event is typically posted when the
223  // invoked method is completed.  If the method can be executed in non-blocking fashion then  // invoked method is completed.  If the method can be executed in non-blocking fashion then
224  // it should leave the semaphore postback NULL.  // it should leave the semaphore postback NULL.
225  //  //
226  class pxInvokeMethodEvent : public pxInvokeActionEvent  class pxRpcEvent : public pxActionEvent
227  {  {
228          DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxInvokeMethodEvent)          DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxRpcEvent)
229    
230          typedef pxInvokeActionEvent _parent;          typedef pxActionEvent _parent;
231    
232  protected:  protected:
233          void (*m_Method)();          void (*m_Method)();
234    
235  public:  public:
236          virtual ~pxInvokeMethodEvent() throw() { }          virtual ~pxRpcEvent() throw() { }
237          virtual pxInvokeMethodEvent *Clone() const { return new pxInvokeMethodEvent(*this); }          virtual pxRpcEvent *Clone() const { return new pxRpcEvent(*this); }
238    
239          explicit pxInvokeMethodEvent( void (*method)()=NULL, SynchronousActionState* sema=NULL )          explicit pxRpcEvent( void (*method)()=NULL, SynchronousActionState* sema=NULL )
240                  : pxInvokeActionEvent( sema )                  : pxActionEvent( sema )
241          {          {
242                  m_Method = method;                  m_Method = method;
243          }          }
244    
245          explicit pxInvokeMethodEvent( void (*method)(), SynchronousActionState& sema )          explicit pxRpcEvent( void (*method)(), SynchronousActionState& sema )
246                  : pxInvokeActionEvent( sema )                  : pxActionEvent( sema )
247          {          {
248                  m_Method = method;                  m_Method = method;
249          }          }
250                    
251          pxInvokeMethodEvent( const pxInvokeMethodEvent& src )          pxRpcEvent( const pxRpcEvent& src )
252                  : pxInvokeActionEvent( src )                  : pxActionEvent( src )
253          {          {
254                  m_Method = src.m_Method;                  m_Method = src.m_Method;
255          }          }
# Line 254  protected: Line 266  protected:
266          }          }
267  };  };
268    
269  IMPLEMENT_DYNAMIC_CLASS( pxInvokeMethodEvent, pxInvokeActionEvent )  IMPLEMENT_DYNAMIC_CLASS( pxRpcEvent, pxActionEvent )
270    
271  // --------------------------------------------------------------------------------------  // --------------------------------------------------------------------------------------
272  //  pxExceptionEvent implementations  //  pxExceptionEvent implementations
# Line 285  IMPLEMENT_DYNAMIC_CLASS( wxAppWithHelper Line 297  IMPLEMENT_DYNAMIC_CLASS( wxAppWithHelper
297  // main thread.  // main thread.
298  void wxAppWithHelpers::PostMethod( FnType_Void* method )  void wxAppWithHelpers::PostMethod( FnType_Void* method )
299  {  {
300          PostEvent( pxInvokeMethodEvent( method ) );          PostEvent( pxRpcEvent( method ) );
301  }  }
302    
303  // Posts a method to the main thread; non-blocking.  Post occurs even when called from the  // Posts a method to the main thread; non-blocking.  Post occurs even when called from the
304  // main thread.  // main thread.
305  void wxAppWithHelpers::PostIdleMethod( FnType_Void* method )  void wxAppWithHelpers::PostIdleMethod( FnType_Void* method )
306  {  {
307          pxInvokeMethodEvent evt( method );          pxRpcEvent evt( method );
308          AddIdleEvent( evt );          AddIdleEvent( evt );
309  }  }
310    
311  bool wxAppWithHelpers::PostMethodMyself( void (*method)() )  // Invokes the specified void method, or posts the method to the main thread if the calling
312    // thread is not Main.  Action is blocking.  For non-blocking method execution, use
313    // AppRpc_TryInvokeAsync.
314    //
315    // This function works something like setjmp/longjmp, in that the return value indicates if the
316    // function actually executed the specified method or not.
317    //
318    // Returns:
319    //   FALSE if the method was not invoked (meaning this IS the main thread!)
320    //   TRUE if the method was invoked.
321    //
322    
323    bool wxAppWithHelpers::Rpc_TryInvoke( FnType_Void* method )
324  {  {
325          if( wxThread::IsMain() ) return false;          if( wxThread::IsMain() ) return false;
326          PostEvent( pxInvokeMethodEvent( method ) );  
327            SynchronousActionState sync;
328            PostEvent( pxRpcEvent( method, sync ) );
329            sync.WaitForResult();
330    
331          return true;          return true;
332  }  }
333    
334  void wxAppWithHelpers::ProcessMethod( void (*method)() )  // Invokes the specified void method, or posts the method to the main thread if the calling
335    // thread is not Main.  Action is non-blocking (asynchronous).  For blocking method execution,
336    // use AppRpc_TryInvoke.
337    //
338    // This function works something like setjmp/longjmp, in that the return value indicates if the
339    // function actually executed the specified method or not.
340    //
341    // Returns:
342    //   FALSE if the method was not posted to the main thread (meaning this IS the main thread!)
343    //   TRUE if the method was posted.
344    //
345    bool wxAppWithHelpers::Rpc_TryInvokeAsync( FnType_Void* method )
346    {
347            if( wxThread::IsMain() ) return false;
348            PostEvent( pxRpcEvent( method ) );
349            return true;
350    }
351    
352    void wxAppWithHelpers::ProcessMethod( FnType_Void* method )
353  {  {
354          if( wxThread::IsMain() )          if( wxThread::IsMain() )
355          {          {
# Line 312  void wxAppWithHelpers::ProcessMethod( vo Line 358  void wxAppWithHelpers::ProcessMethod( vo
358          }          }
359    
360          SynchronousActionState sync;          SynchronousActionState sync;
361          PostEvent( pxInvokeMethodEvent( method, sync ) );          PostEvent( pxRpcEvent( method, sync ) );
362          sync.WaitForResult();          sync.WaitForResult();
363  }  }
364    
# Line 345  bool wxAppWithHelpers::ProcessEvent( wxE Line 391  bool wxAppWithHelpers::ProcessEvent( wxE
391          return _parent::ProcessEvent( *deleteMe );          return _parent::ProcessEvent( *deleteMe );
392  }  }
393    
394  bool wxAppWithHelpers::ProcessEvent( pxInvokeActionEvent& evt )  bool wxAppWithHelpers::ProcessEvent( pxActionEvent& evt )
395  {  {
396          if( wxThread::IsMain() )          if( wxThread::IsMain() )
397                  return _parent::ProcessEvent( evt );                  return _parent::ProcessEvent( evt );
# Line 359  bool wxAppWithHelpers::ProcessEvent( pxI Line 405  bool wxAppWithHelpers::ProcessEvent( pxI
405          }          }
406  }  }
407    
408  bool wxAppWithHelpers::ProcessEvent( pxInvokeActionEvent* evt )  bool wxAppWithHelpers::ProcessEvent( pxActionEvent* evt )
409  {  {
410          if( wxThread::IsMain() )          if( wxThread::IsMain() )
411          {          {
# Line 389  void wxAppWithHelpers::CleanUp() Line 435  void wxAppWithHelpers::CleanUp()
435          _parent::CleanUp();          _parent::CleanUp();
436  }  }
437    
438  void pxInvokeActionEvent::_DoInvokeEvent()  // Executes the event with exception handling.  If the event throws an exception, the exception
439    // will be neatly packaged and transported back to the thread that posted the event.
440    // This function is virtual, however overloading it is not recommended.  Derrived classes
441    // should overload InvokeEvent() instead.
442    void pxActionEvent::_DoInvokeEvent()
443  {  {
444          AffinityAssert_AllowFrom_MainUI();          AffinityAssert_AllowFrom_MainUI();
445    
# Line 412  void wxAppWithHelpers::OnSynchronousComm Line 462  void wxAppWithHelpers::OnSynchronousComm
462  {  {
463          AffinityAssert_AllowFrom_MainUI();          AffinityAssert_AllowFrom_MainUI();
464    
465            pxAppLog.Write(L"(App) Executing command event synchronously...");
466          evt.SetEventType( evt.GetRealEventType() );          evt.SetEventType( evt.GetRealEventType() );
467    
468          try {          try {
# Line 468  void wxAppWithHelpers::IdleEventDispatch Line 519  void wxAppWithHelpers::IdleEventDispatch
519                  lock.Release();                  lock.Release();
520                  if( !Threading::AllowDeletions() && (deleteMe->GetEventType() == pxEvt_DeleteThread) )                  if( !Threading::AllowDeletions() && (deleteMe->GetEventType() == pxEvt_DeleteThread) )
521                  {                  {
522                            // Threads that have active semaphores or mutexes (other threads are waiting on them) cannot
523                            // be deleted because those mutex/sema objects will become invalid and cause the pending
524                            // thread to crash.  So we disallow deletions when those waits are in action, and continue
525                            // to postpone the deletion of the thread until such time that it is safe.
526    
527                            pxThreadLog.Write( ((pxThread*)((wxCommandEvent*)deleteMe.GetPtr())->GetClientData())->GetName(), L"Deletion postponed due to mutex or semaphore dependency." );
528                          postponed.push_back(deleteMe.DetachPtr());                          postponed.push_back(deleteMe.DetachPtr());
529                  }                  }
530                  else                  else
531                  {                  {
532                          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() );
533                          ProcessEvent( *deleteMe );              // dereference to prevent auto-deletion by ProcessEvent                          ProcessEvent( *deleteMe );              // dereference to prevent auto-deletion by ProcessEvent
534                  }                  }
535                  lock.Acquire();                  lock.Acquire();
536          }          }
537    
538          m_IdleEventQueue = postponed;          m_IdleEventQueue = postponed;
539            if( m_IdleEventQueue.size() > 0 )
540                    pxAppLog.Write( L"(AppIdleQueue%s) %d events postponed due to dependencies.", action, m_IdleEventQueue.size() );
541  }  }
542    
543  void wxAppWithHelpers::OnIdleEvent( wxIdleEvent& evt )  void wxAppWithHelpers::OnIdleEvent( wxIdleEvent& evt )
544  {  {
545          m_IdleEventTimer.Stop();          m_IdleEventTimer.Stop();
546          IdleEventDispatcher( L"Idle" );          IdleEventDispatcher();
547  }  }
548    
549  void wxAppWithHelpers::OnIdleEventTimeout( wxTimerEvent& evt )  void wxAppWithHelpers::OnIdleEventTimeout( wxTimerEvent& evt )
550  {  {
551          IdleEventDispatcher( L"Timeout" );          IdleEventDispatcher( L"[Timeout]" );
552  }  }
553    
554  void wxAppWithHelpers::Ping()  void wxAppWithHelpers::Ping()
555  {  {
556          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." );
557    
558          SynchronousActionState sync;          SynchronousActionState sync;
559          pxInvokeActionEvent evt( sync );          pxActionEvent evt( sync );
560          AddIdleEvent( evt );          AddIdleEvent( evt );
561          sync.WaitForResult();          sync.WaitForResult();
562  }  }
# Line 537  sptr wxAppWithHelpers::ProcessCommand( i Line 596  sptr wxAppWithHelpers::ProcessCommand( i
596          return ProcessCommand( NULL, evtType, intParam, longParam, stringParam );          return ProcessCommand( NULL, evtType, intParam, longParam, stringParam );
597  }  }
598    
599  void wxAppWithHelpers::PostAction( const pxInvokeActionEvent& evt )  void wxAppWithHelpers::PostAction( const pxActionEvent& evt )
600  {  {
601          PostEvent( evt );          PostEvent( evt );
602  }  }
603    
604  void wxAppWithHelpers::ProcessAction( pxInvokeActionEvent& evt )  void wxAppWithHelpers::ProcessAction( pxActionEvent& evt )
605  {  {
606          if( !wxThread::IsMain() )          if( !wxThread::IsMain() )
607          {          {
# Line 558  void wxAppWithHelpers::ProcessAction( px Line 617  void wxAppWithHelpers::ProcessAction( px
617    
618  void wxAppWithHelpers::DeleteObject( BaseDeletableObject& obj )  void wxAppWithHelpers::DeleteObject( BaseDeletableObject& obj )
619  {  {
620          pxAssume( !obj.IsBeingDeleted() );          pxAssert( !obj.IsBeingDeleted() );
621          wxCommandEvent evt( pxEvt_DeleteObject );          wxCommandEvent evt( pxEvt_DeleteObject );
622          evt.SetClientData( (void*)&obj );          evt.SetClientData( (void*)&obj );
623          AddIdleEvent( evt );          AddIdleEvent( evt );
624  }  }
625    
626  void wxAppWithHelpers::DeleteThread( PersistentThread& obj )  void wxAppWithHelpers::DeleteThread( pxThread& obj )
627  {  {
628          //pxAssume( obj.IsBeingDeleted() );          pxThreadLog.Write(obj.GetName(), L"Scheduling for deletion...");
629          wxCommandEvent evt( pxEvt_DeleteThread );          wxCommandEvent evt( pxEvt_DeleteThread );
630          evt.SetClientData( (void*)&obj );          evt.SetClientData( (void*)&obj );
631          AddIdleEvent( evt );          AddIdleEvent( evt );
632  }  }
633    
634  typedef void (wxEvtHandler::*pxInvokeActionEventFunction)(pxInvokeActionEvent&);  typedef void (wxEvtHandler::*pxInvokeActionEventFunction)(pxActionEvent&);
635    
636  bool wxAppWithHelpers::OnInit()  bool wxAppWithHelpers::OnInit()
637  {  {
# Line 594  bool wxAppWithHelpers::OnInit() Line 653  bool wxAppWithHelpers::OnInit()
653          return _parent::OnInit();          return _parent::OnInit();
654  }  }
655    
656  void wxAppWithHelpers::OnInvokeAction( pxInvokeActionEvent& evt )  void wxAppWithHelpers::OnInvokeAction( pxActionEvent& evt )
657  {  {
658          evt._DoInvokeEvent();           // wow this is easy!          evt._DoInvokeEvent();           // wow this is easy!
659  }  }
# Line 609  void wxAppWithHelpers::OnDeleteObject( w Line 668  void wxAppWithHelpers::OnDeleteObject( w
668  // (thus we have a fairly automatic threaded exception system!)  // (thus we have a fairly automatic threaded exception system!)
669  void wxAppWithHelpers::OnDeleteThread( wxCommandEvent& evt )  void wxAppWithHelpers::OnDeleteThread( wxCommandEvent& evt )
670  {  {
671          ScopedPtr<PersistentThread> thr( (PersistentThread*)evt.GetClientData() );          ScopedPtr<pxThread> thr( (pxThread*)evt.GetClientData() );
672          if( !thr ) return;          if( !thr )
673            {
674                    pxThreadLog.Write( L"null", L"OnDeleteThread: NULL thread object received (and ignored)." );
675                    return;
676            }
677    
678            pxThreadLog.Write(thr->GetName(), (wxString)L"Thread object deleted successfully" + (thr->HasPendingException() ? wxEmptyString : L"[exception pending!]"));
679          thr->RethrowException();          thr->RethrowException();
680  }  }
681    

Legend:
Removed from v.31  
changed lines
  Added in v.62

  ViewVC Help
Powered by ViewVC 1.1.22