]> code.bitgloo.com Git - clyne/entityx.git/commitdiff
Increase cache coherency.
authorAlec Thomas <alec@swapoff.org>
Sun, 2 Mar 2014 01:50:01 +0000 (12:50 +1100)
committerAlec Thomas <alec@swapoff.org>
Sun, 2 Mar 2014 01:50:01 +0000 (12:50 +1100)
Mainly achieved by allocating components in contiguous memory blocks.
This is a breaking change, thus the major version bump.

entityx/Benchmarks_test.cc
entityx/Entity.cc
entityx/Entity.h
entityx/Entity_test.cc
entityx/System_test.cc

index 100defde55d16b11ff50413e95ca69262e2775a8..2790ae0faf78fc8405fad21ea557585494a5caa7 100644 (file)
@@ -107,9 +107,8 @@ TEST_F(BenchmarksTest, TestEntityIteration) {
   cout << "iterating over " << count << " entities with a component 10 times" << endl;
 
   for (int i = 0; i < 10; ++i) {
-    ptr<Position> position;
+    ComponentPtr<Position> position;
     for (auto e : em->entities_with_components<Position>(position)) {
-      position.get();
     }
   }
 }
index 48b582772ecc1633c201f7a4e35e96caf3cbbc98..f23e974a089625b066f56dc8fa9276001195d837 100644 (file)
@@ -35,13 +35,18 @@ EntityManager::EntityManager(ptr<EventManager> event_manager) : event_manager_(e
 }
 
 EntityManager::~EntityManager() {
+  reset();
 }
 
