2 #include "PyEvent_Event.h"
5 #include <QApplication>
7 // asv 21.02.05 : introducing multi-platform approach of thread comparison
8 // - on Unix using pthread_t type for storing ThreadId
9 // - on Win32 using integer type for storing ThreadId
10 // NOT using integer ThreadId on both Unix and Win32 because (from documentation):
11 // "...Do not allow your program to rely on the internal structure or size of the pthread_t..."
15 static DWORD myThread;
18 static pthread_t myThread;
23 \brief Helper event class responsible for initializing PyEvent_Event
24 mechanism by the main thread ID
26 class InitEvent : public PyEvent_Event
31 virtual void Execute();
35 \brief Constructor, initializes the event mechanism by the current thread ID.
36 It is asssumed to be the main thread ID, so be careful!
38 InitEvent::InitEvent()
44 \brief Destructor, does nothing.
46 InitEvent::~InitEvent()
51 \brief Nothing to be executed for this kind of event.
53 void InitEvent::Execute()
57 // NOTE: Here the SALOME event mechanism is initalized by the
58 // current thread ID that is always assumed to be the main thread ID.
59 // This should be revised as soon as the application library is no longer
60 // linked against the Event library (i.e. this static object is not created or created
61 // outside the main thread).
62 static InitEvent myInitEvent;
65 \class PyEvent_CustomEvent
66 \brief Generic event class for user-defined events
68 This class contains a generic void* data member that may be used
69 for transferring event-specific data to the receiver.
71 \warning The internal data is not destroyed by the class destructor.
76 \param type event type
78 PyEvent_CustomEvent::PyEvent_CustomEvent( int type )
79 : QEvent( (QEvent::Type)type ), d( 0 )
85 \param type event type
86 \param data custom data
88 PyEvent_CustomEvent::PyEvent_CustomEvent( QEvent::Type type, void* data )
89 : QEvent( type ), d( data )
94 \brief Get custom data.
95 \return pointer to the internal data
97 void* PyEvent_CustomEvent::data() const
103 \brief Set custom data.
104 \param data pointer to the internal data
106 void PyEvent_CustomEvent::setData( void* data )
113 \brief The class which encapsulates data and functionality required for
114 posting component-specific events to perform arbitrary operations
115 in the main GUI thread.
117 PyEvent_Event objects can be posted by any thread belonging to the GUI process.
119 It is necessary to derive a custom event class from PyEvent_Event and
120 re-implement virtual Execute() method. This method should actually perform
121 the desirable operation. To pass all the required data to Execute() and
122 store a return value, arbitrary data fields can be added to the custom
123 event class. There is no need to protect such fields with a mutex, for only
124 one thread working with a PyEvent_Event object is active at any moment.
127 - Create PyEvent_Event. Components can derive their own event class from
128 PyEvent_Event in order to pass custom data to the event handler.
129 - Call process() method to post the event. After process() execution
130 it is possible to examine fields of your custom event object.
131 - Perform delete operator on the event to wake up the desktop (you can also
132 set <autoRelease> parameter to \c true to automatically wake up desktop after
135 The method processed() is used by the desktop to signal that event processing
138 To make all this work, it is necessary to call static method GetSessionThread()
139 during the application initialization, i.e. from main() function.
140 It is important to call this method from the primary application thread.
146 //! Total number of semaphore resources
147 const int NumberOfResources = 2;
150 \brief Initialize event mechanism.
152 This function sets up the main application thread. It should be called
153 during the application initialization, i.e. main() function.
155 void PyEvent_Event::GetSessionThread(){
157 myThread = ::GetCurrentThreadId();
159 myThread = pthread_self();
164 \brief Check if the processing is in the main application thread.
165 \return \c true if this method is called from the main application thread
167 bool PyEvent_Event::IsSessionThread(){
168 bool aResult = false;
170 aResult = myThread == ::GetCurrentThreadId();
172 aResult = myThread == pthread_self();
180 PyEvent_Event::PyEvent_Event(){
181 // Prepare the semaphore
182 mySemaphore = new QSemaphore( NumberOfResources );
183 mySemaphore->acquire( NumberOfResources );
189 PyEvent_Event::~PyEvent_Event(){
190 if ( mySemaphore->available() < NumberOfResources )
191 mySemaphore->release( NumberOfResources - mySemaphore->available() );
196 \brief This method should be called by the main GUI thread
197 in order to execute the code specific for this event and finally
198 to inform the calling thread that the event
199 has been processed waking it up with help of the semaphore .
201 void PyEvent_Event::ExecutePostedEvent()
203 // Diagnose incorrect usage of PyEvent_Event API
204 if ( !IsSessionThread() ){
205 qWarning( "PyEvent_Event::ExecutePostedEvent() is called from a secondary thread that might mean an error in application logic!" );
207 // Actual execution specific for particular kind of event
209 // Signal the calling thread that the event has been processed
214 \brief Post the event and wait for its completion.
215 process() should be called from a secondary thread only.
218 void PyEvent_Event::process()
220 // Diagnose incorrect usage of PyEvent_Event API
221 if ( IsSessionThread() ){
222 qWarning( "PyEvent_Event::process() is called from the main GUI thread that might mean an error in application logic!" );
225 QApplication::postEvent( qApp, new PyEvent_CustomEvent( PyEvent_EVENT, (void*)this ) );
226 mySemaphore->acquire( 1 );
230 \brief Use this method to signal that this event has been processed.
232 void PyEvent_Event::processed()
234 mySemaphore->release( 1 );
238 \fn virtual void PyEvent_Event::Execute();
239 \brief This method should be redefined in the successor classes
245 \brief Template class for event which calls the function
246 without arguments and returning result.
250 \class TVoidMemFunEvent
251 \brief Template class for event which calls the function
252 without arguments and without return value.
256 \class TMemFun1ArgEvent
257 \brief Template class for event which calls the function
258 with one argument and returning result.
262 \class TVoidMemFun1ArgEvent
263 \brief Template class for event which calls the function
264 with one argument and without return value.
268 \class TMemFun2ArgEvent
269 \brief Template class for event which calls the function
270 with two arguments and returning result.
274 \class TVoidMemFun2ArgEvent
275 \brief Template class for event which calls the function
276 with two arguments and without return value.
281 \brief Template function for processing events with return value.
286 \brief Template function for processing events without return value.