]> code.bitgloo.com Git - clyne/entityx.git/commitdiff
Added unsubscribe feature to EventManager. Also added tests in Event_test.cc that...
authorrobin <robgro@telia.com>
Thu, 5 Feb 2015 00:06:08 +0000 (01:06 +0100)
committerrobin <robgro@telia.com>
Thu, 5 Feb 2015 00:20:56 +0000 (01:20 +0100)
entityx/Event.h
entityx/Event_test.cc

index 6e6757db7eec791a4f680843cd8d7b8d82da6519..b6249f94863a655628581af134c346cd4908ba82 100644 (file)
@@ -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);
index 04d06403d81a0f8f7a31cc551990117b2df50d12..041ee8a1c3dedba3057464ac720a1ef759d6cf6d 100644 (file)
@@ -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);
+  }
+}