Salome HOME
NRI : Merge from Event_Server.
authornri <nri@opencascade.com>
Fri, 30 Apr 2004 12:50:12 +0000 (12:50 +0000)
committernri <nri@opencascade.com>
Fri, 30 Apr 2004 12:50:12 +0000 (12:50 +0000)
src/Event/Makefile.in [new file with mode: 0644]
src/Event/SALOME_Event.cxx [new file with mode: 0644]
src/Event/SALOME_Event.hxx [new file with mode: 0644]

diff --git a/src/Event/Makefile.in b/src/Event/Makefile.in
new file mode 100644 (file)
index 0000000..426af68
--- /dev/null
@@ -0,0 +1,52 @@
+#  SALOME Utils : general SALOME's definitions and tools
+#
+#  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+#  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
+# 
+#  This library is free software; you can redistribute it and/or 
+#  modify it under the terms of the GNU Lesser General Public 
+#  License as published by the Free Software Foundation; either 
+#  version 2.1 of the License. 
+# 
+#  This library is distributed in the hope that it will be useful, 
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of 
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#  Lesser General Public License for more details. 
+# 
+#  You should have received a copy of the GNU Lesser General Public 
+#  License along with this library; if not, write to the Free Software 
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
+# 
+#  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+#
+#
+#
+#  File   : Makefile.in
+#  Author : Marc Tajchman (CEA)
+#  Module : SALOME
+#  $Header$
+
+top_srcdir=@top_srcdir@
+top_builddir=../..
+srcdir=@srcdir@
+VPATH=.:@srcdir@:@top_srcdir@/idl
+
+
+@COMMENCE@
+
+# header files  
+EXPORT_HEADERS= \
+       SALOME_Event.hxx 
+
+EXPORT_PYSCRIPTS = 
+# Libraries targets
+
+LIB = libEvent.la 
+LIB_SRC = SALOME_Event.cxx 
+
+CPPFLAGS+=$(QT_INCLUDES)
+LDFLAGS+=$(QT_MT_LIBS)
+
+@CONCLUDE@
+
+
diff --git a/src/Event/SALOME_Event.cxx b/src/Event/SALOME_Event.cxx
new file mode 100644 (file)
index 0000000..dfebd7b
--- /dev/null
@@ -0,0 +1,140 @@
+//  KERNEL SALOME_Event : Define event posting mechanism
+//
+//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
+// 
+//  This library is free software; you can redistribute it and/or 
+//  modify it under the terms of the GNU Lesser General Public 
+//  License as published by the Free Software Foundation; either 
+//  version 2.1 of the License. 
+// 
+//  This library is distributed in the hope that it will be useful, 
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+//  Lesser General Public License for more details. 
+// 
+//  You should have received a copy of the GNU Lesser General Public 
+//  License along with this library; if not, write to the Free Software 
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
+// 
+//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+//
+//
+//
+//  File   : SALOME_Event.cxx
+//  Author : Sergey ANIKIN
+//  Module : KERNEL
+//  $Header$
+
+#include "SALOME_Event.hxx"
+
+#include "utilities.h"
+
+#include <qsemaphore.h>
+#include <qapplication.h>
+#include <qthread.h>
+
+#ifdef _DEBUG_
+static int MYDEBUG = 0;
+#else
+static int MYDEBUG = 0;
+#endif
+
+//===========================================================
+/*!
+ *  SALOME_Event::SALOME_Event
+ *  Constructor
+ */
+//===========================================================
+SALOME_Event::SALOME_Event(): 
+  myWait( true ),
+  myAutoRelease( false )
+{
+  if(MYDEBUG) MESSAGE( "SALOME_Event::SALOME_Event(): this = "<<this<<", myWait = "<<myWait );
+  if ( myWait ) {
+    // Prepare the semaphore 
+    mySemaphore = new QSemaphore( 2 );
+    mySemaphore->operator+=( 2 );
+  }
+}
+
+//===========================================================
+/*!
+ *  SALOME_Event::~SALOME_Event
+ *  Destructor
+ */
+//===========================================================
+SALOME_Event::~SALOME_Event()
+{
+  if(MYDEBUG) MESSAGE( "SALOME_Event::~SALOME_Event(): this = "<<this<<", myWait = "<<myWait );
+  if ( myWait ) {
+    if ( mySemaphore->available() < mySemaphore->total() )
+      mySemaphore->operator-=( mySemaphore->total() - mySemaphore->available() );
+    delete mySemaphore;
+  }
+}
+
+//===========================================================
+/*!
+ *  SALOME_Event::process
+ *  Posts the event and optionally waits for its completion
+ */
+//===========================================================
+void SALOME_Event::process()
+{
+  if(MYDEBUG) MESSAGE( "SALOME_Event::process(): this = "<<this<<", myWait = "<<myWait );
+  QThread::postEvent( qApp, new QCustomEvent( SALOME_EVENT, (void*)this ) );
+  if ( myWait ) {
+    if(MYDEBUG) MESSAGE( "SALOME_Event::process(): available = " << mySemaphore->available() );
+    if ( !mySemaphore->available() )
+      mySemaphore->operator+=( 1 );
+
+    if(MYDEBUG) MESSAGE( "SALOME_Event::process() COMPLETED: this = "<<this<<", myWait = "<<myWait );
+  }
+  if ( myAutoRelease )
+    release();
+}
+
+//===========================================================
+/*!
+ *  SALOME_Event::processed
+ *  Signals that this event has been processed
+ */
+//===========================================================
+void SALOME_Event::processed()
+{
+  if(MYDEBUG) MESSAGE( "SALOME_Event::processed(): this = "<<this<<", myWait = "<<myWait );
+  if ( myWait ) {
+    if(MYDEBUG) MESSAGE( "SALOME_Event::processed(): available = " << mySemaphore->available() );
+    if ( !mySemaphore->available() ) {
+      // process() takes control over mySemaphore after the next line is executed
+      mySemaphore->operator-=( 1 );
+
+      if(MYDEBUG) MESSAGE( "SALOME_Event::processed(): semaphore DECREMENTED" );
+
+      // Current thread will block here until process() completes
+      mySemaphore->operator+=( mySemaphore->total() );
+    }
+  }
+  if(MYDEBUG) MESSAGE( "SALOME_Event::processed() COMPLETED: this = "<<this<<", myWait = "<<myWait );
+}
+
+//===========================================================
+/*!
+ *  SALOME_Event::release
+ *  Wakes up the desktop
+ */
+//===========================================================
+void SALOME_Event::release()
+{
+  if(MYDEBUG) MESSAGE( "SALOME_Event::release(): this = "<<this<<", myWait = "<<myWait );
+  if ( myWait ) {
+    if(MYDEBUG) MESSAGE( "SALOME_Event::release(): available = " << mySemaphore->available() );
+    mySemaphore->operator-=( mySemaphore->total() - mySemaphore->available() );
+  }
+  if(MYDEBUG) MESSAGE( "SALOME_Event::release() COMPLETED: this = "<<this<<", myWait = "<<myWait );
+}
+
+
+
+
diff --git a/src/Event/SALOME_Event.hxx b/src/Event/SALOME_Event.hxx
new file mode 100644 (file)
index 0000000..2467912
--- /dev/null
@@ -0,0 +1,259 @@
+//  KERNEL SALOME_Event : Define event posting mechanism
+//
+//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
+// 
+//  This library is free software; you can redistribute it and/or 
+//  modify it under the terms of the GNU Lesser General Public 
+//  License as published by the Free Software Foundation; either 
+//  version 2.1 of the License. 
+// 
+//  This library is distributed in the hope that it will be useful, 
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+//  Lesser General Public License for more details. 
+// 
+//  You should have received a copy of the GNU Lesser General Public 
+//  License along with this library; if not, write to the Free Software 
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
+// 
+//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+//
+//
+//
+//  File   : SALOME_Event.hxx
+//  Author : Sergey ANIKIN
+//  Module : KERNEL
+//  $Header$
+
+
+#ifndef SALOME_Event_HeaderFile
+#define SALOME_Event_HeaderFile
+
+#include <qevent.h>
+
+#define SALOME_EVENT QEvent::Type( QEvent::User + 10000 )
+
+class QSemaphore;
+
+//===========================================================
+/*!
+ *  Class: SALOME_Event
+ *  Description: 
+ *  This class encapsulates data and functionality required for 
+ *  posting component-specific events to perform arbitrary operations in main GUI thread. 
+ *  SALOME_Event objects can be posted by any thread belonging to the GUI process.
+ *
+ *  It is necessary to derive a custom event class from SALOME_Event and 
+ *  re-implement virtual Execute() method. This method should actually perform 
+ *  the desirable operation. To pass all the required data to Execute() and store a return value,
+ *  arbitrary data fields can be added to the custom event class. There is 
+ *  no need to protect such fields with a mutex, for only one thread working with
+ *  a SALOME_Event object is active at any moment.
+ *
+ *  It is possible to make the thread that creates SALOME_Event
+ *  wait until the event is processed by the component GUI, SALOME_Event
+ *  should be constructed with <wait> == TRUE in such a case.
+ *
+ *  SALOME_Event objects should be created on the heap. QAD_Desktop deletes
+ *  these objects as soon as they have been processed.
+ *
+ *  Usage:
+ *  - create SALOME_Event object on the heap with proper <type> and <wait> parameters. 
+ *    Components can derive their own event class from SALOME_Event
+ *    in order to pass custom data to the event handler.
+ *  - call process() method to post the event. Between process() and release()
+ *    it is possible to examine fields of your custom event object.
+ *  - call release() method to wake up the desktop (you can also set <autoRelease>
+ *    parameter to TRUE to automatically wake up desktop after process()
+ * 
+ *  processed() method is used by the desktop to signal that event processing 
+ *  has been completed.
+ *  
+ *  Caveats: 
+ *  1. Never create SALOME_Event with <wait> == TRUE in code that is 
+ *     supposed to be called within main GUI thread, for this will result
+ *     in GUI process deadlock.
+ *  2. Always call release() method after process() if you use <wait> parameters as TRUE,
+ *     otherwise processed() method will never return and main GUI thread will be blocked!
+ *  3. Never use pointers to the event after it has been released (either by calling release()
+ *     or automatically by process() if <autoRelease> == TRUE) to avoid application crashes!
+ */
+//===========================================================
+
+
+class SALOME_Event
+{
+public:
+  SALOME_Event();
+  virtual ~SALOME_Event();
+
+  // To do real work
+  virtual void Execute() = 0;
+
+  void process();
+  void processed();
+
+  void release();
+
+private:
+  bool        myWait;
+  bool        myAutoRelease;
+  QSemaphore* mySemaphore;
+};
+
+
+// Template classes for member function
+//-------------------------------------
+template<class TObject, typename TRes>
+class TMemFunEvent: public SALOME_Event{
+public:
+  typedef TRes TResult;
+  TResult myResult;
+  typedef TResult (TObject::* TAction)();
+  TMemFunEvent(TObject* theObject, TAction theAction, 
+              TResult theResult = TResult()):
+    myObject(theObject),
+    myAction(theAction),
+    myResult(theResult)
+  {}
+  virtual void Execute(){
+    myResult = (myObject->*myAction)();
+  }
+private:
+  TObject* myObject;
+  TAction myAction;
+};
+
+
+template<class TObject>
+class TVoidMemFunEvent: public SALOME_Event{
+public:
+  typedef void (TObject::* TAction)();
+  TVoidMemFunEvent(TObject* theObject, TAction theAction):
+    myObject(theObject),
+    myAction(theAction)
+  {}
+  virtual void Execute(){
+    (myObject->*myAction)();
+  }
+private:
+  TObject* myObject;
+  TAction myAction;
+};
+
+
+// Template for member function with one argument
+//-----------------------------------------------
+template<class TObject, typename TRes, 
+        typename TArg, typename TStoreArg = TArg>
+class TMemFun1ArgEvent: public SALOME_Event{
+public:
+  typedef TRes TResult;
+  TResult myResult;
+  typedef TResult (TObject::* TAction)(TArg);
+  TMemFun1ArgEvent(TObject* theObject, TAction theAction, TArg theArg, 
+                  TResult theResult = TResult()):
+    myObject(theObject),
+    myAction(theAction),
+    myResult(theResult),
+    myArg(theArg)
+  {}
+  virtual void Execute(){
+    myResult = (myObject->*myAction)(myArg);
+  }
+private:
+  TObject* myObject;
+  TAction myAction;
+  TStoreArg myArg;
+};
+
+
+template<class TObject, typename TArg, typename TStoreArg = TArg>
+class TVoidMemFun1ArgEvent: public SALOME_Event{
+public:
+  typedef void (TObject::* TAction)(TArg);
+  TVoidMemFun1ArgEvent(TObject* theObject, TAction theAction, TArg theArg):
+    myObject(theObject),
+    myAction(theAction),
+    myArg(theArg)
+  {}
+  virtual void Execute(){
+    (myObject->*myAction)(myArg);
+  }
+private:
+  TObject* myObject;
+  TAction myAction;
+  TStoreArg myArg;
+};
+
+
+// Template for member function with one argument
+//-----------------------------------------------
+template<class TObject, typename TRes,
+        typename TArg, typename TArg1, 
+        typename TStoreArg = TArg, typename TStoreArg1 = TArg1>
+class TMemFun2ArgEvent: public SALOME_Event{
+public:
+  typedef TRes TResult;
+  TResult myResult;
+  typedef TResult (TObject::* TAction)(TArg,TArg1);
+  TMemFun2ArgEvent(TObject* theObject, TAction theAction, 
+                  TArg theArg, TArg1 theArg1,
+                  TResult theResult = TResult()):
+    myObject(theObject),
+    myAction(theAction),
+    myResult(theResult),
+    myArg(theArg),
+    myArg1(theArg1)
+  {}
+  virtual void Execute(){
+    myResult = (myObject->*myAction)(myArg,myArg1);
+  }
+private:
+  TObject* myObject;
+  TAction myAction;
+  TStoreArg myArg;
+  TStoreArg1 myArg1;
+};
+
+
+template<class TObject, typename TArg, typename TArg1, 
+        typename TStoreArg = TArg, typename TStoreArg1 = TArg1>
+class TVoidMemFun2ArgEvent: public SALOME_Event{
+public:
+  typedef void (TObject::* TAction)(TArg,TArg1);
+  TVoidMemFun2ArgEvent(TObject* theObject, TAction theAction, TArg theArg, TArg1 theArg1):
+    myObject(theObject),
+    myAction(theAction),
+    myArg(theArg),
+    myArg1(theArg1)
+  {}
+  virtual void Execute(){
+    (myObject->*myAction)(myArg,myArg1);
+  }
+private:
+  TObject* myObject;
+  TAction myAction;
+  TStoreArg myArg;
+  TStoreArg1 myArg1;
+};
+
+
+// Template function for processing events with result returing
+template<class TEvent> inline typename TEvent::TResult ProcessEvent(TEvent* theEvent){
+  theEvent->process();
+  typename TEvent::TResult aResult = theEvent->myResult;
+  theEvent->release();
+  return aResult;
+}
+
+
+// Template function for processing events without result
+inline void ProcessVoidEvent(SALOME_Event* theEvent){
+  theEvent->process();
+  theEvent->release();
+}
+
+
+#endif