aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobin <robgro@telia.com>2015-02-05 01:06:08 +0100
committerrobin <robgro@telia.com>2015-02-05 01:20:56 +0100
commit27b0ee23f0be3d26a1aaa845446a499c4c69590c (patch)
tree3889d8ac8e07fb2c196a264a1fa32f18f3a81b93
parent21376ab730cb707f1bb20dfbc3533a2117c80b48 (diff)
Added unsubscribe feature to EventManager. Also added tests in Event_test.cc that checks that it's working correctly.
-rw-r--r--entityx/Event.h31
-rw-r--r--entityx/Event_test.cc14
2 files changed, 40 insertions, 5 deletions
diff --git a/entityx/Event.h b/entityx/Event.h
index 6e6757d..b6249f9 100644
--- a/entityx/Event.h
+++ b/entityx/Event.h
@@ -14,6 +14,7 @@
#include <cstddef>
#include <vector>
#include <list>
+#include <unordered_map>
#include <memory>
#include <utility>
#include "entityx/config.h"
@@ -68,9 +69,9 @@ class BaseReceiver {
public:
virtual ~BaseReceiver() {
for (auto connection : connections_) {
- auto &ptr = connection.first;
+ auto &ptr = connection.second.first;
if (!ptr.expired()) {
- ptr.lock()->disconnect(connection.second);
+ ptr.lock()->disconnect(connection.second.second);
}
}
}
@@ -79,7 +80,7 @@ class BaseReceiver {
std::size_t connected_signals() const {
std::size_t size = 0;
for (auto connection : connections_) {
- if (!connection.first.expired()) {
+ if (!connection.second.first.expired()) {
size++;
}
}
@@ -88,7 +89,7 @@ class BaseReceiver {
private:
friend class EventManager;
- std::list<std::pair<EventSignalWeakPtr, std::size_t>> connections_;
+ std::unordered_map<BaseEvent::Family, std::pair<EventSignalWeakPtr, std::size_t>> connections_;
};
@@ -131,7 +132,27 @@ class EventManager : entityx::help::NonCopyable {
auto wrapper = EventCallbackWrapper<E>(std::bind(receive, &receiver, std::placeholders::_1));
auto connection = sig->connect(wrapper);
BaseReceiver &base = receiver;
- base.connections_.push_back(std::make_pair(EventSignalWeakPtr(sig), connection));
+ base.connections_.insert(std::make_pair(E::family(), std::make_pair(EventSignalWeakPtr(sig), connection)));
+ }
+
+ /**
+ * Unsubscribe an object in order to not receive events of type E anymore.
+ *
+ * Receivers must have subscribed for event E before unsubscribing from event E.
+ *
+ */
+ template <typename E, typename Receiver>
+ void unsubscribe(Receiver &receiver) {
+ BaseReceiver &base = receiver;
+ //Assert that it has been subscribed before
+ assert(base.connections_.find(E::family()) != base.connections_.end());
+ auto pair = base.connections_[E::family()];
+ auto connection = pair.second;
+ auto &ptr = pair.first;
+ if (!ptr.expired()) {
+ ptr.lock()->disconnect(connection);
+ }
+ base.connections_.erase(E::family());
}
void emit(const BaseEvent &event);
diff --git a/entityx/Event_test.cc b/entityx/Event_test.cc
index 04d0640..041ee8a 100644
--- a/entityx/Event_test.cc
+++ b/entityx/Event_test.cc
@@ -80,3 +80,17 @@ TEST_CASE("TestSenderExpired") {
}
REQUIRE(0 == explosion_system.connected_signals());
}
+
+TEST_CASE("TestUnsubscription") {
+ ExplosionSystem explosion_system;
+ {
+ EventManager em;
+ em.subscribe<Explosion>(explosion_system);
+ REQUIRE(explosion_system.damage_received == 0);
+ em.emit<Explosion>(1);
+ REQUIRE(explosion_system.damage_received == 1);
+ em.unsubscribe<Explosion>(explosion_system);
+ em.emit<Explosion>(1);
+ REQUIRE(explosion_system.damage_received == 1);
+ }
+}