117 lines
3.2 KiB
C++
117 lines
3.2 KiB
C++
#pragma once
|
|
|
|
#include <set>
|
|
#include <utility>
|
|
#include <type_traits>
|
|
#include <functional>
|
|
#include <cassert>
|
|
|
|
namespace dhandy {
|
|
namespace implem {
|
|
} //namespace implem
|
|
|
|
template <typename Name, typename Res>
|
|
class ResourcePoolBase {
|
|
struct Wrapper;
|
|
struct WrapperCompare {
|
|
typedef std::true_type is_transparent;
|
|
bool operator() (const Wrapper& a, const Name& b) const;
|
|
bool operator() (const Name& a, const Wrapper& b) const;
|
|
bool operator() (const Wrapper& a, const Wrapper& b) const;
|
|
};
|
|
typedef std::set<Wrapper, WrapperCompare> StorageContainer;
|
|
public:
|
|
virtual ~ResourcePoolBase() = default;
|
|
|
|
class Item {
|
|
friend class ResourcePoolBase;
|
|
Item (typename StorageContainer::iterator it) : m_it(it) {}
|
|
typename StorageContainer::iterator m_it;
|
|
public:
|
|
Res& operator*();
|
|
typename std::add_const<Res>::type& operator*() const;
|
|
Res* operator->();
|
|
typename std::add_const<Res>::type* operator->() const;
|
|
};
|
|
|
|
Item make (const Name& res_name);
|
|
std::size_t size() const { return m_storage.size(); }
|
|
|
|
private:
|
|
struct Wrapper {
|
|
Wrapper (Res&& res, const Name& nm) :
|
|
payload(std::move(res)), name(nm)
|
|
{}
|
|
|
|
mutable Res payload;
|
|
Name name;
|
|
};
|
|
|
|
virtual Res on_res_requested (const Name& name) = 0;
|
|
|
|
StorageContainer m_storage;
|
|
};
|
|
|
|
template <typename Name, typename Res>
|
|
class ResourcePool : private ResourcePoolBase<Name, Res> {
|
|
typedef std::function<Res(const Name&)> MakerFunc;
|
|
public:
|
|
explicit ResourcePool (MakerFunc maker) : m_make_res(maker) {}
|
|
using ResourcePoolBase<Name, Res>::make;
|
|
using ResourcePoolBase<Name, Res>::Item;
|
|
using ResourcePoolBase<Name, Res>::size;
|
|
|
|
private:
|
|
virtual Res on_res_requested (const Name& n) { return m_make_res(n); }
|
|
|
|
MakerFunc m_make_res;
|
|
};
|
|
|
|
template <typename Name, typename Res>
|
|
inline Res& ResourcePoolBase<Name, Res>::Item::operator*() {
|
|
return m_it->payload;
|
|
}
|
|
|
|
template <typename Name, typename Res>
|
|
inline typename std::add_const<Res>::type& ResourcePoolBase<Name, Res>::Item::operator*() const {
|
|
return m_it->payload;
|
|
}
|
|
|
|
template <typename Name, typename Res>
|
|
inline bool ResourcePoolBase<Name, Res>::WrapperCompare::operator() (const Wrapper& a, const Name& b) const {
|
|
return a.name < b;
|
|
}
|
|
|
|
template <typename Name, typename Res>
|
|
inline bool ResourcePoolBase<Name, Res>::WrapperCompare::operator() (const Name& a, const Wrapper& b) const {
|
|
return a < b.name;
|
|
}
|
|
|
|
template <typename Name, typename Res>
|
|
inline bool ResourcePoolBase<Name, Res>::WrapperCompare::operator() (const Wrapper& a, const Wrapper& b) const {
|
|
return a.name < b.name;
|
|
}
|
|
|
|
template <typename Name, typename Res>
|
|
Res* ResourcePoolBase<Name, Res>::Item::operator->() {
|
|
return &m_it->payload;
|
|
}
|
|
|
|
template <typename Name, typename Res>
|
|
typename std::add_const<Res>::type* ResourcePoolBase<Name, Res>::Item::operator->() const {
|
|
return &m_it->payload;
|
|
}
|
|
|
|
template <typename Name, typename Res>
|
|
auto ResourcePoolBase<Name, Res>::make (const Name& name) -> Item {
|
|
auto it_found = m_storage.find(name);
|
|
if (m_storage.end() != it_found) {
|
|
return Item(it_found);
|
|
}
|
|
else {
|
|
auto insertion_pair = m_storage.insert(Wrapper(this->on_res_requested(name), name));
|
|
assert(insertion_pair.second);
|
|
return Item(insertion_pair.first);
|
|
}
|
|
}
|
|
} //namespace dhandy
|