]> SALOME platform Git repositories - modules/gui.git/blob - src/PyInterp/PyInterp_Dispatcher.cxx
Salome HOME
d772c34a2a502ec3f8666c14d8f0ff74f4a0e048
[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 void PyInterp_Request::process()
26 {
27   safeExecute();
28
29   myMutex.lock();
30   //if ( !IsSync() && getListener() && getEvent() )
31   if ( getListener() && getEvent() )
32     postEvent();
33   myMutex.unlock();
34 }
35
36 void PyInterp_Request::safeExecute()
37 {
38   execute();
39 }
40
41 void PyInterp_Request::Destroy( PyInterp_Request* request )
42 {
43   // Lock and unlock the mutex to avoid errors on its deletion
44   request->myMutex.lock();
45   request->myMutex.unlock();
46   delete request;
47 }
48
49 QEvent* PyInterp_Request::createEvent() const
50 {
51   return new PyInterp_Event( PyInterp_Event::NOTIFY, (PyInterp_Request*)this );
52 }
53
54 QEvent* PyInterp_Request::getEvent()
55 {
56   //if ( !myEvent && !IsSync() )
57   if ( !myEvent )
58     myEvent = createEvent();
59   return myEvent;
60 }
61
62 void PyInterp_Request::postEvent()
63 {
64 #if QT_VERSION >= 0x030303
65 //  MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.3.3")
66   QApplication::postEvent( getListener(), getEvent() );
67 #else
68 //  MESSAGE("*** PyInterp_Request::postEvent(): for Qt 3.0.5")
69   QThread::postEvent( getListener(), getEvent() );
70 #endif
71 }
72
73 void PyInterp_Request::setListener( QObject* o )
74 {
75   myMutex.lock();
76   myListener = o;
77   myMutex.unlock();
78 }
79
80 void PyInterp_LockRequest::safeExecute()
81 {
82   if ( getInterp() ){
83     PyLockWrapper aLock = getInterp()->GetLockWrapper();
84     execute();
85   }
86 }
87
88 PyInterp_Event::~PyInterp_Event()
89 {
90   PyInterp_Request::Destroy( myRequest );
91   myRequest = 0;
92 }
93
94 PyInterp_Dispatcher* PyInterp_Dispatcher::Get()
95 {
96   if ( !myInstance )
97     myInstance = new PyInterp_Dispatcher();
98   return myInstance;
99 }
100
101 PyInterp_Dispatcher::PyInterp_Dispatcher() 
102 : QThread()
103 {
104   myWatcher = new PyInterp_Watcher();
105 }
106
107 PyInterp_Dispatcher::~PyInterp_Dispatcher()
108 {
109   // Clear the request queue
110   myQueueMutex.lock();
111
112   for ( std::list<PyInterp_Request*>::iterator it = myQueue.begin(); it != myQueue.end(); ++it )
113     PyInterp_Request::Destroy( *it );
114   myQueue.clear();
115
116   myQueueMutex.unlock();
117
118   // Wait for run() to finish
119   wait();
120
121   delete myWatcher;
122   myWatcher = 0;
123 }
124
125 bool PyInterp_Dispatcher::IsBusy() const
126 {
127   return running();
128 }
129
130 void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest )
131 {
132   if ( !theRequest )
133     return;
134
135   //if ( theRequest->IsSync() && !IsBusy() ) // synchronous processing - nothing is done if dispatcher is busy!
136   if ( theRequest->IsSync() ) // synchronous processing - nothing is done if dispatcher is busy!
137     processRequest( theRequest );
138   else { // asynchronous processing
139     myQueueMutex.lock();
140     myQueue.push_back( theRequest );
141     if ( theRequest->getListener() )
142       QObject::connect( theRequest->getListener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) );
143     myQueueMutex.unlock();  
144
145     if ( !IsBusy() )
146       start();
147   }
148 }
149
150 void PyInterp_Dispatcher::run()
151 {
152 //  MESSAGE("*** PyInterp_Dispatcher::run(): STARTED")
153   PyInterp_Request* aRequest;
154
155   // prepare for queue size check
156   myQueueMutex.lock();
157
158   while( myQueue.size() ) {
159 //    MESSAGE("*** PyInterp_Dispatcher::run(): next request taken from the queue")
160     aRequest = myQueue.front();
161
162     // let other threads append their requests to the end of the queue
163     myQueueMutex.unlock();
164
165     // processRequest() may delete a request, so this pointer must not be used
166     // after request is processed!
167     processRequest( aRequest );
168
169     // prepare for removal of the first request in the queue
170     myQueueMutex.lock();
171     // IMPORTANT: the first item could have been removed by objectDestroyed() --> we have to check it
172     if ( myQueue.front() == aRequest ) // It's still here --> remove it
173       myQueue.pop_front();
174
175 //    MESSAGE("*** PyInterp_Dispatcher::run(): request processed")
176   }
177
178   myQueueMutex.unlock();
179 //  MESSAGE("*** PyInterp_Dispatcher::run(): FINISHED")
180 }
181
182 void PyInterp_Dispatcher::processRequest( PyInterp_Request* theRequest )
183 {
184   theRequest->process();
185 }
186
187 void PyInterp_Dispatcher::objectDestroyed( const QObject* o )
188 {
189   // prepare for modification of the queue
190   myQueueMutex.lock();
191
192   for ( std::list<RequestPtr>::iterator it = myQueue.begin(); it != myQueue.end(); ++it ){
193     if ( o == (*it)->getListener() ){
194       (*it)->setListener( 0 ); // to prevent event posting
195       it = myQueue.erase( it );
196     }
197   }
198
199   myQueueMutex.unlock();
200 }
201