]> SALOME platform Git repositories - modules/gui.git/blob - src/PyInterp/PyInterp_Dispatcher.cxx
Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/gui.git] / src / PyInterp / PyInterp_Dispatcher.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
2 // 
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either 
6 // version 2.1 of the License.
7 // 
8 // This library is distributed in the hope that it will be useful 
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public  
14 // License along with this library; if not, write to the Free Software 
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 //  SALOME SALOMEGUI : implementation of desktop and GUI kernel
20 //
21 //  File   : PyInterp_Dispatcher.cxx
22 //  Author : Sergey ANIKIN, OCC
23 //  Module : GUI
24 //  $Header$
25
26
27 #include <PyInterp_base.h>
28 #include <PyInterp_Dispatcher.h>
29 #include <PyInterp_Watcher.h>
30
31 #include <qapplication.h>
32 #include <qobject.h>
33
34 //#include <utilities.h>
35 using namespace std;
36
37 PyInterp_Dispatcher* PyInterp_Dispatcher::myInstance = 0;
38
39 void PyInterp_Request::process()
40 {
41   safeExecute();
42
43   myMutex.lock();
44   //if ( !IsSync() && getListener() && getEvent() )
45   if ( getListener() && getEvent() )
46     postEvent();
47   myMutex.unlock();
48 }
49
50 void PyInterp_Request::safeExecute()
51 {
52   execute();
53 }
54
55 void PyInterp_Request::Destroy( PyInterp_Request* request )
56 {
57   // Lock and unlock the mutex to avoid errors on its deletion
58   request->myMutex.lock();
59   request->myMutex.unlock();
60   delete request;
61 }
62
63 QEvent* PyInterp_Request::createEvent() const
64 {
65   return new PyInterp_Event( PyInterp_Event::NOTIFY, (PyInterp_Request*)this );
66 }
67
68 QEvent* PyInterp_Request::getEvent()
69 {
70   //if ( !myEvent && !IsSync() )
71   if ( !myEvent )
72     myEvent = createEvent();
73   return myEvent;
74 }
75
76 void PyInterp_Request::postEvent()
77 {
78 #if QT_VERSION >= 0x030303
79 //  MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.3.3")
80   QApplication::postEvent( getListener(), getEvent() );
81 #else
82 //  MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.0.5")
83   QThread::postEvent( getListener(), getEvent() );
84 #endif
85 }
86
87 void PyInterp_Request::setListener( QObject* o )
88 {
89   myMutex.lock();
90   myListener = o;
91   myMutex.unlock();
92 }
93
94 void PyInterp_LockRequest::safeExecute()
95 {
96   if ( getInterp() ){
97     PyLockWrapper aLock = getInterp()->GetLockWrapper();
98     execute();
99   }
100 }
101
102 PyInterp_Event::~PyInterp_Event()
103 {
104   PyInterp_Request::Destroy( myRequest );
105   myRequest = 0;
106 }
107
108 PyInterp_Dispatcher* PyInterp_Dispatcher::Get()
109 {
110   if ( !myInstance )
111     myInstance = new PyInterp_Dispatcher();
112   return myInstance;
113 }
114
115 PyInterp_Dispatcher::PyInterp_Dispatcher() 
116 : QThread()
117 {
118   myWatcher = new PyInterp_Watcher();
119 }
120
121 PyInterp_Dispatcher::~PyInterp_Dispatcher()
122 {
123   // Clear the request queue
124   myQueueMutex.lock();
125
126   for ( std::list<PyInterp_Request*>::iterator it = myQueue.begin(); it != myQueue.end(); ++it )
127     PyInterp_Request::Destroy( *it );
128   myQueue.clear();
129
130   myQueueMutex.unlock();
131
132   // Wait for run() to finish
133   wait();
134
135   delete myWatcher;
136   myWatcher = 0;
137 }
138
139 bool PyInterp_Dispatcher::IsBusy() const
140 {
141   return running();
142 }
143
144 void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest )
145 {
146   if ( !theRequest )
147     return;
148
149   //if ( theRequest->IsSync() && !IsBusy() ) // synchronous processing - nothing is done if dispatcher is busy!
150   if ( theRequest->IsSync() ) // synchronous processing - nothing is done if dispatcher is busy!
151     processRequest( theRequest );
152   else { // asynchronous processing
153     myQueueMutex.lock();
154     myQueue.push_back( theRequest );
155     if ( theRequest->getListener() )
156       QObject::connect( theRequest->getListener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) );
157     myQueueMutex.unlock();  
158
159     if ( !IsBusy() )
160       start();
161   }
162 }
163
164 void PyInterp_Dispatcher::run()
165 {
166 //  MESSAGE("*** PyInterp_Dispatcher::run(): STARTED")
167   PyInterp_Request* aRequest;
168
169   // prepare for queue size check
170   myQueueMutex.lock();
171
172   while( myQueue.size() ) {
173 //    MESSAGE("*** PyInterp_Dispatcher::run(): next request taken from the queue")
174     aRequest = myQueue.front();
175
176     // let other threads append their requests to the end of the queue
177     myQueueMutex.unlock();
178
179     // processRequest() may delete a request, so this pointer must not be used
180     // after request is processed!
181     processRequest( aRequest );
182
183     // prepare for removal of the first request in the queue
184     myQueueMutex.lock();
185     // IMPORTANT: the first item could have been removed by objectDestroyed() --> we have to check it
186     if ( myQueue.front() == aRequest ) // It's still here --> remove it
187       myQueue.pop_front();
188
189 //    MESSAGE("*** PyInterp_Dispatcher::run(): request processed")
190   }
191
192   myQueueMutex.unlock();
193 //  MESSAGE("*** PyInterp_Dispatcher::run(): FINISHED")
194 }
195
196 void PyInterp_Dispatcher::processRequest( PyInterp_Request* theRequest )
197 {
198   theRequest->process();
199 }
200
201 void PyInterp_Dispatcher::objectDestroyed( const QObject* o )
202 {
203   // prepare for modification of the queue
204   myQueueMutex.lock();
205
206   for ( std::list<RequestPtr>::iterator it = myQueue.begin(); it != myQueue.end(); ++it ){
207     if ( o == (*it)->getListener() ){
208       (*it)->setListener( 0 ); // to prevent event posting
209       it = myQueue.erase( it );
210     }
211   }
212
213   myQueueMutex.unlock();
214 }
215