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
|
#ifndef OPENMW_COMPONENTS_MISC_OBJECTPOOL_H
#define OPENMW_COMPONENTS_MISC_OBJECTPOOL_H
#include <deque>
#include <memory>
#include <vector>
namespace Misc
{
template <class T>
class ObjectPool;
template <class T>
class ObjectPtrDeleter
{
public:
ObjectPtrDeleter(std::nullptr_t)
: mPool(nullptr)
{
}
ObjectPtrDeleter(ObjectPool<T>& pool)
: mPool(&pool)
{
}
void operator()(T* object) const { mPool->recycle(object); }
private:
ObjectPool<T>* mPool;
};
template <class T>
struct ObjectPtr final : std::unique_ptr<T, ObjectPtrDeleter<T>>
{
using std::unique_ptr<T, ObjectPtrDeleter<T>>::unique_ptr;
using std::unique_ptr<T, ObjectPtrDeleter<T>>::operator=;
ObjectPtr()
: ObjectPtr(nullptr)
{
}
ObjectPtr(std::nullptr_t)
: std::unique_ptr<T, ObjectPtrDeleter<T>>(nullptr, nullptr)
{
}
};
template <class T>
class ObjectPool
{
friend class ObjectPtrDeleter<T>;
public:
ObjectPool()
: mObjects(std::make_unique<std::deque<T>>())
{
}
ObjectPtr<T> get()
{
T* object;
if (!mUnused.empty())
{
object = mUnused.back();
mUnused.pop_back();
}
else
{
mObjects->emplace_back();
object = &mObjects->back();
}
return ObjectPtr<T>(object, ObjectPtrDeleter<T>(*this));
}
private:
std::unique_ptr<std::deque<T>> mObjects;
std::vector<T*> mUnused;
void recycle(T* object) { mUnused.push_back(object); }
};
}
#endif
|