-void EntityManager::destroy_all() {
-  entity_components_.clear();
+void EntityManager::reset() {
+  for (auto allocator : component_allocators_) {
+    if (allocator) delete allocator;
+  }
+  component_allocators_.clear();
   entity_component_mask_.clear();
   entity_version_.clear();
   free_list_.clear();
+  index_counter_ = 0;
 }
 
 
index 1758c3fc58dcc0313cffaa28ac510b1c97f4049b..84a8cfb63eddf93868ffe8b87e57a6d5db47e9eb 100644 (file)
@@ -12,6 +12,7 @@
 
 
 #include <stdint.h>
+#include <cstdlib>
 #include <algorithm>
 #include <bitset>
 #include <cassert>
@@ -33,6 +34,10 @@ namespace entityx {
 class EntityManager;
 
 
+template <typename T>
+class ComponentPtr;
+
+
 /** A convenience handle around an Entity::Id.
  *
  * If an entity is destroyed, any copies will be invalidated. Use valid() to
@@ -71,10 +76,9 @@ public:
   static const Id INVALID;
 
   Entity() {}
-  Entity(const ptr<EntityManager> &manager, Entity::Id id) : manager_(manager), id_(id) {
-  }
-  Entity(const Entity &other) : manager_(other.manager_), id_(other.id_) {
-  }
+  Entity(const ptr<EntityManager> &manager, Entity::Id id) : manager_(manager), id_(id) {}
+  Entity(const Entity &other) : manager_(other.manager_), id_(other.id_) {}
+
   Entity &operator = (const Entity &other) {
     manager_ = other.manager_;
     id_ = other.id_;
@@ -117,18 +121,18 @@ public:
   Id id() const { return id_; }
 
   template <typename C>
-  ptr<C> assign(ptr<C> component);
+  ComponentPtr<C> assign(ComponentPtr<C> component);
   template <typename C, typename ... Args>
-  ptr<C> assign(Args && ... args);
+  ComponentPtr<C> assign(Args && ... args);
 
   template <typename C>
-  ptr<C> remove();
+  void remove();
 
   template <typename C>
-  ptr<C> component();
+  ComponentPtr<C> component();
 
   template <typename A, typename ... Args>
-  void unpack(ptr<A> &a, ptr<Args> & ... args);
+  void unpack(ComponentPtr<A> &a, ComponentPtr<Args> & ... args);
 
   /**
    * Destroy and invalidate this Entity.
@@ -195,6 +199,34 @@ struct Component : public BaseComponent {
 };
 
 
+template <typename T>
+class ComponentPtr {
+public:
+  ComponentPtr() : id_(0), manager_(nullptr) {}
+
+  T *operator -> ();
+
+  const T *operator -> () const;
+
+  operator bool () const;
+
+  bool operator == (const ComponentPtr<T> &other) const {
+    return other.id_ == id_ && other.manager_ == manager_;
+  }
+
+private:
+  friend class EntityManager;
+
+  ComponentPtr(Entity::Id id, EntityManager *manager) : id_(id), manager_(manager) {}
+
+  template <typename R>
+  friend inline std::ostream &operator << (std::ostream &out, const ComponentPtr<R> &ptr);
+
+  Entity::Id id_;
+  EntityManager *manager_;
+};
+
+
 /**
  * Emitted when an entity is added to the system.
  */
@@ -220,11 +252,11 @@ struct EntityDestroyedEvent : public Event<EntityDestroyedEvent> {
  */
 template <typename T>
 struct ComponentAddedEvent : public Event<ComponentAddedEvent<T>> {
-  ComponentAddedEvent(Entity entity, ptr<T> component) :
+  ComponentAddedEvent(Entity entity, ComponentPtr<T> component) :
       entity(entity), component(component) {}
 
   Entity entity;
-  ptr<T> component;
+  ComponentPtr<T> component;
 };
 
 /**
@@ -232,13 +264,89 @@ struct ComponentAddedEvent : public Event<ComponentAddedEvent<T>> {
  */
 template <typename T>
 struct ComponentRemovedEvent : public Event<ComponentRemovedEvent<T>> {
-  ComponentRemovedEvent(Entity entity, ptr<T> component) :
+  ComponentRemovedEvent(Entity entity, ComponentPtr<T> component) :
       entity(entity), component(component) {}
 
   Entity entity;
-  ptr<T> component;
+  ComponentPtr<T> component;
+};
+
+
+/**
+ * Cache-friendly component allocator.
+ */
+class BaseComponentAllocator {
+public:
+  BaseComponentAllocator(int sizeof_element, int size = 0) :
+      sizeof_(sizeof_element), size_(0), capacity_(32),
+      components_(static_cast<char*>(malloc(sizeof_ * 32))) {
+    reserve(size);
+  }
+
+  virtual ~BaseComponentAllocator() {
+    free(components_);
+  }
+
+  /**
+   * Get a pointer to the nth element.
+   */
+  void *get(int n) {
+    assert(n < size_);
+    return static_cast<void*>(components_ + n * sizeof_);
+  }
+
+  const void *get(int n) const {
+    assert(n < size_);
+    return static_cast<const void*>(components_ + n * sizeof_);
+  }
+
+  /**
+   * Resize the underlying array so it fits *at least* n elements.
+   */
+  void reserve(int n) {
+    if (n >= size_) {
+      // Resize underlying array.
+      if (n >= capacity_) {
+        while (n >= capacity_)
+          capacity_ *= 2;
+        components_ = static_cast<char*>(realloc(components_, capacity_ * sizeof_));
+        assert(components_);
+      }
+      size_ = n + 1;
+    }
+  }
+
+  /**
+   * Call the destructor of the object at slot n.
+   */
+  virtual void destroy(int n) = 0;
+
+private:
+  int sizeof_;
+  int size_;
+  int capacity_;
+  char *components_;
+};
+
+
+template <typename T>
+class ComponentAllocator : public BaseComponentAllocator {
+public:
+  explicit ComponentAllocator(int size = 0) : BaseComponentAllocator(sizeof(T), size) {}
+
+  virtual void destroy(int n) {
+    T *ptr = static_cast<T*>(get(n));
+    ptr->~T();
+  }
 };
 
+
+template <typename T>
+inline std::ostream &operator << (std::ostream &out, const ComponentPtr<T> &ptr) {
+  return out << *(ptr.manager_->template get_component_ptr<T>(ptr.id_));
+}
+
+
 /**
  * Manages Entity::Id creation and component assignment.
  */
@@ -260,16 +368,16 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
     /// A predicate that matches valid entities with the given component mask.
     class ComponentMaskPredicate {
      public:
-      ComponentMaskPredicate(const std::vector<ComponentMask> &entity_components, ComponentMask mask)
-          : entity_components_(entity_components), mask_(mask) {}
+      ComponentMaskPredicate(const std::vector<ComponentMask> &entity_component_masks, ComponentMask mask)
+          : entity_component_masks_(entity_component_masks), mask_(mask) {}
 
       bool operator()(const ptr<EntityManager> &entities, const Entity::Id &entity) {
         return entities->entity_version_[entity.index()] == entity.version()
-            && (entity_components_[entity.index()] & mask_) == mask_;
+            && (entity_component_masks_[entity.index()] & mask_) == mask_;
       }
 
      private:
-      const std::vector<ComponentMask> &entity_components_;
+      const std::vector<ComponentMask> &entity_component_masks_;
       ComponentMask mask_;
     };
 
@@ -343,13 +451,13 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
     const Iterator end() const { return Iterator(manager_, predicates_, unpackers_, manager_->capacity()); }
 
     template <typename A>
-    View &unpack_to(ptr<A> &a) {
+    View &unpack_to(ComponentPtr<A> &a) {
       unpackers_.push_back(ptr<Unpacker<A>>(new Unpacker<A>(manager_, a)));
       return *this;
     }
 
     template <typename A, typename B, typename ... Args>
-    View &unpack_to(ptr<A> &a, ptr<B> &b, ptr<Args> & ... args) {
+    View &unpack_to(ComponentPtr<A> &a, ComponentPtr<B> &b, ComponentPtr<Args> & ... args) {
       unpack_to<A>(a);
       return unpack_to<B, Args ...>(b, args ...);
     }
@@ -359,7 +467,7 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
 
     template <typename T>
     struct Unpacker : BaseUnpacker {
-      Unpacker(ptr<EntityManager> manager, ptr<T> &c) : manager_(manager), c(c) {}
+      Unpacker(ptr<EntityManager> manager, ComponentPtr<T> &c) : manager_(manager), c(c) {}
 
       void unpack(const Entity::Id &id) {
         c = manager_->component<T>(id);
@@ -367,7 +475,7 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
 
      private:
       ptr<EntityManager> manager_;
-      ptr<T> &c;
+      ComponentPtr<T> &c;
     };
 
     View(ptr<EntityManager> manager, Predicate predicate) : manager_(manager) {
@@ -423,19 +531,19 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
    * Emits EntityDestroyedEvent.
    */
   void destroy(Entity::Id entity) {
-    assert(entity.index() < entity_component_mask_.size() && "Entity::Id ID outside entity vector range");
-    assert(entity_version_[entity.index()] == entity.version() && "Attempt to destroy Entity using a stale Entity::Id");
+    assert_valid(entity);
+    int index = entity.index();
     event_manager_->emit<EntityDestroyedEvent>(Entity(shared_from_this(), entity));
-    for (auto &components : entity_components_) {
-      components[entity.index()].reset();
+    for (BaseComponentAllocator *allocator : component_allocators_) {
+      if (allocator) allocator->destroy(index);
     }
-    entity_component_mask_[entity.index()] = 0;
-    entity_version_[entity.index()]++;
-    free_list_.push_back(entity.index());
+    entity_component_mask_[index] = 0;
+    entity_version_[index]++;
+    free_list_.push_back(index);
   }
 
   Entity get(Entity::Id id) {
-    assert(entity_version_[id.index()] == id.version() && "Attempt to get() with stale Entity::Id");
+    assert_valid(id);
     return Entity(shared_from_this(), id);
   }
 
@@ -450,31 +558,22 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
   }
 
   /**
-   * Assigns a previously constructed Component to an Entity::Id.
-   *
-   * @returns component
-   */
-  template <typename C>
-  ptr<C> assign(Entity::Id id, ptr<C> component) {
-    ptr<BaseComponent> base(static_pointer_cast<BaseComponent>(component));
-    accomodate_component(C::family());
-    entity_components_[C::family()][id.index()] = base;
-    entity_component_mask_[id.index()] |= uint64_t(1) << C::family();
-
-    event_manager_->emit<ComponentAddedEvent<C>>(Entity(shared_from_this(), id), component);
-    return component;
-  }
-
-  /**
-   * Assign a Component to an Entity::Id, optionally passing through Component constructor arguments.
+   * Assign a Component to an Entity::Id, passing through Component constructor arguments.
    *
-   *     ptr<Position> position = em.assign<Position>(e, x, y);
+   *     ComponentPtr<Position> position = em.assign<Position>(e, x, y);
    *
-   * @returns Newly created component.
+   * @returns Smart pointer to newly created component.
    */
   template <typename C, typename ... Args>
-  ptr<C> assign(Entity::Id entity, Args && ... args) {
-    return assign<C>(entity, ptr<C>(new C(std::forward<Args>(args) ...)));
+  ComponentPtr<C> assign(Entity::Id id, Args && ... args) {
+    assert_valid(id);
+    const int family = C::family();
+    ComponentAllocator<C> *allocator = accomodate_component<C>();
+    new(allocator->get(id.index())) C(std::forward<Args>(args) ...);
+    entity_component_mask_[id.index()] |= uint64_t(1) << family;
+    ComponentPtr<C> component(id, this);
+    event_manager_->emit<ComponentAddedEvent<C>>(Entity(shared_from_this(), id), component);
+    return ComponentPtr<C>(id, this);
   }
 
   /**
@@ -483,13 +582,16 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
    * Emits a ComponentRemovedEvent<C> event.
    */
   template <typename C>
-  ptr<C> remove(const Entity::Id &id) {
-    ptr<C> component(static_pointer_cast<C>(entity_components_[C::family()][id.index()]));
-    entity_components_[C::family()][id.index()].reset();
-    entity_component_mask_[id.index()] &= ~(uint64_t(1) << C::family());
-    if (component)
-      event_manager_->emit<ComponentRemovedEvent<C>>(Entity(shared_from_this(), id), component);
-    return component;
+  void remove(Entity::Id id) {
+    assert_valid(id);
+    const int family = C::family();
+    const int index = id.index();
+    BaseComponentAllocator *allocator = component_allocators_[family];
+    assert(allocator);
+    entity_component_mask_[id.index()] &= ~(uint64_t(1) << family);
+    ComponentPtr<C> component(id, this);
+    event_manager_->emit<ComponentRemovedEvent<C>>(Entity(shared_from_this(), id), component);
+    allocator->destroy(index);
   }
 
   /**
@@ -498,13 +600,16 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
    * @returns Component instance, or empty ptr<> if the Entity::Id does not have that Component.
    */
   template <typename C>
-  ptr<C> component(const Entity::Id &id) {
+  ComponentPtr<C> component(Entity::Id id) {
+    assert_valid(id);
+    size_t family = C::family();
     // We don't bother checking the component mask, as we return a nullptr anyway.
-    if (C::family() >= entity_components_.size()) {
-      return ptr<C>();
-    }
-    ptr<BaseComponent> c = entity_components_[C::family()][id.index()];
-    return ptr<C>(static_pointer_cast<C>(c));
+    if (family >= component_allocators_.size())
+      return ComponentPtr<C>();
+    BaseComponentAllocator *allocator = component_allocators_[family];
+    if (!allocator || !entity_component_mask_[id.index()][family])
+      return ComponentPtr<C>();
+    return ComponentPtr<C>(id, this);
   }
 
   /**
@@ -521,7 +626,7 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
    * to the given parameters.
    */
   template <typename C, typename ... Components>
-  View entities_with_components(ptr<C> &c, ptr<Components> & ... args) {
+  View entities_with_components(ComponentPtr<C> &c, ComponentPtr<Components> & ... args) {
     auto mask = component_mask(c, args ...);
     return
         View(shared_from_this(), View::ComponentMaskPredicate(entity_component_mask_, mask))
@@ -529,7 +634,8 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
   }
 
   template <typename A>
-  void unpack(Entity::Id id, ptr<A> &a) {
+  void unpack(Entity::Id id, ComponentPtr<A> &a) {
+    assert_valid(id);
     a = component<A>(id);
   }
 
@@ -540,26 +646,53 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
    *
    * Useful for fast bulk iterations.
    *
-   * ptr<Position> p;
-   * ptr<Direction> d;
+   * ComponentPtr<Position> p;
+   * ComponentPtr<Direction> d;
    * unpack<Position, Direction>(e, p, d);
    */
   template <typename A, typename ... Args>
-  void unpack(Entity::Id id, ptr<A> &a, ptr<Args> & ... args) {
+  void unpack(Entity::Id id, ComponentPtr<A> &a, ComponentPtr<Args> & ... args) {
+    assert_valid(id);
     a = component<A>(id);
     unpack<Args ...>(id, args ...);
   }
 
   /**
-   * Destroy all entities from this EntityManager.
+   * Destroy all entities and reset the EntityManager.
    */
-  void destroy_all();
+  void reset();
+
+ private:
+  template <typename C>
+  friend class ComponentPtr;
+  friend class Entity;
+
+  inline void assert_valid(Entity::Id id) const {
+    assert(id.index() < entity_component_mask_.size() && "Entity::Id ID outside entity vector range");
+    assert(entity_version_[id.index()] == id.version() && "Attempt to access Entity via a stale Entity::Id");
+  }
+
+  template <typename C>
+  C *get_component_ptr(Entity::Id id) {
+    assert(valid(id));
+    BaseComponentAllocator *allocator = component_allocators_[C::family()];
+    assert(allocator);
+    return static_cast<C*>(allocator->get(id.index()));
+  }
+
+  template <typename C>
+  const C *get_component_ptr(Entity::Id id) const {
+    assert_valid(id);
+    BaseComponentAllocator *allocator = component_allocators_[C::family()];
+    assert(allocator);
+    return static_cast<const C*>(allocator->get(id.index()));
+  }
 
   ComponentMask component_mask(Entity::Id id) {
+    assert_valid(id);
     return entity_component_mask_.at(id.index());
   }
 
- private:
   template <typename C>
   ComponentMask component_mask() {
     ComponentMask mask;
@@ -573,12 +706,12 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
   }
 
   template <typename C>
-  ComponentMask component_mask(const ptr<C> &c) {
+  ComponentMask component_mask(const ComponentPtr<C> &c) {
     return component_mask<C>();
   }
 
   template <typename C1, typename C2, typename ... Components>
-  ComponentMask component_mask(const ptr<C1> &c1, const ptr<C2> &c2, ptr<Components> & ... args) {
+  ComponentMask component_mask(const ComponentPtr<C1> &c1, const ComponentPtr<C2> &c2, ComponentPtr<Components> & ... args) {
     return component_mask<C1>(c1) | component_mask<C2, Components ...>(c2, args...);
   }
 
@@ -586,26 +719,30 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
     if (entity_component_mask_.size() <= index) {
       entity_component_mask_.resize(index + 1);
       entity_version_.resize(index + 1);
-      for (auto &components : entity_components_) {
-          components.resize(index + 1);
+      for (BaseComponentAllocator *allocator : component_allocators_) {
+          if (allocator) allocator->reserve(index);
       }
     }
   }
 
-  inline void accomodate_component(BaseComponent::Family family) {
-    if (entity_components_.size() <= family) {
-      entity_components_.resize(family + 1);
-      for (auto &components : entity_components_) {
-          components.resize(index_counter_);
-      }
+  template <typename T>
+  ComponentAllocator<T> *accomodate_component() {
+    BaseComponent::Family family = T::family();
+    if (component_allocators_.size() <= family) {
+      component_allocators_.resize(family + 1, nullptr);
     }
+    if (!component_allocators_[family]) {
+      component_allocators_[family] = new ComponentAllocator<T>(index_counter_);
+    }
+    return static_cast<ComponentAllocator<T>*>(component_allocators_[family]);
   }
 
+
   uint32_t index_counter_ = 0;
 
   ptr<EventManager> event_manager_;
-  // A nested array of: components = entity_components_[family][entity]
-  std::vector<std::vector<ptr<BaseComponent>>> entity_components_;
+  // Each element in component_allocators_ corresponds to a Component::family().
+  std::vector<BaseComponentAllocator*> component_allocators_;
   // Bitmask of components associated with each entity. Index into the vector is the Entity::Id.
   std::vector<ComponentMask> entity_component_mask_;
   // Vector of entity version numbers. Incremented each time an entity is destroyed
@@ -621,32 +758,26 @@ BaseComponent::Family Component<C>::family() {
   return family;
 }
 
-template <typename C>
-ptr<C> Entity::assign(ptr<C> component) {
-  assert(valid());
-  return manager_.lock()->assign<C>(id_, component);
-}
-
 template <typename C, typename ... Args>
-ptr<C> Entity::assign(Args && ... args) {
+ComponentPtr<C> Entity::assign(Args && ... args) {
   assert(valid());
   return manager_.lock()->assign<C>(id_, std::forward<Args>(args) ...);
 }
 
 template <typename C>
-ptr<C> Entity::remove() {
+void Entity::remove() {
   assert(valid() && component<C>());
-  return manager_.lock()->remove<C>(id_);
+  manager_.lock()->remove<C>(id_);
 }
 
 template <typename C>
-ptr<C> Entity::component() {
+ComponentPtr<C> Entity::component() {
   assert(valid());
   return manager_.lock()->component<C>(id_);
 }
 
 template <typename A, typename ... Args>
-void Entity::unpack(ptr<A> &a, ptr<Args> & ... args) {
+void Entity::unpack(ComponentPtr<A> &a, ComponentPtr<Args> & ... args) {
   assert(valid());
   manager_.lock()->unpack(id_, a, args ...);
 }
@@ -655,6 +786,20 @@ inline bool Entity::valid() const {
   return !manager_.expired() && manager_.lock()->valid(id_);
 }
 
+template <typename T>
+inline T *ComponentPtr<T>::operator -> () {
+  return manager_->get_component_ptr<T>(id_);
+}
+
+template <typename T>
+inline const T *ComponentPtr<T>::operator -> () const {
+  return manager_->get_component_ptr<T>(id_);
+}
+
+template <typename T>
+inline ComponentPtr<T>::operator bool () const {
+  return manager_ && manager_->valid(id_);
+}
 
 
 }  // namespace entityx
index 925b282d5c25b499e70d140f8a117a364ca845c8..553a15966e29758eebb7c05919689c1770b9c2c1 100644 (file)
@@ -144,24 +144,14 @@ TEST_F(EntityManagerTest, TestComponentConstruction) {
   ASSERT_FLOAT_EQ(2.0, cp->y);
 }
 
-TEST_F(EntityManagerTest, TestComponentCreationWithObject) {
-  auto e = em->create();
-  auto p = e.assign(ptr<Position>(new Position(1.0, 2.0)));
-  auto cp = e.component<Position>();
-  ASSERT_EQ(p, cp);
-  ASSERT_FLOAT_EQ(1.0, cp->x);
-  ASSERT_FLOAT_EQ(2.0, cp->y);
-}
-
 TEST_F(EntityManagerTest, TestDestroyEntity) {
   Entity e = em->create();
   Entity f = em->create();
-  auto ep = e.assign<Position>();
+  e.assign<Position>();
   f.assign<Position>();
   e.assign<Direction>();
   f.assign<Direction>();
 
-  ASSERT_EQ(2, use_count(ep));
   ASSERT_TRUE(e.valid());
   ASSERT_TRUE(f.valid());
   ASSERT_TRUE(static_cast<bool>(e.component<Position>()));
@@ -175,7 +165,6 @@ TEST_F(EntityManagerTest, TestDestroyEntity) {
   ASSERT_TRUE(f.valid());
   ASSERT_TRUE(static_cast<bool>(f.component<Position>()));
   ASSERT_TRUE(static_cast<bool>(f.component<Direction>()));
-  ASSERT_EQ(1, use_count(ep));
 }
 
 TEST_F(EntityManagerTest, TestGetEntitiesWithComponent) {
@@ -210,7 +199,7 @@ TEST_F(EntityManagerTest, TestGetEntitiesWithComponentAndUnpacking) {
   Entity e = em->create();
   Entity f = em->create();
   Entity g = em->create();
-  std::vector<std::pair<ptr<Position>, ptr<Direction>>> position_directions;
+  std::vector<std::pair<ComponentPtr<Position>, ComponentPtr<Direction>>> position_directions;
   position_directions.push_back(std::make_pair(
           e.assign<Position>(1.0f, 2.0f),
           e.assign<Direction>(3.0f, 4.0f)));
@@ -222,10 +211,10 @@ TEST_F(EntityManagerTest, TestGetEntitiesWithComponentAndUnpacking) {
   int i = 0;
 
 
-  ptr<Position> position;
+  ComponentPtr<Position> position;
   ASSERT_EQ(3, size(em->entities_with_components(position)));
 
-  ptr<Direction> direction;
+  ComponentPtr<Direction> direction;
   for (auto unused_entity : em->entities_with_components(position, direction)) {
     (void)unused_entity;
     ASSERT_TRUE(static_cast<bool>(position));
@@ -236,7 +225,7 @@ TEST_F(EntityManagerTest, TestGetEntitiesWithComponentAndUnpacking) {
     ++i;
   }
   ASSERT_EQ(2, i);
-  ptr<Tag> tag;
+  ComponentPtr<Tag> tag;
   i = 0;
   for (auto unused_entity : em->entities_with_components(position, direction, tag)) {
     (void)unused_entity;
@@ -258,9 +247,9 @@ TEST_F(EntityManagerTest, TestUnpack) {
   auto d = e.assign<Direction>(3.0, 4.0);
   auto t = e.assign<Tag>("tag");
 
-  ptr<Position> up;
-  ptr<Direction> ud;
-  ptr<Tag> ut;
+  ComponentPtr<Position> up;
+  ComponentPtr<Direction> ud;
+  ComponentPtr<Tag> ut;
   e.unpack(up);
   ASSERT_EQ(p, up);
   e.unpack(up, ud);
@@ -378,7 +367,7 @@ TEST_F(EntityManagerTest, TestComponentRemovedEvent) {
       removed = event.component;
     }
 
-    ptr<Direction> removed;
+    ComponentPtr<Direction> removed;
   };
 
   ComponentRemovedReceiver receiver;
@@ -386,8 +375,8 @@ TEST_F(EntityManagerTest, TestComponentRemovedEvent) {
 
   ASSERT_FALSE(receiver.removed);
   Entity e = em->create();
-  e.assign<Direction>(1.0, 2.0);
-  auto p = e.remove<Direction>();
+  auto p = e.assign<Direction>(1.0, 2.0);
+  e.remove<Direction>();
   ASSERT_EQ(receiver.removed, p);
   ASSERT_FALSE(e.component<Direction>());
 }
@@ -404,7 +393,7 @@ TEST_F(EntityManagerTest, TestEntityAssignment) {
 
 TEST_F(EntityManagerTest, TestEntityDestroyAll) {
   Entity a = em->create(), b = em->create();
-  em->destroy_all();
+  em->reset();
   ASSERT_FALSE(a.valid());
   ASSERT_FALSE(b.valid());
 }
index b08416e37e781ff8df945f99b47bc9758fd8ec2c..e0d5b6a4961cbdc7b670f5ff7cf80b6590a39fe3 100644 (file)
@@ -38,8 +38,8 @@ class MovementSystem : public System<MovementSystem> {
 
   void update(ptr<EntityManager> es, ptr<EventManager> events, double) override {
     EntityManager::View entities = es->entities_with_components<Position, Direction>();
-    ptr<Position> position;
-    ptr<Direction> direction;
+    ComponentPtr<Position> position;
+    ComponentPtr<Direction> direction;
     for (auto entity : entities) {
       entity.unpack<Position, Direction>(position, direction);
       position->x += direction->x;
@@ -101,8 +101,8 @@ TEST_F(SystemManagerTest, TestApplySystem) {
   manager.sm()->configure();
 
   manager.sm()->update<MovementSystem>(0.0);
-  ptr<Position> position;
-  ptr<Direction> direction;
+  ComponentPtr<Position> position;
+  ComponentPtr<Direction> direction;
   for (auto entity : manager.entities) {
     entity.unpack<Position, Direction>(position, direction);
     if (position && direction) {