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() )
39 void PyInterp_Request::safeExecute()
44 void PyInterp_Request::Destroy( PyInterp_Request* request )
46 // Lock and unlock the mutex to avoid errors on its deletion
47 request->myMutex.lock();
48 request->myMutex.unlock();
52 QEvent* PyInterp_Request::createEvent() const
54 return new PyInterp_Event( PyInterp_Event::NOTIFY, (PyInterp_Request*)this );
57 QEvent* PyInterp_Request::getEvent()
59 if ( !myEvent && !IsSync() )
60 myEvent = createEvent();
64 void PyInterp_Request::postEvent()
66 #if QT_VERSION >= 0x030303
67 // MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.3.3")
68 QApplication::postEvent( getListener(), getEvent() );
70 // MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.0.5")
71 QThread::postEvent( getListener(), getEvent() );
75 void PyInterp_Request::setListener( QObject* o )
82 void PyInterp_LockRequest::safeExecute()
85 PyLockWrapper aLock = getInterp()->GetLockWrapper();
90 //////////////////////////////////////////////////////////
91 // class : PyInterp_Event
92 //////////////////////////////////////////////////////////
94 PyInterp_Event::~PyInterp_Event()
96 PyInterp_Request::Destroy( myRequest );
100 //////////////////////////////////////////////////////////
101 // class : PyInterp_Dispatcher
102 //////////////////////////////////////////////////////////
104 PyInterp_Dispatcher* PyInterp_Dispatcher::Get()
107 myInstance = new PyInterp_Dispatcher();
111 PyInterp_Dispatcher::PyInterp_Dispatcher()
114 myWatcher = new PyInterp_Watcher();
117 PyInterp_Dispatcher::~PyInterp_Dispatcher()
119 // Clear the request queue
122 for ( std::list<PyInterp_Request*>::iterator it = myQueue.begin(); it != myQueue.end(); ++it )
123 PyInterp_Request::Destroy( *it );
126 myQueueMutex.unlock();
128 // Wait for run() to finish
135 bool PyInterp_Dispatcher::IsBusy() const
140 void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest )
145 if ( theRequest->IsSync() && !IsBusy() ) // synchronous processing - nothing is done if dispatcher is busy!
146 processRequest( theRequest );
147 else { // asynchronous processing
149 myQueue.push_back( theRequest );
150 if ( theRequest->getListener() )
151 QObject::connect( theRequest->getListener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) );
152 myQueueMutex.unlock();
159 void PyInterp_Dispatcher::run()
161 // MESSAGE("*** PyInterp_Dispatcher::run(): STARTED")
162 PyInterp_Request* aRequest;
164 // prepare for queue size check
167 while( myQueue.size() ) {
168 // MESSAGE("*** PyInterp_Dispatcher::run(): next request taken from the queue")
169 aRequest = myQueue.front();
171 // let other threads append their requests to the end of the queue
172 myQueueMutex.unlock();
174 // processRequest() may delete a request, so this pointer must not be used
175 // after request is processed!
176 processRequest( aRequest );
178 // prepare for removal of the first request in the queue
180 // IMPORTANT: the first item could have been removed by objectDestroyed() --> we have to check it
181 if ( myQueue.front() == aRequest ) // It's still here --> remove it
184 // MESSAGE("*** PyInterp_Dispatcher::run(): request processed")
187 myQueueMutex.unlock();
188 // MESSAGE("*** PyInterp_Dispatcher::run(): FINISHED")
191 void PyInterp_Dispatcher::processRequest( PyInterp_Request* theRequest )
193 theRequest->process();
196 void PyInterp_Dispatcher::objectDestroyed( const QObject* o )
198 // prepare for modification of the queue
201 for ( std::list<RequestPtr>::iterator it = myQueue.begin(); it != myQueue.end(); ++it ){
202 if ( o == (*it)->getListener() ){
203 (*it)->setListener( 0 ); // to prevent event posting
204 it = myQueue.erase( it );
208 myQueueMutex.unlock();