Nebula
Loading...
Searching...
No Matches
idallocator.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
23//------------------------------------------------------------------------------
24#include "id.h"
25#include "idpool.h"
26#include "util/array.h"
28#include <tuple>
29#include <utility>
30#include "util/tupleutility.h"
31#include "util/arrayallocator.h"
33#include "idgenerationpool.h"
34
35namespace Ids
36{
37
38template<class ... TYPES>
39class IdAllocator : public Util::ArrayAllocator<TYPES...>
40{
41public:
43 IdAllocator(uint32_t maxid = 0xFFFFFFFF) : maxId(maxid) {};
44
47 {
49 Ids::Id32 id;
50 if (this->pool.Allocate(id))
51 {
53 n_assert2(this->maxId > Ids::Index(id), "max amount of allocations exceeded!\n");
54 }
55
56 return id;
57 }
58
61 {
62 // TODO: We could possibly get better performance when defragging if we insert it in reverse order (high to low)
63 this->pool.Deallocate(id);
64 }
65
67 template<int MEMBER>
68 inline void Set(const Ids::Id32 id, const Util::tuple_array_t<MEMBER, TYPES...>& type)
69 {
70 Util::ArrayAllocator<TYPES...>::template Set<MEMBER>(Ids::Index(id), type);
71 }
72
74 inline void Set(const Ids::Id32 id, TYPES... values)
75 {
77 }
78
80 template<int MEMBER>
81 inline Util::tuple_array_t<MEMBER, TYPES...>& Get(const Ids::Id32 id)
82 {
83 return Util::ArrayAllocator<TYPES...>::template Get<MEMBER>(Ids::Index(id));
84 }
85
87 template<int MEMBER>
88 inline const Util::tuple_array_t<MEMBER, TYPES...>& ConstGet(const Ids::Id32 id) const
89 {
90 return Util::ArrayAllocator<TYPES...>::template ConstGet<MEMBER>(Ids::Index(id));
91 }
92
95 {
96 return this->pool.FreeIds();
97 }
98
100 const uint32_t Size() const
101 {
102 return this->size;
103 }
104
105private:
106 uint32_t maxId = 0xFFFFFFFF;
108};
109
110#define _DECL_ACQUIRE_RELEASE(ty) \
111 bool ty##Acquire(const ty id); \
112 void ty##Release(const ty id); \
113 struct ty##Lock \
114 { \
115 ty##Lock(const ty element) : element(element) { this->didAcquire = ty##Acquire(this->element); } \
116 ~ty##Lock() { if (this->didAcquire) ty##Release(this->element); } \
117 private: \
118 bool didAcquire; \
119 ty element; \
120 };
121
122#define _IMPL_ACQUIRE_RELEASE(ty, allocator) \
123 bool ty##Acquire(const ty id) { return allocator.Acquire(id.id); } \
124 void ty##Release(const ty id) { allocator.Release(id.id); }
125
126template<int MAX_ALLOCS, class... TYPES>
127class IdAllocatorSafe : public Util::ArrayAllocatorSafe<MAX_ALLOCS, TYPES...>
128{
129public:
132 {
133 };
134
137 {
139 this->allocationLock.Lock();
140 Ids::Id32 id;
141 if (this->pool.Allocate(id))
142 {
143 alloc_for_each_in_tuple(this->objects);
144 this->owners.Append(Threading::Thread::GetMyThreadId());
145 n_assert2(MAX_ALLOCS > Ids::Index(id), "max amount of allocations exceeded!\n");
146 }
147 else
148 {
149 this->owners[Ids::Index(id)] = Threading::Thread::GetMyThreadId();
150 }
151 this->allocationLock.Unlock();
152
153 return id;
154 }
155
157 template<int MEMBER>
158 inline void Set(const Ids::Id32 id, const Util::tuple_array_t<MEMBER, TYPES...>& type)
159 {
160 Util::ArrayAllocatorSafe<MAX_ALLOCS, TYPES...>::template Set<MEMBER>(Ids::Index(id), type);
161 }
162
164 inline void Set(const Ids::Id32 id, TYPES... values)
165 {
167 }
168
170 template<int MEMBER>
171 inline Util::tuple_array_t<MEMBER, TYPES...>& Get(const Ids::Id32 id)
172 {
173 return Util::ArrayAllocatorSafe<MAX_ALLOCS, TYPES...>::template Get<MEMBER>(Ids::Index(id));
174 }
175
177 template<int MEMBER>
178 inline const Util::tuple_array_t<MEMBER, TYPES...>& ConstGet(const Ids::Id32 id) const
179 {
180 return Util::ArrayAllocatorSafe<MAX_ALLOCS, TYPES...>::template ConstGet<MEMBER>(Ids::Index(id));
181 }
182
185 {
186 return this->pool.FreeIds();
187 }
188
204
207 {
208 // TODO: We could possibly get better performance when defragging if we insert it in reverse order (high to low)
209 this->allocationLock.Lock();
210 this->pool.Deallocate(id);
211 this->allocationLock.Unlock();
212 }
213
214private:
216};
217
218} // namespace Ids
An ID allocator associates an id with a slice in an N number of arrays.
Definition idallocator.h:40
IdAllocator(uint32_t maxid=0xFFFFFFFF)
constructor
Definition idallocator.h:43
Ids::IdGenerationPool pool
Definition idallocator.h:107
const Util::tuple_array_t< MEMBER, TYPES... > & ConstGet(const Ids::Id32 id) const
Const get element.
Definition idallocator.h:88
Util::Queue< Id32 > & FreeIds()
Get the free ids list from the pool.
Definition idallocator.h:94
void Set(const Ids::Id32 id, TYPES... values)
Set elements.
Definition idallocator.h:74
Ids::Id32 Alloc()
Allocate an object.
Definition idallocator.h:46
uint32_t maxId
Definition idallocator.h:106
void Dealloc(Ids::Id32 id)
Deallocate an object. Just places it in freeids array for recycling.
Definition idallocator.h:60
Util::tuple_array_t< MEMBER, TYPES... > & Get(const Ids::Id32 id)
Get element.
Definition idallocator.h:81
const uint32_t Size() const
return number of allocated ids
Definition idallocator.h:100
void Set(const Ids::Id32 id, const Util::tuple_array_t< MEMBER, TYPES... > &type)
Set element.
Definition idallocator.h:68
Definition idallocator.h:128
bool Acquire(const Ids::Id32 id)
Acquire element, asserts if false and returns true if this call acquired.
Definition idallocator.h:195
Ids::IdGenerationPool pool
Definition idallocator.h:215
void Dealloc(Ids::Id32 id)
Deallocate an object. Just places it in freeids array for recycling.
Definition idallocator.h:206
Ids::Id32 Alloc()
Allocate an object.
Definition idallocator.h:136
void Release(const Ids::Id32 id)
Release an object, the next thread that acquires may use this instance as it fits.
Definition idallocator.h:200
Util::tuple_array_t< MEMBER, TYPES... > & Get(const Ids::Id32 id)
Get element.
Definition idallocator.h:171
void Set(const Ids::Id32 id, TYPES... values)
Set elements.
Definition idallocator.h:164
const Util::tuple_array_t< MEMBER, TYPES... > & ConstGet(const Ids::Id32 id) const
Const get element.
Definition idallocator.h:178
void Set(const Ids::Id32 id, const Util::tuple_array_t< MEMBER, TYPES... > &type)
Set element.
Definition idallocator.h:158
void TryAcquire(const Ids::Id32 id)
Spinlock to acquire.
Definition idallocator.h:190
Util::Queue< Id32 > & FreeIds()
Get the free ids list from the pool.
Definition idallocator.h:184
IdAllocatorSafe()
constructor
Definition idallocator.h:131
Provides a system for creating array friendly id numbers with reuse and generations.
Definition idgenerationpool.h:43
void Deallocate(Id32 id)
remove an id
Definition idgenerationpool.cc:54
bool Allocate(Id32 &id)
allocate a new id, returns true if a new id was created, and false if an id was reused but with new g...
Definition idgenerationpool.cc:33
Util::Queue< Id32 > & FreeIds()
Get free ids.
Definition idgenerationpool.h:102
void Lock()
Lock.
Definition spinlock.h:83
void Unlock()
Unlock.
Definition spinlock.h:103
The ArrayAllocator provides a variadic list of types which is to be contained in the allocator and fe...
Definition arrayallocator.h:34
uint32_t size
Definition arrayallocator.h:104
void Set(const uint32_t index, const tuple_array_t< MEMBER, TYPES... > &type)
set single item
Definition arrayallocator.h:282
uint32_t Alloc()
allocate a new resource
Definition arrayallocator.h:175
The ArrayAllocatorSafe provides a thread safe variadic list of types which is to be contained in the ...
Definition arrayallocatorsafe.h:65
bool Acquire(const uint32_t index)
Acquire element, asserts if false and returns true if this call acquired.
Definition arrayallocatorsafe.h:421
Threading::Spinlock allocationLock
Definition arrayallocatorsafe.h:147
void Set(const uint32_t index, const tuple_array_t< MEMBER, TYPES... > &type)
set single item
Definition arrayallocatorsafe.h:356
void Release(const uint32_t index)
Release an object, the next thread that acquires may use this instance as it fits.
Definition arrayallocatorsafe.h:440
std::tuple< Util::PinnedArray< MAX_ALLOCS, TYPES >... > objects
Definition arrayallocatorsafe.h:144
void TryAcquire(const uint32_t index)
Spinlock to acquire.
Definition arrayallocatorsafe.h:409
Util::Array< Threading::ThreadId > owners
Definition arrayallocatorsafe.h:145
void Append(const TYPE &first, const ELEM_TYPE &... elements)
Append multiple elements to the end of the array.
Definition array.h:1332
Nebula's queue class (a FIFO container).
Definition queue.h:28
#define n_assert2(exp, msg)
Definition debug.h:51
This simple Id pool implements a set of free and used consecutive integers.
Definition id.h:135
static constexpr Id24 Index(const Id32 id)
Definition idgenerationpool.h:72
uint32_t Id32
Definition id.h:138
get_template_type_t< std::tuple_element_t< MEMBER, std::tuple< Util::Array< TYPES >... > > > tuple_array_t
Get type of contained element in Util::Array stored in std::tuple.
Definition tupleutility.h:334