-
Notifications
You must be signed in to change notification settings - Fork 7
/
ManagerImpl.hpp
162 lines (130 loc) · 5.14 KB
/
ManagerImpl.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright (c) 2013-2014 Vittorio Romeo
// License: Academic Free License ("AFL") v. 3.0
// AFL License page: http://opensource.org/licenses/AFL-3.0
#ifndef SSVU_MEMORYMANAGER_INTERNAL_MANAGERIMPL
#define SSVU_MEMORYMANAGER_INTERNAL_MANAGERIMPL
#include "SSVUtils/Range/Range.hpp"
#include "SSVUtils/GrowableArray/GrowableArray.hpp"
namespace ssvu
{
namespace Internal
{
template<typename T, typename TItrValue, typename TImpl> class MMItrBase : public BaseAdaptorItrRnd<TItrValue, TImpl>
{
protected:
TImpl impl;
public:
template<typename... TArgs> inline MMItrBase(TItrValue mValue, TArgs&&... mArgs) noexcept
: BaseAdaptorItrRnd<TItrValue, TImpl>{mValue}, impl{fwd<TArgs>(mArgs)...} { }
inline decltype(auto) operator*() noexcept { return impl.get(this->itr); }
inline decltype(auto) operator*() const noexcept { return impl.get(this->itr); }
inline decltype(auto) operator->() noexcept { return &impl.get(this->itr); }
inline decltype(auto) operator->() const noexcept { return &impl.get(this->itr); }
};
template<typename TBM> struct MMItrImplIdx
{
TBM* bm;
template<typename TV> inline decltype(auto) get(const TV& mValue) noexcept { return bm->getDataAt(mValue); }
};
template<typename TBase, typename TBM> using MMItrIdx = MMItrBase<TBase, SizeT, MMItrImplIdx<TBM>>;
/// @brief Base memory recycler manager class.
/// @tparam TBase Base type of manager objects.
/// @tparam TRecycler Internal recycler type. (MonoRecycler? PolyRecycler?)
template<typename TBase, typename TRecycler> class BaseManager
{
public:
using LayoutType = LayoutImpl::LHelperBool<TBase>;
using ChunkType = Chunk<TBase, LayoutImpl::LHelperBool>;
using ChunkDeleterType = ChunkDeleter<TBase, LayoutImpl::LHelperBool>;
using PtrType = UPtr<TBase, ChunkDeleterType>;
using RecyclerType = TRecycler;
using Container = GrowableArray<PtrType>;
using ItrIdx = MMItrIdx<PtrType, BaseManager<TBase, TRecycler>>;
using ItrIdxC = MMItrIdx<PtrType, const BaseManager<TBase, TRecycler>>;
private:
RecyclerType recycler;
Container items;
SizeT msize{0u}, sizeNext{0u}, capacity{0u};
inline bool isAliveAt(SizeT mI) const noexcept { return isAlive(items[mI].get()); }
inline bool isDeadAt(SizeT mI) const noexcept { return isDead(items[mI].get()); }
public:
inline BaseManager() { reserve(25); }
inline ~BaseManager() { clear(); }
inline auto& getDataAt(SizeT mI) noexcept { return items[mI]; }
inline const auto& getDataAt(SizeT mI) const noexcept { return items[mI]; }
template<typename T = TBase, typename... TArgs> inline T& create(TArgs&&... mArgs)
{
auto uPtr(recycler.template create<T>(fwd<TArgs>(mArgs)...));
if(capacity <= sizeNext) reserve(capacity * 3);
items.initAt(sizeNext, std::move(uPtr));
return ssvu::castUp<T>(*items[sizeNext++]);
}
inline void clear() noexcept
{
for(auto i(0u); i < sizeNext; ++i) items.deinitAt(i);
msize = sizeNext = 0;
}
inline void del(TBase& mBase) noexcept { LayoutType::setBool(&mBase, false); }
inline void reserve(SizeT mCapacityNew)
{
SSVU_ASSERT(capacity < mCapacityNew);
items.grow(capacity, mCapacityNew);
capacity = mCapacityNew;
}
inline void refresh()
{
// TODO: code review
// TODO: compare to handlevector
const int intSizeNext(sizeNext);
int iD{0}, iA{intSizeNext - 1};
do
{
// Find dead item from left
for(; true; ++iD)
{
// No more dead items
if(iD > iA) goto finishRefresh;
if(isDeadAt(iD)) break;
}
// Find alive item from right
for(; true; --iA)
{
// No more alive items
if(iA <= iD) goto finishRefresh;
if(isAliveAt(iA)) break;
}
SSVU_ASSERT(isDeadAt(iD) && isAliveAt(iA));
std::swap(items[iD], items[iA]);
SSVU_ASSERT(isAliveAt(iD) && isDeadAt(iA));
// Move both iterators
++iD; --iA;
}
while(true);
finishRefresh:
#if SSVU_DEBUG
for(iA = iA - 1; iA >= 0; --iA) SSVU_ASSERT(isAliveAt(iA));
#endif
msize = sizeNext = iD;
for(; iD < intSizeNext; ++iD)
{
SSVU_ASSERT(isDeadAt(iD));
items.deinitAt(iD);
}
}
inline static bool isAlive(const TBase* mBase) noexcept { return LayoutType::getBool(mBase); }
inline static bool isDead(const TBase* mBase) noexcept { return !isAlive(mBase); }
inline auto size() const noexcept { return msize; }
inline auto begin() noexcept { return ItrIdx{0, this}; }
inline auto end() noexcept { return ItrIdx{msize, this}; }
inline auto begin() const noexcept { return ItrIdxC{0, this}; }
inline auto end() const noexcept { return ItrIdxC{msize, this}; }
/*inline auto cbegin() const noexcept { return std::cbegin(items); }
inline auto cend() const noexcept { return std::cend(items); }
inline auto rbegin() noexcept { return std::rbegin(items); }
inline auto rend() noexcept { return std::rend(items); }
inline auto crbegin() const noexcept { return std::crbegin(items); }
inline auto crend() const noexcept { return std::crend(items); }*/
};
}
}
#endif