Salome HOME
DCQ : Merge with Ecole_ete_a6.
[modules/kernel.git] / src / Event / SALOME_Event.hxx
1 //  KERNEL SALOME_Event : Define event posting mechanism
2 //
3 //  Copyright (C) 2003  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. 
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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SALOME_Event.hxx
25 //  Author : Sergey ANIKIN
26 //  Module : KERNEL
27 //  $Header$
28
29
30 #ifndef SALOME_Event_HeaderFile
31 #define SALOME_Event_HeaderFile
32
33 #include <qevent.h>
34
35 #define SALOME_EVENT QEvent::Type( QEvent::User + 10000 )
36
37 class QSemaphore;
38
39 //===========================================================
40 /*!
41  *  Class: SALOME_Event
42  *  Description: 
43  *  This class encapsulates data and functionality required for 
44  *  posting component-specific events to perform arbitrary operations in main GUI thread. 
45  *  SALOME_Event objects can be posted by any thread belonging to the GUI process.
46  *
47  *  It is necessary to derive a custom event class from SALOME_Event and 
48  *  re-implement virtual Execute() method. This method should actually perform 
49  *  the desirable operation. To pass all the required data to Execute() and store a return value,
50  *  arbitrary data fields can be added to the custom event class. There is 
51  *  no need to protect such fields with a mutex, for only one thread working with
52  *  a SALOME_Event object is active at any moment.
53  *
54  *  It is possible to make the thread that creates SALOME_Event
55  *  wait until the event is processed by the component GUI, SALOME_Event
56  *  should be constructed with <wait> == TRUE in such a case.
57  *
58  *  SALOME_Event objects should be created on the heap. QAD_Desktop deletes
59  *  these objects as soon as they have been processed.
60  *
61  *  Usage:
62  *  - create SALOME_Event object on the heap with proper <type> and <wait> parameters. 
63  *    Components can derive their own event class from SALOME_Event
64  *    in order to pass custom data to the event handler.
65  *  - call process() method to post the event. Between process() and release()
66  *    it is possible to examine fields of your custom event object.
67  *  - call release() method to wake up the desktop (you can also set <autoRelease>
68  *    parameter to TRUE to automatically wake up desktop after process()
69  * 
70  *  processed() method is used by the desktop to signal that event processing 
71  *  has been completed.
72  *  
73  *  Caveats: 
74  *  1. Never create SALOME_Event with <wait> == TRUE in code that is 
75  *     supposed to be called within main GUI thread, for this will result
76  *     in GUI process deadlock.
77  *  2. Always call release() method after process() if you use <wait> parameters as TRUE,
78  *     otherwise processed() method will never return and main GUI thread will be blocked!
79  *  3. Never use pointers to the event after it has been released (either by calling release()
80  *     or automatically by process() if <autoRelease> == TRUE) to avoid application crashes!
81  */
82 //===========================================================
83
84
85 class SALOME_Event
86 {
87 public:
88   SALOME_Event();
89   virtual ~SALOME_Event();
90
91   // To do real work
92   virtual void Execute() = 0;
93
94   void process();
95   void processed();
96
97   void release();
98
99 private:
100   bool        myWait;
101   bool        myAutoRelease;
102   QSemaphore* mySemaphore;
103 };
104
105
106 // Template classes for member function
107 //-------------------------------------
108 template<class TObject, typename TRes>
109 class TMemFunEvent: public SALOME_Event{
110 public:
111   typedef TRes TResult;
112   TResult myResult;
113   typedef TResult (TObject::* TAction)();
114   TMemFunEvent(TObject* theObject, TAction theAction, 
115                TResult theResult = TResult()):
116     myObject(theObject),
117     myAction(theAction),
118     myResult(theResult)
119   {}
120   virtual void Execute(){
121     myResult = (myObject->*myAction)();
122   }
123 private:
124   TObject* myObject;
125   TAction myAction;
126 };
127
128
129 template<class TObject>
130 class TVoidMemFunEvent: public SALOME_Event{
131 public:
132   typedef void (TObject::* TAction)();
133   TVoidMemFunEvent(TObject* theObject, TAction theAction):
134     myObject(theObject),
135     myAction(theAction)
136   {}
137   virtual void Execute(){
138     (myObject->*myAction)();
139   }
140 private:
141   TObject* myObject;
142   TAction myAction;
143 };
144
145
146 // Template for member function with one argument
147 //-----------------------------------------------
148 template<class TObject, typename TRes, 
149          typename TArg, typename TStoreArg = TArg>
150 class TMemFun1ArgEvent: public SALOME_Event{
151 public:
152   typedef TRes TResult;
153   TResult myResult;
154   typedef TResult (TObject::* TAction)(TArg);
155   TMemFun1ArgEvent(TObject* theObject, TAction theAction, TArg theArg, 
156                    TResult theResult = TResult()):
157     myObject(theObject),
158     myAction(theAction),
159     myResult(theResult),
160     myArg(theArg)
161   {}
162   virtual void Execute(){
163     myResult = (myObject->*myAction)(myArg);
164   }
165 private:
166   TObject* myObject;
167   TAction myAction;
168   TStoreArg myArg;
169 };
170
171
172 template<class TObject, typename TArg, typename TStoreArg = TArg>
173 class TVoidMemFun1ArgEvent: public SALOME_Event{
174 public:
175   typedef void (TObject::* TAction)(TArg);
176   TVoidMemFun1ArgEvent(TObject* theObject, TAction theAction, TArg theArg):
177     myObject(theObject),
178     myAction(theAction),
179     myArg(theArg)
180   {}
181   virtual void Execute(){
182     (myObject->*myAction)(myArg);
183   }
184 private:
185   TObject* myObject;
186   TAction myAction;
187   TStoreArg myArg;
188 };
189
190
191 // Template for member function with one argument
192 //-----------------------------------------------
193 template<class TObject, typename TRes,
194          typename TArg, typename TArg1, 
195          typename TStoreArg = TArg, typename TStoreArg1 = TArg1>
196 class TMemFun2ArgEvent: public SALOME_Event{
197 public:
198   typedef TRes TResult;
199   TResult myResult;
200   typedef TResult (TObject::* TAction)(TArg,TArg1);
201   TMemFun2ArgEvent(TObject* theObject, TAction theAction, 
202                    TArg theArg, TArg1 theArg1,
203                    TResult theResult = TResult()):
204     myObject(theObject),
205     myAction(theAction),
206     myResult(theResult),
207     myArg(theArg),
208     myArg1(theArg1)
209   {}
210   virtual void Execute(){
211     myResult = (myObject->*myAction)(myArg,myArg1);
212   }
213 private:
214   TObject* myObject;
215   TAction myAction;
216   TStoreArg myArg;
217   TStoreArg1 myArg1;
218 };
219
220
221 template<class TObject, typename TArg, typename TArg1, 
222          typename TStoreArg = TArg, typename TStoreArg1 = TArg1>
223 class TVoidMemFun2ArgEvent: public SALOME_Event{
224 public:
225   typedef void (TObject::* TAction)(TArg,TArg1);
226   TVoidMemFun2ArgEvent(TObject* theObject, TAction theAction, TArg theArg, TArg1 theArg1):
227     myObject(theObject),
228     myAction(theAction),
229     myArg(theArg),
230     myArg1(theArg1)
231   {}
232   virtual void Execute(){
233     (myObject->*myAction)(myArg,myArg1);
234   }
235 private:
236   TObject* myObject;
237   TAction myAction;
238   TStoreArg myArg;
239   TStoreArg1 myArg1;
240 };
241
242
243 // Template function for processing events with result returing
244 template<class TEvent> inline typename TEvent::TResult ProcessEvent(TEvent* theEvent){
245   theEvent->process();
246   typename TEvent::TResult aResult = theEvent->myResult;
247   theEvent->release();
248   return aResult;
249 }
250
251
252 // Template function for processing events without result
253 inline void ProcessVoidEvent(SALOME_Event* theEvent){
254   theEvent->process();
255   theEvent->release();
256 }
257
258
259 #endif