]> SALOME platform Git repositories - modules/gui.git/blob - src/PyInterp/PyInterp_Dispatcher.cxx
Salome HOME
Join modifications from branch BR_3_1_0deb
[modules/gui.git] / src / PyInterp / PyInterp_Dispatcher.cxx
1 //  SALOME SALOMEGUI : implementation of desktop and GUI kernel
2 //
3 //  Copyright (C) 2005  CEA/DEN, EDF R&D
4 //
5 //
6 //
7 //  File   : PyInterp_Dispatcher.cxx
8 //  Author : Sergey ANIKIN, OCC
9 //  Module : GUI
10 //  $Header$
11
12
13 #include <PyInterp_base.h>
14 #include <PyInterp_Dispatcher.h>
15 #include <PyInterp_Watcher.h>
16
17 #include <qapplication.h>
18 #include <qobject.h>
19
20 //#include <utilities.h>
21 using namespace std;
22
23 PyInterp_Dispatcher* PyInterp_Dispatcher::myInstance = 0;
24
25 //////////////////////////////////////////////////////////
26 // class : PyInterp_Request
27 //////////////////////////////////////////////////////////
28
29 void PyInterp_Request::process()
30 {
31   safeExecute();
32
33   myMutex.lock();
34   //if ( !IsSync() && getListener() && getEvent() )
35   if ( getListener() && getEvent() )
36     postEvent();
37   myMutex.unlock();
38 }
39
40 void PyInterp_Request::safeExecute()
41 {
42   execute();
43 }
44
45 void PyInterp_Request::Destroy( PyInterp_Request* request )
46 {
47   // Lock and unlock the mutex to avoid errors on its deletion
48   request->myMutex.lock();
49   request->myMutex.unlock();
50   delete request;
51 }
52
53 QEvent* PyInterp_Request::createEvent() const
54 {
55   return new PyInterp_Event( PyInterp_Event::NOTIFY, (PyInterp_Request*)this );
56 }
57
58 QEvent* PyInterp_Request::getEvent()
59 {
60   //if ( !myEvent && !IsSync() )
61   if ( !myEvent )
62     myEvent = createEvent();
63   return myEvent;
64 }
65
66 void PyInterp_Request::postEvent()
67 {
68 #if QT_VERSION >= 0x030303
69 //  MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.3.3")
70   QApplication::postEvent( getListener(), getEvent() );
71 #else
72 //  MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.0.5")
73   QThread::postEvent( getListener(), getEvent() );
74 #endif
75 }
76
77 void PyInterp_Request::setListener( QObject* o )
78 {
79   myMutex.lock();
80   myListener = o;
81   myMutex.unlock();
82 }
83
84 void PyInterp_LockRequest::safeExecute()
85 {
86   if ( getInterp() ){
87     PyLockWrapper aLock = getInterp()->GetLockWrapper();
88     execute();
89   }
90 }
91
92 //////////////////////////////////////////////////////////
93 // class : PyInterp_Event
94 //////////////////////////////////////////////////////////
95
96 PyInterp_Event::~PyInterp_Event()
97 {
98   PyInterp_Request::Destroy( myRequest );
99   myRequest = 0;
100 }
101
102 //////////////////////////////////////////////////////////
103 // class : PyInterp_Dispatcher
104 //////////////////////////////////////////////////////////
105
106 PyInterp_Dispatcher* PyInterp_Dispatcher::Get()
107 {
108   if ( !myInstance )
109     myInstance = new PyInterp_Dispatcher();
110   return myInstance;
111 }
112
113 PyInterp_Dispatcher::PyInterp_Dispatcher() 
114 : QThread()
115 {
116   myWatcher = new PyInterp_Watcher();
117 }
118
119 PyInterp_Dispatcher::~PyInterp_Dispatcher()
120 {
121   // Clear the request queue
122   myQueueMutex.lock();
123
124   for ( std::list<PyInterp_Request*>::iterator it = myQueue.begin(); it != myQueue.end(); ++it )
125     PyInterp_Request::Destroy( *it );
126   myQueue.clear();
127
128   myQueueMutex.unlock();
129
130   // Wait for run() to finish
131   wait();
132
133   delete myWatcher;
134   myWatcher = 0;
135 }
136
137 bool PyInterp_Dispatcher::IsBusy() const
138 {
139   return running();
140 }
141
142 void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest )
143 {
144   if ( !theRequest )
145     return;
146
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
151     myQueueMutex.lock();
152     myQueue.push_back( theRequest );
153     if ( theRequest->getListener() )
154       QObject::connect( theRequest->getListener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) );
155     myQueueMutex.unlock();  
156
157     if ( !IsBusy() )
158       start();
159   }
160 }
161
162 void PyInterp_Dispatcher::run()
163 {
164 //  MESSAGE("*** PyInterp_Dispatcher::run(): STARTED")
165   PyInterp_Request* aRequest;
166
167   // prepare for queue size check
168   myQueueMutex.lock();
169
170   while( myQueue.size() ) {
171 //    MESSAGE("*** PyInterp_Dispatcher::run(): next request taken from the queue")
172     aRequest = myQueue.front();
173
174     // let other threads append their requests to the end of the queue
175     myQueueMutex.unlock();
176
177     // processRequest() may delete a request, so this pointer must not be used
178     // after request is processed!
179     processRequest( aRequest );
180
181     // prepare for removal of the first request in the queue
182     myQueueMutex.lock();
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
185       myQueue.pop_front();
186
187 //    MESSAGE("*** PyInterp_Dispatcher::run(): request processed")
188   }
189
190   myQueueMutex.unlock();
191 //  MESSAGE("*** PyInterp_Dispatcher::run(): FINISHED")
192 }
193
194 void PyInterp_Dispatcher::processRequest( PyInterp_Request* theRequest )
195 {
196   theRequest->process();
197 }
198
199 void PyInterp_Dispatcher::objectDestroyed( const QObject* o )
200 {
201   // prepare for modification of the queue
202   myQueueMutex.lock();
203
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 );
208     }
209   }
210
211   myQueueMutex.unlock();
212 }
213