Salome HOME
40b0059e834e6bed488cf10d452fc2ecdd1d4d03
[modules/gui.git] / src / PyInterp / PyInterp_Dispatcher.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File   : PyInterp_Dispatcher.cxx
24 //  Author : Sergey ANIKIN, OCC
25 //  Module : GUI
26 //
27 #include "PyInterp_Dispatcher.h"   // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
28 #include "PyInterp_Interp.h"
29 #include "PyInterp_Watcher.h"
30 #include "PyInterp_Request.h"
31
32 #include <QObject>
33 #include <QCoreApplication>
34
35 PyInterp_Dispatcher* PyInterp_Dispatcher::myInstance = 0;
36
37 PyInterp_Dispatcher* PyInterp_Dispatcher::Get()
38 {
39   if ( !myInstance )
40     myInstance = new PyInterp_Dispatcher();
41   return myInstance;
42 }
43
44 PyInterp_Dispatcher::PyInterp_Dispatcher() 
45 : QThread()
46 {
47   myWatcher = new PyInterp_Watcher();
48 }
49
50 PyInterp_Dispatcher::~PyInterp_Dispatcher()
51 {
52   // Clear the request queue
53   myQueueMutex.lock();
54
55   QListIterator<RequestPtr> it( myQueue );
56   while ( it.hasNext() )
57     PyInterp_Request::Destroy( it.next() );
58   myQueue.clear();
59
60   myQueueMutex.unlock();
61
62   // Wait for run() to finish
63   wait();
64
65   delete myWatcher;
66   myWatcher = 0;
67 }
68
69 bool PyInterp_Dispatcher::IsBusy() const
70 {
71   return isRunning();
72 }
73
74 void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest )
75 {
76   if ( !theRequest )
77     return;
78
79   //if ( theRequest->IsSync() && !IsBusy() ) // synchronous processing - nothing is done if dispatcher is busy!
80   if ( theRequest->IsSync() ) // synchronous processing
81     processRequest( theRequest );
82   else // asynchronous processing
83   {
84     myQueueMutex.lock();
85     myQueue.enqueue( theRequest );
86     if ( theRequest->listener() )
87       QObject::connect( theRequest->listener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) );
88     myQueueMutex.unlock();  
89
90     if ( !IsBusy() )
91       start();
92   }
93 }
94
95 void PyInterp_Dispatcher::run()
96 {
97 //  MESSAGE("*** PyInterp_Dispatcher::run(): STARTED")
98   PyInterp_Request* aRequest;
99
100   // prepare for queue size check
101   myQueueMutex.lock();
102
103   while( myQueue.size() ) {
104 //    MESSAGE("*** PyInterp_Dispatcher::run(): next request taken from the queue")
105     aRequest = myQueue.head();
106
107     // let other threads append their requests to the end of the queue
108     myQueueMutex.unlock();
109
110     // processRequest() may delete a request, so this pointer must not be used
111     // after request is processed!
112     processRequest( aRequest );
113
114     // prepare for removal of the first request in the queue
115     myQueueMutex.lock();
116     // IMPORTANT: the first item could have been removed by objectDestroyed() --> we have to check it
117     if ( myQueue.head() == aRequest ) // It's still here --> remove it
118       myQueue.dequeue();
119
120 //    MESSAGE("*** PyInterp_Dispatcher::run(): request processed")
121   }
122
123   myQueueMutex.unlock();
124 //  MESSAGE("*** PyInterp_Dispatcher::run(): FINISHED")
125 }
126
127 void PyInterp_Dispatcher::processRequest( PyInterp_Request* theRequest )
128 {
129   theRequest->process();
130 }
131
132 void PyInterp_Dispatcher::objectDestroyed( const QObject* o )
133 {
134   // prepare for modification of the queue
135   myQueueMutex.lock();
136
137   QMutableListIterator<RequestPtr> it( myQueue );
138   while ( it.hasNext() )
139   {
140     RequestPtr r = it.next();
141     if ( o == r->listener() )
142     {
143       r->setListener( 0 ); // to prevent event posting
144       it.remove();
145     }
146   }
147
148   myQueueMutex.unlock();
149 }