]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Initial version of event loop functionality (not multi-threaded)
authormpv <mikhail.ponikarov@opencascade.com>
Thu, 13 Mar 2014 15:29:27 +0000 (19:29 +0400)
committermpv <mikhail.ponikarov@opencascade.com>
Thu, 13 Mar 2014 15:29:27 +0000 (19:29 +0400)
CMakeLists.txt
src/Event/CMakeLists.txt [new file with mode: 0644]
src/Event/Event.hxx [new file with mode: 0644]
src/Event/Event_Listener.cxx [new file with mode: 0644]
src/Event/Event_Listener.hxx [new file with mode: 0644]
src/Event/Event_Loop.cxx [new file with mode: 0644]
src/Event/Event_Loop.hxx [new file with mode: 0644]
src/Event/Event_Message.cxx [new file with mode: 0644]
src/Event/Event_Message.hxx [new file with mode: 0644]

index 16974454f665d810c81cca521ccea5909e4fdf1d..d67d35f11e9488913dd8d57f1ea8b0fd0203561c 100644 (file)
@@ -7,6 +7,7 @@ SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeCommon" ${CMAKE_MODULE_PATH})
 INCLUDE(Common)
 INCLUDE(FindQt5)
 
+ADD_SUBDIRECTORY (src/Event)
 #ADD_SUBDIRECTORY (src/ModelAPI)
 ADD_SUBDIRECTORY (src/Model)
 ADD_SUBDIRECTORY (src/XGUI)
