summaryrefslogtreecommitdiff
path: root/src/core/managed
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/managed')
-rw-r--r--src/core/managed/Managed.cpp16
-rw-r--r--src/core/managed/Managed.hpp34
-rw-r--r--src/core/managed/Manager.cpp64
-rw-r--r--src/core/managed/Manager.hpp50
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);
};
}