]> code.bitgloo.com Git - clyne/entityx.git/commitdiff
Fix unpacking bug (segfault from lambda).
authorAlec Thomas <alec@swapoff.org>
Wed, 24 Oct 2012 20:14:48 +0000 (16:14 -0400)
committerAlec Thomas <alec@swapoff.org>
Wed, 24 Oct 2012 20:14:48 +0000 (16:14 -0400)
entityx/Entity.h
entityx/Entity_test.cc

index 356c773d5c4fae2838603822ec8bd5f05b3a03ce..013830e4dfcd6c79f923ceb72d9d6f2e80167dc1 100644 (file)
@@ -180,14 +180,10 @@ class EntityManager : boost::noncopyable {
         while (i_ < manager_.size() && !predicate()) {
           ++i_;
         }
-        if (i_ < manager_.size()) {
-          unpack();
-        }
-      }
-
-      void unpack() {
-        for (auto unpacker : unpackers_) {
-          unpacker(i_);
+        if (i_ < manager_.size() && !unpackers_.empty()) {
+          for (auto unpacker : unpackers_) {
+            unpacker(i_);
+          }
         }
       }
 
@@ -218,20 +214,35 @@ class EntityManager : boost::noncopyable {
 
     template <typename A>
     View &unpack_to(boost::shared_ptr<A> &a) {
-      unpackers_.push_back([&] (Entity id) {
+      unpackers_.push_back(Unpacker<A>(manager_, a));
+      // This resulted in a segfault under clang 4.1 on OSX. No idea why. 
+      /*unpackers_.push_back([&a, this](Entity id) {
         a = manager_.component<A>(id);
-      });
+      });*/
       return *this;
     }
 
     template <typename A, typename B, typename ... Args>
-    View &unpack_to(boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args *& ... args) {
+    View &unpack_to(boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args && ... args) {
       unpack_to<A>(a);
       return unpack_to<B, Args ...>(b, args ...);
     }
    private:
     friend class EntityManager;
 
+    template <typename T>
+    struct Unpacker {
+      Unpacker(EntityManager &manager, boost::shared_ptr<T> &c) : manager(manager), c(c) {}
+
+      void operator () (Entity id) {
+        c = manager.component<T>(id);
+      }
+
+     private:
+      EntityManager &manager;
+      boost::shared_ptr<T> &c;
+    };
+
     View(EntityManager &manager, Predicate predicate) : manager_(manager) {
       predicates_.push_back(predicate);
     }
@@ -331,44 +342,24 @@ class EntityManager : boost::noncopyable {
     return boost::static_pointer_cast<C>(c);
   }
 
-  /**
-   * Get all entities with the given component.
-   */
-  template <typename C>
-  View entities_with_components() {
-    auto mask = component_mask<C>();
-    return View(*this, View::ComponentMaskPredicate(entity_component_mask_, mask));
-  }
-
   /**
    * Find Entities that have all of the specified Components.
    */
-  template <typename C1, typename C2, typename ... Components>
+  template <typename C, typename ... Components>
   View entities_with_components() {
-    auto mask = component_mask<C1, C2, Components ...>();
+    uint64_t mask = component_mask<C, Components ...>();
     return View(*this, View::ComponentMaskPredicate(entity_component_mask_, mask));
   }
 
-  /**
-   * Get all entities with the given component.
-   */
-  template <typename C>
-  View entities_with_components(boost::shared_ptr<C> &c) {
-    auto mask = component_mask<C>();
-    return
-        View(*this, View::ComponentMaskPredicate(entity_component_mask_, mask))
-        .unpack_to<C>(c);
-  }
-
   /**
    * Find Entities that have all of the specified Components.
    */
-  template <typename C1, typename C2, typename ... Components>
-  View entities_with_components(boost::shared_ptr<C1> &c1, boost::shared_ptr<C2> &c2, Components *& ... args) {
-    auto mask = component_mask<C1, C2, Components ...>();
+  template <typename C, typename ... Components>
+  View entities_with_components(boost::shared_ptr<C> &c, Components && ... args) {
+    uint64_t mask = component_mask(c, args ...);
     return
         View(*this, View::ComponentMaskPredicate(entity_component_mask_, mask))
-        .unpack_to<C1, C2, Components...>(c1, c2, args...);
+        .unpack_to(c, args ...);
   }
 
   /**
@@ -399,7 +390,7 @@ class EntityManager : boost::noncopyable {
    * unpack<Position, Direction>(e, p, d);
    */
   template <typename A, typename B, typename ... Args>
-  void unpack(Entity id, boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args & ... args) {
+  void unpack(Entity id, boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args && ... args) {
     unpack<A>(id, a);
     unpack<B, Args ...>(id, b, args ...);
   }
@@ -415,6 +406,16 @@ class EntityManager : boost::noncopyable {
     return component_mask<C1>() | component_mask<C2, Components ...>();
   }
 
+  template <typename C>
+  uint64_t component_mask(const boost::shared_ptr<C> &c) {
+    return uint64_t(1) << C::family();
+  }
+
+  template <typename C1, typename C2, typename ... Components>
+  uint64_t component_mask(const boost::shared_ptr<C1> &c1, const boost::shared_ptr<C2> &c2, Components && ... args) {
+    return component_mask<C1>(c1) | component_mask<C2, Components ...>(c2, args...);
+  }
+
   inline void accomodate_entity(Entity entity) {
     if (entity_component_mask_.size() <= entity) {
       entity_component_mask_.resize(entity + 1);
index aa1b32bf21ab5ef1ce269f9873a9f2b61a621b08..805a3d3f423c733c7959308b9392c46b2ae87546 100644 (file)
@@ -164,6 +164,7 @@ TEST_F(EntityManagerTest, TestGetEntitiesWithComponentAndUnpacking) {
           em.assign<Direction>(f, 9.0f, 10.0f)));
   em.assign<Position>(g, 5.0f, 6.0f);
   int i = 0;
+
   shared_ptr<Position> position;
   shared_ptr<Direction> direction;
   for (auto unused_entity : em.entities_with_components(position, direction)) {