diff --git a/src/Event/CMakeLists.txt b/src/Event/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7a8af5b
--- /dev/null
@@ -0,0 +1,23 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11)
+
+INCLUDE(Common)
+
+SET(PROJECT_HEADERS
+    Event.hxx
+    Event_Message.hxx
+    Event_Listener.hxx
+    Event_Loop.hxx
+)
+
+SET(PROJECT_SOURCES
+    Event_Message.cxx
+    Event_Listener.cxx
+    Event_Loop.cxx
+)
+
+ADD_DEFINITIONS(-DEVENT_EXPORTS)
+ADD_LIBRARY(Event SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS})
+TARGET_LINK_LIBRARIES(Event ${PROJECT_LIBRARIES})
+
+INCLUDE_DIRECTORIES(
+)
diff --git a/src/Event/Event.hxx b/src/Event/Event.hxx
new file mode 100644 (file)
index 0000000..d99cd00
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef EVENT_H
+#define EVENT_H
+
+#if defined EVENT_EXPORTS
+#if defined WIN32
+#define EVENT_EXPORT              __declspec( dllexport )
+#else
+#define EVENT_EXPORT
+#endif
+#else
+#if defined WIN32
+#define EVENT_EXPORT              __declspec( dllimport )
+#else
+#define EVENT_EXPORT
+#endif
+#endif
+
+#endif
diff --git a/src/Event/Event_Listener.cxx b/src/Event/Event_Listener.cxx
new file mode 100644 (file)
index 0000000..44f9075
--- /dev/null
@@ -0,0 +1,5 @@
+// File:       Event_Listener.cxx
+// Created:    Thu Mar 13 2014
+// Author:     Mikhail PONIKAROV
+
+#include <Event_Listener.hxx>
\ No newline at end of file
diff --git a/src/Event/Event_Listener.hxx b/src/Event/Event_Listener.hxx
new file mode 100644 (file)
index 0000000..f5d70ba
--- /dev/null
@@ -0,0 +1,25 @@
+// File:       Event_Listener.hxx
+// Created:    Thu Mar 13 2014
+// Author:     Mikhail PONIKAROV
+
+#ifndef Event_Listener_HeaderFile
+#define Event_Listener_HeaderFile
+
+#include <Event.hxx>
+class Event_Message;
+
+/**\class Event_Listener
+ * \ingroup EventLoop
+ * \brief Base interface for any event listener.
+ *
+ * If some object wants to listen some events it must inherit
+ * this class and register in the Loop.
+ */
+EVENT_EXPORT class Event_Listener {
+
+public:
+  //! This method is called by loop when the event is started to process.
+  virtual void ProcessEvent(const Event_Message* theMessage) = 0;
+};
+
+#endif
diff --git a/src/Event/Event_Loop.cxx b/src/Event/Event_Loop.cxx
new file mode 100644 (file)
index 0000000..b1f22b5
--- /dev/null
@@ -0,0 +1,80 @@
+// File:       Event_Loop.hxx
+// Created:    Thu Mar 13 2014
+// Author:     Mikhail PONIKAROV
+
+#include <Event_Loop.hxx>
+#include <string>
+
+using namespace std;
+
+Event_Loop* Event_Loop::Loop()
+{
+  // initialized on initialization of the application
+  static Event_Loop MAIN_LOOP;
+  return &MAIN_LOOP;
+}
+
+Event_ID Event_Loop::EventByName(const char* theName)
+{
+  ///! All events created in this session, uniquely identified by the text and char pointer
+  static map<string, char*> CREATED_EVENTS;
+  char* aResult;
+  string aName(theName);
+  map<string, char*>::iterator aFound = CREATED_EVENTS.find(aName);
+  if (aFound == CREATED_EVENTS.end()) { //not created yet
+    aResult = strdup(theName); // copy to make unique internal pointer
+    CREATED_EVENTS[aName] = aResult;
+  } else 
+    aResult = aFound->second;
+
+  return Event_ID(aResult);
+}
+
+void Event_Loop::Send(Event_Message theMessage)
+{
+  // TO DO: make it in thread and wit husage of semaphores
+
+  map<char*, map<void*, list<Event_Listener*> > >::iterator aFindID = 
+    myListeners.find(theMessage.ID().EventText());
+  if (aFindID != myListeners.end()) {
+    map<void*, list<Event_Listener*> >::iterator aFindSender = 
+      aFindID->second.find(theMessage.Sender());
+    if (aFindSender != aFindID->second.end()) {
+      list<Event_Listener*>& aListeners = aFindSender->second;
+      for(list<Event_Listener*>::iterator aL = aListeners.begin(); aL != aListeners.end(); aL++)
+        (*aL)->ProcessEvent(&theMessage);
+    }
+    if (theMessage.Sender()) { // also call for NULL senders registered
+      aFindSender = aFindID->second.find(NULL);
+      if (aFindSender != aFindID->second.end()) {
+        list<Event_Listener*>& aListeners = aFindSender->second;
+        for(list<Event_Listener*>::iterator aL = aListeners.begin(); aL != aListeners.end(); aL++)
+          (*aL)->ProcessEvent(&theMessage);
+      }
+    }
+  }
+}
+
+void Event_Loop::RegisterListener(
+  Event_Listener* theListener, const Event_ID theID, void* theSender)
+{
+  map<char*, map<void*, list<Event_Listener*> > >::iterator aFindID = 
+    myListeners.find(theID.EventText());
+  if (aFindID == myListeners.end()) { // create container associated with ID
+    myListeners[theID.EventText()] = map<void*, list<Event_Listener*> >();
+    aFindID = myListeners.find(theID.EventText());
+  }
+
+  map<void*, list<Event_Listener*> >::iterator aFindSender = 
+    aFindID->second.find(theSender);
+  if (aFindSender == aFindID->second.end()) { // create container associated with sender
+    aFindID->second[theSender] = list<Event_Listener*>();
+    aFindSender = aFindID->second.find(theSender);
+  }
+  // check that listener was not registered wit hsuch parameters before
+  list<Event_Listener*>& aListeners = aFindSender->second;
+  for(list<Event_Listener*>::iterator aL = aListeners.begin(); aL != aListeners.end(); aL++)
+    if (*aL == theListener) return; // avoid duplicates
+
+  aListeners.push_back(theListener);
+}
diff --git a/src/Event/Event_Loop.hxx b/src/Event/Event_Loop.hxx
new file mode 100644 (file)
index 0000000..7b6da95
--- /dev/null
@@ -0,0 +1,46 @@
+// File:       Event_Loop.hxx
+// Created:    Thu Mar 13 2014
+// Author:     Mikhail PONIKAROV
+
+#ifndef Event_Loop_HeaderFile
+#define Event_Loop_HeaderFile
+
+#include <Event_Message.hxx>
+#include <Event_Listener.hxx>
+
+#include <map>
+#include <list>
+
+/**\class Event_Lopp
+ * \ingroup EventLoop
+ * \brief Base class that manages the receiving and sending of all
+ * not Qt-events in the application.
+ *
+ * One per application, initialized on start. Listeners must register in this loop
+ * to get events, called by senders. Sending of events is very fast (just adding to container).
+ * Performing of events is processed in separated thread, so, sender takes 
+ * control back immideately.
+ */
+class Event_Loop {
+  std::map<char*, std::map<void*, std::list<Event_Listener*> > >
+    myListeners; ///< map from event ID to sender pointer to listeners that must be called for this
+
+  //! The empty constructor, will be called at startup of the application, only once
+  Event_Loop() {};
+public:
+  ///! Returns the main object of the loop, one per application.
+  EVENT_EXPORT static Event_Loop* Loop();
+  //! Returns the unique event by the given name. Call this method only on initialization of object
+  //! to speedup the events processing without parsing of the string.
+  EVENT_EXPORT static Event_ID EventByName(const char* theName);
+
+  //! Allows to send an event
+  EVENT_EXPORT void Send(Event_Message theMessage);
+
+  //! Registers (or adds if such listener is already registered) a listener 
+  //! that will be called on the event and from the defined sender
+  EVENT_EXPORT void RegisterListener(Event_Listener* theListener, const Event_ID theID, 
+    void* theSender = 0);
+};
+
+#endif
diff --git a/src/Event/Event_Message.cxx b/src/Event/Event_Message.cxx
new file mode 100644 (file)
index 0000000..02a018e
--- /dev/null
@@ -0,0 +1,5 @@
+// File:       Event_Message.cxx
+// Created:    Thu Mar 13 2014
+// Author:     Mikhail PONIKAROV
+
+#include <Event_Message.hxx>
diff --git a/src/Event/Event_Message.hxx b/src/Event/Event_Message.hxx
new file mode 100644 (file)
index 0000000..b9abe11
--- /dev/null
@@ -0,0 +1,54 @@
+// File:       Event_Message.hxx
+// Created:    Thu Mar 13 2014
+// Author:     Mikhail PONIKAROV
+
+#ifndef Event_Message_HeaderFile
+#define Event_Message_HeaderFile
+
+#include <Event.hxx>
+
+/**\class Event_ID
+ * \ingroup EventLoop
+ * \brief Identifier of the event kind.
+ *
+ * Each event ID is created in main Envent_Loop class
+ * that stores correspondance between the string-name of the
+ * identifier and the pointer to the static string that is really
+ * used as an identifier (this is usefull for debugging of the events
+ * with log files and in debugger).
+ */
+EVENT_EXPORT class Event_ID {
+  char* myID; ///< pointer to the text-identifier of the event, unique pointer for all events of such type
+
+  Event_ID(char* theID) {myID = theID;}
+
+  friend class Event_Loop;
+public:
+  /// Returns the text-identifier of the event (for debugging reasons)
+  char* EventText() const {return myID;}
+  /// Allows to compare identifiers
+  bool operator==(const Event_ID& theID) const {return myID == theID.myID;}
+};
+
+/**\class Event_Message
+ * \ingroup EventLoop
+ * \brief Message for communication between sender and listener of event.
+ * Normally it is inherited by the higher-level 
+ */
+EVENT_EXPORT class Event_Message {
+  Event_ID myID; ///< identifier of the event
+  void* mySender; ///< the sender object
+
+public:
+
+  //! Creates the message
+  Event_Message(const Event_ID theID, const void* theSender = 0);
+
+  //! Returns identifier of the message
+  const Event_ID& ID() const {return myID;}
+
+  //! Returns sender of the message or NULL if it is anonymous message
+  void* Sender() {return mySender;}
+};
+
+#endif