
Just to clarify, when I'm talking about allocators having state, what I expect is to be able to do something similar to the following. Note that this is just an example, there are tons of variants of this: template< class ComponentType > class ComponentPool { public: template< typename... Args > ComponentType* create( Args... args ) { if( auto free_slot = find_free_slot() ) { *free_slot = make_optional<ComponentType>( args... ); // or something similar return free_slot.get_ptr(); } return nullptr; } void destroy( ComponentType& component ) { auto slot = find_slot( component ); assert( slot ); *slot = none_t; // reset the slot } template< typename Func > void for_all_living_components( Func&& f ) { for( ComponentSlot& slot : m_components ) { if( !slot ) continue; f( slot.get() ); } } private: using ComponentSlot = boost::optional<ComponentType>; // to know if the component memory is constructed or not. std::array< ComponentSlot, MAX_COMPONENTS_PER_WORLD > m_components; ComponentSlot* find_free_slot() { for( auto& slot : m_components ) if( !slot ) return &slot; return nullptr; } ComponentSlot* find_slot( ComponentType& component ); }; class ComponentSystem { public: class Allocator; Allocator allocator(); // proivde an allocator for component that will use this; template< class ComponentType > void declare_component_type() { auto find_it = m_pool_index.find( typeid(ComponentType) ); if( find_it == end(m_pool_index ) ) { auto new_pool = std::make_unique<PoolSlotSpecific<ComponentType>>(); m_pool_index.insert( std::make_pair( typeid(ComponentType), std::move(new_pool) ) ); } } template< class ComponentType > ComponentPool<ComponentType>* find_pool() { auto find_it = m_pool_index.find( typeid(ComponentType) ); if( find_it != end(m_pool_index ) ) { return find_it->second.get(); } return nullptr; } private: struct PoolSlot{}; template< class ComponentType > struct PoolSlotSpecific { CompomentPool<ComponentType> pool; }; boost::flat_map< std::type_index, std::unique_ptr<PoolSlot> > m_pool_index; }; class World { public: using Entity = boost::mixin::object< ComponentSystem::Allocator >; World() { m_component_system.declare_component_type<PhysicsData>(); m_component_system.declare_component_type<BrainData>(); m_component_system.declare_component_type<GraphicData>(); m_component_system.declare_component_type<AudioData>(); } void update() { const now = m_clock.now(); // here we assmue that the data don't communicate or do it through thread-safe work queues/messages auto physics_update = async( /*some_executor,*/ [&] { m_component_system.find_pool( typeid(PhysicsData) )->for_all_living_components( [&]( PhysicsData& data ) { data.update( now ); } ); }; auto brain_update = async( /*some_executor,*/ [&] { m_component_system.find_pool( typeid(BrainData) )->for_all_living_components( [&]( BrainData& data ) { data.update( now ); } ); }; when_all( physics_update, brain_update ); // for some reasons, cannot be updated in parallel m_component_system.find_pool( typeid(GraphicData) )->for_all_living_components( [&]( GraphicData& data ) { data.update( now ); } ); m_component_system.find_pool( typeid(AudioData) )->for_all_living_components( [&]( AudioData& data ) { data.update( now ); } ); } Entity& create_entity( EntityInfo info ) { m_entities.emplace_back(); auto& new_entity = m_entities.back( m_component_system.allocator() ); // here we pass an allocator which will use this specific instance of component system. using boost::mixin; mutate( *new_entity ) .add<PhysicsData>( info ) .add<BrainData>( info ) .add<GraphicData>( info ) .add<AudioData>( info ) ; return *new_entity; } private: Clock m_clock; // some kind of clock implementation, which could be or not real time (often it's a virtual time) ComponentSystem m_component_system; boost::stable_vector<Entity> m_entities; // or whatever stable way to list them }; class Universe { public: void update() { parallel_for( auto world_idx : m_awake_worlds_indice ) { m_world[world_idx].update(); } } private: boost::stable_vector<World> m_worlds; std::vector<size_t> m_awake_worlds_indice; }; ------------------------- This is a raw and a bit complex example but I hope it can clarify my request. Joel Lamotte