1 // SALOME SALOMEGUI : implementation of desktop and GUI kernel
3 // Copyright (C) 2005 CEA/DEN, EDF R&D
7 // File : PyInterp_Dispatcher.cxx
8 // Author : Sergey ANIKIN, OCC
13 #include <PyInterp_base.h>
14 #include <PyInterp_Dispatcher.h>
15 #include <PyInterp_Watcher.h>
17 #include <qapplication.h>
20 //#include <utilities.h>
23 PyInterp_Dispatcher* PyInterp_Dispatcher::myInstance = 0;
25 //////////////////////////////////////////////////////////
26 // class : PyInterp_Request
27 //////////////////////////////////////////////////////////
29 void PyInterp_Request::process()
34 //if ( !IsSync() && getListener() && getEvent() )
35 if ( getListener() && getEvent() )
40 void PyInterp_Request::safeExecute()
45 void PyInterp_Request::Destroy( PyInterp_Request* request )
47 // Lock and unlock the mutex to avoid errors on its deletion
48 request->myMutex.lock();
49 request->myMutex.unlock();
53 QEvent* PyInterp_Request::createEvent() const
55 return new PyInterp_Event( PyInterp_Event::NOTIFY, (PyInterp_Request*)this );
58 QEvent* PyInterp_Request::getEvent()
60 //if ( !myEvent && !IsSync() )
62 myEvent = createEvent();
66 void PyInterp_Request::postEvent()
68 #if QT_VERSION >= 0x030303
69 // MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.3.3")
70 QApplication::postEvent( getListener(), getEvent() );
72 // MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.0.5")
73 QThread::postEvent( getListener(), getEvent() );
77 void PyInterp_Request::setListener( QObject* o )
84 void PyInterp_LockRequest::safeExecute()
87 PyLockWrapper aLock = getInterp()->GetLockWrapper();
92 //////////////////////////////////////////////////////////
93 // class : PyInterp_Event
94 //////////////////////////////////////////////////////////
96 PyInterp_Event::~PyInterp_Event()
98 PyInterp_Request::Destroy( myRequest );
102 //////////////////////////////////////////////////////////
103 // class : PyInterp_Dispatcher
104 //////////////////////////////////////////////////////////
106 PyInterp_Dispatcher* PyInterp_Dispatcher::Get()
109 myInstance = new PyInterp_Dispatcher();
113 PyInterp_Dispatcher::PyInterp_Dispatcher()
116 myWatcher = new PyInterp_Watcher();
119 PyInterp_Dispatcher::~PyInterp_Dispatcher()
121 // Clear the request queue
124 for ( std::list<PyInterp_Request*>::iterator it = myQueue.begin(); it != myQueue.end(); ++it )
125 PyInterp_Request::Destroy( *it );
128 myQueueMutex.unlock();
130 // Wait for run() to finish
137 bool PyInterp_Dispatcher::IsBusy() const
142 void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest )
147 //if ( theRequest->IsSync() && !IsBusy() ) // synchronous processing - nothing is done if dispatcher is busy!
148 if ( theRequest->IsSync() ) // synchronous processing - nothing is done if dispatcher is busy!
149 processRequest( theRequest );
150 else { // asynchronous processing
152 myQueue.push_back( theRequest );
153 if ( theRequest->getListener() )
154 QObject::connect( theRequest->getListener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) );
155 myQueueMutex.unlock();
162 void PyInterp_Dispatcher::run()
164 // MESSAGE("*** PyInterp_Dispatcher::run(): STARTED")
165 PyInterp_Request* aRequest;
167 // prepare for queue size check
170 while( myQueue.size() ) {
171 // MESSAGE("*** PyInterp_Dispatcher::run(): next request taken from the queue")
172 aRequest = myQueue.front();
174 // let other threads append their requests to the end of the queue
175 myQueueMutex.unlock();
177 // processRequest() may delete a request, so this pointer must not be used
178 // after request is processed!
179 processRequest( aRequest );
181 // prepare for removal of the first request in the queue
183 // IMPORTANT: the first item could have been removed by objectDestroyed() --> we have to check it
184 if ( myQueue.front() == aRequest ) // It's still here --> remove it
187 // MESSAGE("*** PyInterp_Dispatcher::run(): request processed")
190 myQueueMutex.unlock();
191 // MESSAGE("*** PyInterp_Dispatcher::run(): FINISHED")
194 void PyInterp_Dispatcher::processRequest( PyInterp_Request* theRequest )
196 theRequest->process();
199 void PyInterp_Dispatcher::objectDestroyed( const QObject* o )
201 // prepare for modification of the queue
204 for ( std::list<RequestPtr>::iterator it = myQueue.begin(); it != myQueue.end(); ++it ){
205 if ( o == (*it)->getListener() ){
206 (*it)->setListener( 0 ); // to prevent event posting
207 it = myQueue.erase( it );
211 myQueueMutex.unlock();