Last active
April 11, 2018 11:58
-
-
Save Delaunay/8695f1e965ab3fc76c9d82a9eda555d8 to your computer and use it in GitHub Desktop.
Simple Pool Implementation (gcc 8, C++2a)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <thread> | |
#include <mutex> | |
#include <tuple> | |
#include <list> | |
#include <memory> | |
namespace pool{ | |
namespace internal { | |
template<typename T> | |
struct PoolObjectWrapper{ | |
/*PoolObjectWrapper(bool f, T& obj): | |
free(f), object(obj) | |
{}*/ | |
bool free = false; | |
T object; | |
}; | |
template<typename T> | |
struct Deleter | |
{ | |
Deleter() {} | |
static void deleter(internal::PoolObjectWrapper<T>* t) { | |
t->free = true; | |
} | |
void operator () (internal::PoolObjectWrapper<T>* t) { | |
deleter(t); | |
} | |
}; | |
} | |
template<typename T> | |
struct PooledObjectTrait{ | |
static T make(){ return T(); } | |
}; | |
template<typename T, typename PtrType> | |
class PooledObject{ | |
public: | |
PooledObject(internal::PoolObjectWrapper<T>* object): | |
_ptr(object) | |
{} | |
PooledObject(internal::PoolObjectWrapper<T>* object, void(*deleter)(internal::PoolObjectWrapper<T>*)): | |
_ptr(object, deleter) | |
{} | |
inline T& operator* () { return (*_ptr).object; } | |
inline T* operator->() { return _ptr->object; } | |
inline operator bool() const { return _ptr; } | |
private: | |
PtrType _ptr; | |
}; | |
template<typename T> | |
using UniquePooledObject = PooledObject<T, std::unique_ptr<internal::PoolObjectWrapper<T>, internal::Deleter<T>>>; | |
template<typename T> | |
using SharedPooledObject = PooledObject<T, std::shared_ptr<internal::PoolObjectWrapper<T>>>; | |
template<typename T> | |
class DynamicPool{ | |
public: | |
DynamicPool(std::size_t initial_size){ | |
//_pool.reserve(initial_size); | |
for(std::size_t i = 0; i < initial_size; ++i){ | |
_pool.push_back({true, PooledObjectTrait<T>::make()}); | |
} | |
} | |
UniquePooledObject<T> get_unique(){ | |
return UniquePooledObject<T>(get_free_or_make()); | |
} | |
SharedPooledObject<T> get_shared(){ | |
void(*deleter)(internal::PoolObjectWrapper<T>*) = &internal::Deleter<T>::deleter; | |
return SharedPooledObject<T>(get_free_or_make(), deleter); | |
} | |
std::size_t size() const { return _pool.size(); } | |
private: | |
internal::PoolObjectWrapper<T>* get_free_or_make(){ | |
std::lock_guard<std::mutex> lock(_mutex); | |
for(auto& elem: _pool){ | |
if (elem.free){ | |
elem.free = false; | |
return &elem; | |
} | |
} | |
_pool.push_back({false, PooledObjectTrait<T>::make()}); | |
return &_pool.back(); | |
} | |
private: | |
std::list<internal::PoolObjectWrapper<T>> _pool; | |
std::mutex _mutex; | |
}; | |
} | |
#include <iostream> | |
int main(){ | |
pool::DynamicPool<int> pool(20); | |
{ | |
auto a = pool.get_unique(); | |
auto b = pool.get_shared(); | |
(*a) = 10; | |
(*b) = 20; | |
} | |
{ | |
auto a = pool.get_unique(); | |
auto b = pool.get_shared(); | |
std::cout << (*a) << std::endl; | |
std::cout << (*b) << std::endl; | |
} | |
auto a = pool.get_shared(); | |
std::cout << (*a) << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment