template <typename T, size_t Capacity>
class LockfreePoolingAllocator
{
public:
template <class U>
struct rebind
{
using other = LockfreePoolingAllocator<U, Capacity>;
};
LockfreePoolingAllocator() = default;
template <typename U>
explicit constexpr LockfreePoolingAllocator(const LockfreePoolingAllocator<U, Capacity>&)
{}
using value_type = T;
T* allocate(size_t) const
{
auto& inst = LockfreeFreeList<sizeof(T), Capacity>::get();
void* p; // NOTE: p doesn't have to be initialized
if (!inst.pop(p)) {
// Acquire memory without calling the constructor of T
p = operator new(sizeof(T));
}
return static_cast<T*>(p);
}
void deallocate(T* p, size_t) const
{
auto& inst = LockfreeFreeList<sizeof(T), Capacity>::get();
if (!inst.bounded_push(p)) {
// Release memory without calling the destructor of T
//(it has already been called at this point)
operator delete(p);
}
}
};