Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#include <SSVUtils/SSVUtils.hpp>
using Idx = std::size_t;
using Ctr = int;
template<typename> class Manager;
template<typename> class Handle;
template<typename T> class Atom
{
template<typename> friend class Manager;
template<typename> friend class Handle;
private:
Idx ctrlIdx;
bool alive{false};
T impl;
public:
inline Atom(Idx mCtrlIdx) : ctrlIdx{mCtrlIdx} { }
};
class Controller
{
template<typename> friend class Manager;
template<typename> friend class Handle;
private:
Idx idx;
Ctr ctr;
public:
inline Controller(Idx mIdx) noexcept : idx{mIdx} { }
};
template<typename T> class Handle
{
template<typename> friend class Manager;
private:
Manager<T>& manager;
Idx ctrlIdx;
Ctr ctr;
inline Handle(Manager<T>& mManager, Idx mCtrlIdx, Ctr mCtr) noexcept
: manager(mManager), ctrlIdx{mCtrlIdx}, ctr{mCtr} { }
Atom<T>& getAtom();
public:
T& get();
bool isAlive();
void destroy();
};
template<typename T> class Storage
{
template<typename> friend class Manager;
template<typename> friend class Handle;
private:
Atom<T>* atomArray{nullptr};
Controller* controllerArray{nullptr};
std::size_t capacity{0u};
inline ~Storage()
{
deleteArrays();
}
inline void deleteArrays()
{
delete[] atomArray;
delete[] controllerArray;
}
inline void reserve(std::size_t mCapacity)
{
SSVU_ASSERT(mCapacity >= 0);
capacity = mCapacity;
auto newAtomArray(new Atom<T>[capacity]);
auto newControllerArray(new Controller[capacity]);
SSVU_ASSERT(newAtomArray != nullptr);
SSVU_ASSERT(newControllerArray != nullptr);
std::memcpy(newAtomArray, atomArray, sizeof(Atom<T>) * capacity);
std::memcpy(newControllerArray, controllerArray, sizeof(Controller) * capacity);
//std::copy(atomArray, atomArray + capacity, newAtomArray);
//std::copy(controllerArray, controllerArray + capacity, newControllerArray);
deleteArrays();
atomArray = newAtomArray;
controllerArray = newControllerArray;
}
};
template<typename T> class Manager
{
template<typename> friend class Handle;
private:
Storage<T> storage;
Idx lastFree{0u};
inline void checkResize()
{
constexpr std::size_t resizeAmount{10};
// If the last free index is valid, return
auto oldSize(storage.capacity);
if(oldSize > lastFree) return;
// Calculate new size and reserve required memory
auto newSize(oldSize + resizeAmount);
storage.reserve(newSize);
// Initialize reserved memory
while(oldSize++ < newSize)
{
storage.atomArray[oldSize].ctrlIdx = oldSize;
storage.controllerArray[oldSize].idx = oldSize;
}
}
inline void destroy(Idx mCtrlIdx)
{
storage.atomArray[storage.controllerArray[mCtrlIdx].idx].alive = false;
}
public:
inline Manager() { }
template<typename... TArgs> inline Handle<T> createAtom(TArgs&&... mArgs)
{
checkResize();
storage.atomArray[lastFree].impl = T(std::forward<TArgs>(mArgs)...);
storage.atomArray[lastFree].alive = true;
auto cIdx(storage.atomArray[lastFree].ctrlIdx);
storage.controllerArray[cIdx].idx = lastFree;
++(storage.controllerArray[cIdx].ctr);
++lastFree;
return {*this, cIdx, storage.controllerArray[cIdx].ctr};
}
inline void refresh()
{
// C++14: use polymorphic lambda
ssvu::sortStable(storage.atomArray, [](const Atom<T>& mA, const Atom<T>& mB){ return mA.alive > mB.alive; });
auto rIdx(storage.atomArray.size() - 1);
for(; !storage.atomArray[rIdx].alive && rIdx > 0; --rIdx)
{
auto& controller(storage.controllerArray[storage.atomArray[rIdx].ctrlIdx]);
++(controller.ctr);
controller.idx = -1;
}
for(auto fIdx(0u); fIdx <= rIdx; ++fIdx) storage.controllerArray[storage.atomArray[fIdx].ctrlIdx].idx = fIdx;
lastFree = rIdx + 1; // ? check
}
void printState()
{
ssvu::lo("ATOMS") << "";
for(const auto& a : storage.atomArray) std::cout << std::setw(4) << std::left << (int)a.alive << " ";
std::cout << "\n";
ssvu::lo("CTIDX") << "";
for(const auto& a : storage.controllerArray) std::cout << std::setw(4) << std::left << (int)a.idx << " ";
std::cout << "\n";
ssvu::lo("CTCTR") << "";
for(const auto& a : storage.controllerArray) std::cout << std::setw(4) << std::left << (int)a.ctr << " ";
std::cout << "\n\n";
ssvu::lo("ASTRS") << "\n";
std::size_t idx{0u};
for(const auto& a : storage.atomArray) std::cout << idx++ << ": " << a.impl << "\n";
std::cout << std::endl;
}
};
template<typename T> inline Atom<T>& Handle<T>::getAtom()
{
SSVU_ASSERT(isAlive());
return manager.storage.atomArray[manager.controllers[ctrlIdx].idx];
}
template<typename T> inline T& Handle<T>::get()
{
return getAtom().impl;
}
template<typename T> inline bool Handle<T>::isAlive()
{
return manager.storage.controllerArray[ctrlIdx].ctr == ctr;
}
template<typename T> inline void Handle<T>::destroy()
{
return manager.destroy(ctrlIdx);
}
int main()
{
Manager<std::string> test;
test.printState();
auto a0 = test.createAtom();
auto a1 = test.createAtom();
auto a2 = test.createAtom();
auto a3 = test.createAtom();
auto a4 = test.createAtom();
auto a5 = test.createAtom();
auto a6 = test.createAtom();
a0.get() = "hi";
a4.get() = "ciao";
a6.get() = "bye";
test.printState();
a2.destroy();
a3.destroy();
a5.destroy();
//test.atoms[2].alive = false;
//test.atoms[3].alive = false;
//test.atoms[5].alive = false;
test.printState();
test.refresh();
test.printState();
ssvu::lo("RESULT") << a0.get() << std::endl;
ssvu::lo("RESULT") << a4.get() << std::endl;
ssvu::lo("RESULT") << a6.get() << std::endl;
ssvu::lo("alive") << a0.isAlive() << std::endl;
ssvu::lo("alive") << a1.isAlive() << std::endl;
ssvu::lo("alive") << a2.isAlive() << std::endl;
ssvu::lo("alive") << a3.isAlive() << std::endl;
ssvu::lo("alive") << a4.isAlive() << std::endl;
ssvu::lo("alive") << a5.isAlive() << std::endl;
ssvu::lo("alive") << a6.isAlive() << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.