Back to index

salome-gui  6.5.0
PyInterp_Dispatcher.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  File   : PyInterp_Dispatcher.cxx
00024 //  Author : Sergey ANIKIN, OCC
00025 //  Module : GUI
00026 //
00027 #include "PyInterp_Dispatcher.h"   // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
00028 #include "PyInterp_Interp.h"
00029 #include "PyInterp_Watcher.h"
00030 #include <SALOME_Event.h>
00031 
00032 #include <QObject>
00033 #include <QCoreApplication>
00034 
00035 class PyInterp_ExecuteEvent: public SALOME_Event
00036 {
00037 public:
00038   PyInterp_Request* myRequest;
00039   PyInterp_ExecuteEvent( PyInterp_Request* r )
00040     : myRequest( r ) {}
00041   virtual void Execute()
00042   {
00043     myRequest->execute();
00044   }
00045 };
00046 
00047 PyInterp_Dispatcher* PyInterp_Dispatcher::myInstance = 0;
00048 
00049 void PyInterp_Request::process()
00050 {
00051   safeExecute();
00052 
00053   bool isSync = IsSync();
00054 
00055   if ( !isSync )
00056     myMutex.lock();
00057 
00058   if ( listener() )
00059     processEvent( listener() );
00060 
00061   if ( !isSync )
00062     myMutex.unlock();
00063 }
00064 
00065 void PyInterp_Request::safeExecute()
00066 {
00067   //ProcessVoidEvent( new PyInterp_ExecuteEvent( this ) );
00068   execute();
00069 }
00070 
00071 void PyInterp_Request::Destroy( PyInterp_Request* request )
00072 {
00073   // Lock and unlock the mutex to avoid errors on its deletion
00074   request->myMutex.lock();
00075   request->myMutex.unlock();
00076   delete request;
00077 }
00078 
00079 QEvent* PyInterp_Request::createEvent() const
00080 {
00081   return new PyInterp_Event( PyInterp_Event::ES_NOTIFY, (PyInterp_Request*)this );
00082 }
00083 
00084 void PyInterp_Request::processEvent( QObject* o )
00085 {
00086   if ( !o )
00087     return;
00088 
00089   QEvent* e = createEvent();
00090   if ( !e )
00091     return;
00092 
00093   if ( !IsSync() )
00094     QCoreApplication::postEvent( o, e );
00095   else
00096   {
00097     QCoreApplication::sendEvent( o, e );
00098     delete e;
00099   }
00100 }
00101 
00102 void PyInterp_Request::setListener( QObject* o )
00103 {
00104   myMutex.lock();
00105   myListener = o;
00106   myMutex.unlock();
00107 }
00108 
00109 void PyInterp_LockRequest::safeExecute()
00110 {
00111   if ( getInterp() ){
00112     PyLockWrapper aLock = getInterp()->GetLockWrapper();
00113     //ProcessVoidEvent( new PyInterp_ExecuteEvent( this ) );
00114     execute();
00115   }
00116 }
00117 
00118 PyInterp_Event::~PyInterp_Event()
00119 {
00120   PyInterp_Request::Destroy( myRequest );
00121   myRequest = 0;
00122 }
00123 
00124 PyInterp_Dispatcher* PyInterp_Dispatcher::Get()
00125 {
00126   if ( !myInstance )
00127     myInstance = new PyInterp_Dispatcher();
00128   return myInstance;
00129 }
00130 
00131 PyInterp_Dispatcher::PyInterp_Dispatcher() 
00132 : QThread()
00133 {
00134   myWatcher = new PyInterp_Watcher();
00135 }
00136 
00137 PyInterp_Dispatcher::~PyInterp_Dispatcher()
00138 {
00139   // Clear the request queue
00140   myQueueMutex.lock();
00141 
00142   QListIterator<RequestPtr> it( myQueue );
00143   while ( it.hasNext() )
00144     PyInterp_Request::Destroy( it.next() );
00145   myQueue.clear();
00146 
00147   myQueueMutex.unlock();
00148 
00149   // Wait for run() to finish
00150   wait();
00151 
00152   delete myWatcher;
00153   myWatcher = 0;
00154 }
00155 
00156 bool PyInterp_Dispatcher::IsBusy() const
00157 {
00158   return isRunning();
00159 }
00160 
00161 void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest )
00162 {
00163   if ( !theRequest )
00164     return;
00165 
00166   //if ( theRequest->IsSync() && !IsBusy() ) // synchronous processing - nothing is done if dispatcher is busy!
00167   if ( theRequest->IsSync() ) // synchronous processing - nothing is done if dispatcher is busy!
00168     processRequest( theRequest );
00169   else // asynchronous processing
00170   {
00171     myQueueMutex.lock();
00172     myQueue.enqueue( theRequest );
00173     if ( theRequest->listener() )
00174       QObject::connect( theRequest->listener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) );
00175     myQueueMutex.unlock();  
00176 
00177     if ( !IsBusy() )
00178       start();
00179   }
00180 }
00181 
00182 void PyInterp_Dispatcher::run()
00183 {
00184 //  MESSAGE("*** PyInterp_Dispatcher::run(): STARTED")
00185   PyInterp_Request* aRequest;
00186 
00187   // prepare for queue size check
00188   myQueueMutex.lock();
00189 
00190   while( myQueue.size() ) {
00191 //    MESSAGE("*** PyInterp_Dispatcher::run(): next request taken from the queue")
00192     aRequest = myQueue.head();
00193 
00194     // let other threads append their requests to the end of the queue
00195     myQueueMutex.unlock();
00196 
00197     // processRequest() may delete a request, so this pointer must not be used
00198     // after request is processed!
00199     processRequest( aRequest );
00200 
00201     // prepare for removal of the first request in the queue
00202     myQueueMutex.lock();
00203     // IMPORTANT: the first item could have been removed by objectDestroyed() --> we have to check it
00204     if ( myQueue.head() == aRequest ) // It's still here --> remove it
00205       myQueue.dequeue();
00206 
00207 //    MESSAGE("*** PyInterp_Dispatcher::run(): request processed")
00208   }
00209 
00210   myQueueMutex.unlock();
00211 //  MESSAGE("*** PyInterp_Dispatcher::run(): FINISHED")
00212 }
00213 
00214 void PyInterp_Dispatcher::processRequest( PyInterp_Request* theRequest )
00215 {
00216   theRequest->process();
00217 }
00218 
00219 void PyInterp_Dispatcher::objectDestroyed( const QObject* o )
00220 {
00221   // prepare for modification of the queue
00222   myQueueMutex.lock();
00223 
00224   QMutableListIterator<RequestPtr> it( myQueue );
00225   while ( it.hasNext() )
00226   {
00227     RequestPtr r = it.next();
00228     if ( o == r->listener() )
00229     {
00230       r->setListener( 0 ); // to prevent event posting
00231       it.remove();
00232     }
00233   }
00234 
00235   myQueueMutex.unlock();
00236 }