Cogs.Core
ComponentPool.cpp
1#include "ComponentPool.h"
2
3#include "../Reflection/TypeDatabase.h"
4
5#include <OsoMemoryProfiler/CogsMemoryProfile.h>
6
7#include <numeric>
8#include <algorithm>
9#include <cmath>
10
11using namespace Cogs::Reflection;
12
14 next(0),
15 roster(allocator),
16 store(allocator, memType),
17 elementSize(0),
18 componentType(typeId),
19 flags(ComponentPoolFlags::None)
20{
21 const auto & type = TypeDatabase::getType(componentType);
22
23 elementSize = type.getSize();
24
26}
27
29{
30 if (isSet(ComponentPoolFlags::AllowGrow) && static_cast<size_t>(next) == roster.size()) {
31 const size_t newSize = std::min(static_cast<size_t>(maxSize()), static_cast<size_t>(std::round(static_cast<double>(roster.size()) * 1.55)));
32
33 resize(static_cast<SizeType>(newSize));
34 }
35
36 assert(next < roster.size() && "Component pool over capacity.");
37
38 // Find next free component.
39 const auto nextIndex = roster[next];
40 auto component = get(nextIndex);
41
42 const auto & type = TypeDatabase::getType(componentType);
43
44 // Initialize component by calling default constructor.
45 TypeDatabase::constructInstance(type, component, elementSize);
46
47 OsoMP_Allocate(COGSMEM_Component, component, elementSize, nullptr, 0);
48
49 // Initialize housekeeping data.
50 static uint16_t generation = 0;
51 component->setIndex(next++);
52 component->setTypeId(componentType);
53 component->setActive();
54 component->setGeneration(generation);
55
56 return ComponentHandle{ this, nextIndex, componentType, generation++ };
57}
58
60{
61 auto component = handle.resolve();
62 const auto & type = TypeDatabase::getType(componentType);
63
64 const ComponentIndex rosterIndex = component->getIndex();
65
66 OsoMP_Free(COGSMEM_Component, component, nullptr, 0);
67
68 assert(rosterIndex < next && "Roster index out of bounds");
69
70 // Move old component index to first free roster slot.
71 std::swap(roster[rosterIndex], roster[--next]);
72
73 // Component index fix up.
74 get(roster[rosterIndex])->setIndex(rosterIndex);
75
76 component->setGeneration(component->getGeneration() + 1);
77
78 // Destroy old component by invoking destructor.
79 TypeDatabase::destructInstance(type, component);
80
81#ifdef _DEBUG
82 constexpr const uint8_t bytes [] = {
83 0x3F, 0xB3, 0xAD, 0xDE
84 };
85
86 // Set memory to detect uninitialized usage easier.
87 for (size_t i = 0; i < type.getSize(); ++i) {
88 reinterpret_cast<uint8_t *>(component)[i] = bytes[i % 4];
89 }
90#endif
91}
92
94{
95 const size_t oldSize = roster.size();
96
97 roster.resize(capacity);
98 store.resize(static_cast<size_t>(capacity) * elementSize, true, false);
99
100 std::iota(roster.begin() + oldSize, roster.end(), next);
101}
102
104{
105 return std::numeric_limits<SizeType>::max();
106}
COGSFOUNDATION_API void resize(SizeType capacity)
Resize the pool.
COGSFOUNDATION_API SizeType maxSize() const
Get the maximum size of the pool.
COGSFOUNDATION_API ComponentHandle allocateComponent()
Allocates and initializes a new component using placement new into the backing store.
SizeType capacity() const
Get the capacity of the pool, the number of components that can be allocated without resizing the poo...
Definition: ComponentPool.h:80
COGSFOUNDATION_API ComponentPoolBase(const Reflection::TypeId typeId, SizeType capacity, Memory::Allocator *allocator, MemBlockType memType)
Constructs a new pool base for components with the given type.
COGSFOUNDATION_API void deallocateComponent(ComponentHandle handle)
Deallocates a component from the pool, calling the destructor of the derived component type.
Base allocator implementation.
Definition: Allocator.h:30
static const Type & getType()
Get the Type of the given template argument.
Definition: TypeDatabase.h:168
static void destructInstance(const Type &type, void *data)
Destruct an instance of the given type located in data.
static void constructInstance(const Type &type, void *data, const size_t dataSize)
Construct an instance of the given type into the given data.
Contains reflection support.
Definition: Component.h:11
uint16_t TypeId
Built in type used to uniquely identify a single type instance.
Definition: Name.h:48
uint32_t ComponentIndex
Type used to track component indexes in pools.
Definition: Component.h:16
ComponentIndex SizeType
Type used to track the size of pools.
Definition: Component.h:19
Handle to a Component instance.
Definition: Component.h:67
COGSFOUNDATION_API class Component * resolve() const
Resolve the handle, returning a pointer to the held Component instance.
Definition: Component.cpp:65
Contains component pool flags.
Definition: ComponentPool.h:14
@ AllowGrow
Allows the component pool to grow on demand.
Definition: ComponentPool.h:23