diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-01-02 16:00:01 +0100 |
---|---|---|
committer | Andreas Stöckel <andreas@somweyr.de> | 2015-01-02 16:00:01 +0100 |
commit | 128ac91adfdab4a21836c4f19d7024dba9790f9e (patch) | |
tree | 20ae14f5c9e2cbd1e2ae6ce37f4fb575c5ea237a /src/core/managed | |
parent | dd3fccac307527d3b1285f6ac7966b6d527627cb (diff) |
Moved event system from the Node class to the Managed class (with zero overhead if is not used)
Diffstat (limited to 'src/core/managed')
-rw-r--r-- | src/core/managed/Managed.cpp | 16 | ||||
-rw-r--r-- | src/core/managed/Managed.hpp | 34 | ||||
-rw-r--r-- | src/core/managed/Manager.cpp | 64 | ||||
-rw-r--r-- | src/core/managed/Manager.hpp | 50 |
4 files changed, 161 insertions, 3 deletions
diff --git a/src/core/managed/Managed.cpp b/src/core/managed/Managed.cpp index dc3731f..d9db0e0 100644 --- a/src/core/managed/Managed.cpp +++ b/src/core/managed/Managed.cpp @@ -54,6 +54,22 @@ bool Managed::deleteData(const std::string &key) { return mgr.deleteData(this, key); } +EventId Managed::registerEvent(EventType type, EventHandler handler, + Handle<Managed> owner) +{ + return mgr.registerEvent(this, type, handler, owner.get()); +} + +bool Managed::unregisterEvent(EventId id) +{ + return mgr.unregisterEvent(this, id); +} + +bool Managed::triggerEvent(Event &data) +{ + return mgr.triggerEvent(this, data); +} + const RttiBase &Managed::type() const { return typeOf(*this); diff --git a/src/core/managed/Managed.hpp b/src/core/managed/Managed.hpp index 5daa667..4a38dbd 100644 --- a/src/core/managed/Managed.hpp +++ b/src/core/managed/Managed.hpp @@ -135,6 +135,40 @@ public: bool deleteData(const std::string &key); + /* Event handling methods */ + + /** + * Registers an event handler for an event of the given type. + * + * @param type is the event type that should be registered. + * @param handler is the callback function. + * @param owner is a managed object that owns the event handler. A reference + * from the the reference object to the owner is added. The argument may be + * nullptr in which case no reference is added. The owner is passed to the + * event handler as second parameter. + * @return a numeric event id, which is unique for the given reference + * object. The event id must be used when unregistering event handlers. + */ + EventId registerEvent(EventType type, EventHandler handler, + Handle<Managed> owner); + + /** + * Unregisters the event with the given event id. + * + * @param id is the event that should be unregistered as returned by the + * registerEvent function. + * @return true if the operation was successful, false if either the + * reference object or the event id do not exist. + */ + bool unregisterEvent(EventId id); + + /** + * Triggers the event of the given type for the reference object. + * + * @param data is the event data that should be passed to the handlers. + */ + bool triggerEvent(Event &data); + /* RTTI methods */ /** diff --git a/src/core/managed/Manager.cpp b/src/core/managed/Manager.cpp index fbf1bd3..94eb1b1 100644 --- a/src/core/managed/Manager.cpp +++ b/src/core/managed/Manager.cpp @@ -256,8 +256,9 @@ void Manager::deleteObject(Managed *o, ObjectDescriptor *descr) deleteRef(descr->refOut.begin()->first, o, true); } - // Remove the data store entry + // Remove the data store and the event store entry store.erase(o); + events.erase(o); // Remove the Managed from the "marked" set marked.erase(o); @@ -442,5 +443,66 @@ bool Manager::deleteData(Managed *ref, const std::string &key) } return false; } + +/* Class Manager: Event handling */ + +EventId Manager::registerEvent(Managed *ref, EventType type, + EventHandler handler, Managed *owner) +{ + // Add a reference from the reference object to the owner object + if (owner) { + addRef(owner, ref); + } + + // Create a event handler descriptor and store it along with the + auto &vec = events.emplace(ref, std::vector<EventHandlerDescriptor>{}) + .first->second; + const EventHandlerDescriptor descr(type, handler, owner); + for (size_t i = 0; i < vec.size(); i++) { + if (!vec[i].handler) { + vec[i] = descr; + return i; + } + } + vec.push_back(descr); + return vec.size() - 1; +} + +bool Manager::unregisterEvent(Managed *ref, EventId id) +{ + auto eventsIt = events.find(ref); + if (eventsIt != events.end()) { + auto &vec = eventsIt->second; + if (id < vec.size() && vec[id].handler) { + // Delete the reference from the reference object to the handler + EventHandlerDescriptor &descr = vec[id]; + if (descr.owner) { + deleteRef(descr.owner, ref); + } + + // Remove the handler from the list by resetting handler and owner + // to nullptr + descr.handler = nullptr; + descr.owner = nullptr; + return true; + } + } + return false; +} + +bool Manager::triggerEvent(Managed *ref, Event &data) +{ + bool hasHandler = false; + auto eventsIt = events.find(ref); + if (eventsIt != events.end()) { + for (EventHandlerDescriptor &descr : eventsIt->second) { + if (descr.type == data.type && descr.handler) { + descr.handler(data, descr.owner); + hasHandler = true; + } + } + } + return hasHandler; +} } diff --git a/src/core/managed/Manager.hpp b/src/core/managed/Manager.hpp index 303e591..0e9d519 100644 --- a/src/core/managed/Manager.hpp +++ b/src/core/managed/Manager.hpp @@ -35,6 +35,8 @@ #include <vector> #include <queue> +#include "Events.hpp" + namespace ousia { // Forward declaration @@ -166,9 +168,9 @@ private: std::unordered_map<Managed *, std::map<std::string, Managed *>> store; /** - * Map for storing the tagged memory regions. + * Map storing any attached events. */ - std::map<uintptr_t, std::pair<uintptr_t, void *>> tags; + std::unordered_map<Managed *, std::vector<EventHandlerDescriptor>> events; /** * Recursion depth while performing deletion. This variable is needed @@ -225,6 +227,8 @@ public: */ ~Manager(); + /* Reference management and garbage collection */ + /** * Registers an object for being managed by the Manager. The Manager now has * the sole responsibility for freeing the managed object. Under no @@ -266,6 +270,8 @@ public: */ void sweep(); + /* Data storage */ + /** * Registers some arbitrary data (in form of a Managed object) for the * given reference Managed object under a certain (string) key. Overrides @@ -304,6 +310,46 @@ public: * @return true if data for this key was deleted, false otherwise. */ bool deleteData(Managed *ref, const std::string &key); + + /* Events */ + + /** + * Registers an event handler for an event of the given type for the object + * referenced by ref. + * + * @param ref is the reference object for which the event should be + * registered. + * @param type is the event type that should be registered. + * @param handler is the callback function. + * @param owner is a managed object that owns the event handler. A reference + * from the the reference object to the owner is added. The argument may be + * nullptr in which case no reference is added. The owner is passed to the + * event handler as second parameter. + * @return a numeric event id, which is unique for the given reference + * object. The event id must be used when unregistering event handlers. + */ + EventId registerEvent(Managed *ref, EventType type, EventHandler handler, + Managed *owner); + + /** + * Unregisters the event with the given event id from the given reference + * object. + * + * @param ref is the reference object from which the event should be + * removed. + * @param id is the event that should be unregistered. + * @return true if the operation was successful, false if either the + * reference object or the event id do not exist. + */ + bool unregisterEvent(Managed *ref, EventId id); + + /** + * Triggers the event of the given type for the reference object. + * + * @param ref is the object for which the given event should be triggered. + * @param data is the event data that should be passed to the handlers. + */ + bool triggerEvent(Managed *ref, Event &data); }; } |