00001 //<<<<<< INCLUDES >>>>>> 00002 00003 #include "Iguana/Studio/interface/IgQtAppLoopService.h" 00004 #include "Iguana/Studio/interface/IgQtScheduledEventExecutor.h" 00005 #include "Iguana/Studio/interface/IgQtScheduledEvent.h" 00006 #include <classlib/utils/DebugAids.h> 00007 #include <qapplication.h> 00008 00009 //<<<<<< PRIVATE DEFINES >>>>>> 00010 //<<<<<< PRIVATE CONSTANTS >>>>>> 00011 //<<<<<< PRIVATE TYPES >>>>>> 00012 //<<<<<< PRIVATE VARIABLE DEFINITIONS >>>>>> 00013 //<<<<<< PUBLIC VARIABLE DEFINITIONS >>>>>> 00014 //<<<<<< CLASS STRUCTURE INITIALIZATION >>>>>> 00015 00016 IG_DEFINE_STATE_ELEMENT (IgQtAppLoopService, "Services/Qt/Main Loop"); 00017 00018 //<<<<<< PRIVATE FUNCTION DEFINITIONS >>>>>> 00019 //<<<<<< PUBLIC FUNCTION DEFINITIONS >>>>>> 00020 //<<<<<< MEMBER FUNCTION DEFINITIONS >>>>>> 00021 00022 IgQtAppLoopService::IgQtAppLoopService (IgState *state) 00023 : m_state (state), 00024 m_run (lat::CreateCallback (&defaultRunAction)), 00025 m_running (false), 00026 m_executor (new IgQtScheduledEventExecutor ()) 00027 { 00028 ASSERT (state); 00029 state->put (s_key, this); 00030 } 00031 00032 IgQtAppLoopService::~IgQtAppLoopService (void) 00033 { 00034 ASSERT (m_state); 00035 m_state->detach (s_key); 00036 m_executor->deleteLater (); 00037 } 00038 00039 void 00040 IgQtAppLoopService::prepare (lat::Callback action) 00041 { 00042 ASSERT (action); 00043 m_preparations.push_back (action); 00044 } 00045 00046 void 00047 IgQtAppLoopService::schedule (lat::Callback action) 00048 { 00049 ASSERT (action); 00050 QEvent *event = new IgQtScheduledEvent (action); 00051 QApplication::postEvent (m_executor, event); 00052 } 00053 00054 00055 00056 void 00057 IgQtAppLoopService::post (lat::Callback action) 00058 { 00059 ASSERT (action); 00060 m_post.push_back (action); 00061 } 00062 00063 void 00064 IgQtAppLoopService::recover (lat::Callback action) 00065 { 00066 ASSERT (action); 00067 m_recoveries.push_back (action); 00068 } 00069 00070 void 00071 IgQtAppLoopService::override (lat::Callback action) 00072 { 00073 ASSERT (action); 00074 m_run = action; 00075 } 00076 00077 void 00078 IgQtAppLoopService::run (void) 00079 { 00080 doPrepare (); 00081 doRun (); 00082 doPost (); 00083 } 00084 00085 bool 00086 IgQtAppLoopService::running (void) 00087 { 00088 return m_running; 00089 } 00090 00091 void 00092 IgQtAppLoopService::resume (void) 00093 { 00094 // FIXME: Or siglongjmp? See doRun for comments. 00095 longjmp (m_return, 1); 00096 } 00097 00098 void 00099 IgQtAppLoopService::doPrepare (void) 00100 { 00101 std::list<lat::Callback>::iterator i = m_preparations.begin (); 00102 for ( ; i != m_preparations.end (); ++i) 00103 (*i) (); 00104 } 00105 00106 void 00107 IgQtAppLoopService::doRun (void) 00108 { 00109 // FIXME: Use sigsetjmp instead of setjmp to restore signal 00110 // blocking masks? But then we'll have to know about all that 00111 // stuff... but then again, we'll have to know about restoring 00112 // signal masks otherwise. See DDD for code. 00113 if (setjmp (m_return)) 00114 { 00115 m_running = false; 00116 // FIXME: do recoveries as detailed in `iguana' 00117 doResume (); 00118 } 00119 00120 ASSERT (m_run); 00121 m_running = true; 00122 m_run (); 00123 } 00124 00125 void 00126 IgQtAppLoopService::doResume (void) 00127 { 00128 std::list<lat::Callback>::iterator i = m_recoveries.begin (); 00129 for ( ; i != m_recoveries.end (); ++i) 00130 (*i) (); 00131 } 00132 00133 void 00134 IgQtAppLoopService::doPost (void) 00135 { 00136 std::list<lat::Callback>::iterator i = m_post.begin (); 00137 for ( ; i != m_post.end (); ++i) 00138 (*i) (); 00139 } 00140 00141 void 00142 IgQtAppLoopService::defaultRunAction (void) 00143 { 00144 qApp->exec (); 00145 }