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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
// Copyright (c) 2006-2018 Maxim Khizhinsky
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef CDSLIB_MEMORY_POOL_ALLOCATOR_H
#define CDSLIB_MEMORY_POOL_ALLOCATOR_H
#include <cds/details/defs.h>
#include <utility>
namespace cds { namespace memory {
///@defgroup cds_memory_pool Simple memory pool
/// Pool allocator adapter
/**
This class is an adapter for an object pool. It gives \p std::allocator interface
for the @ref cds_memory_pool "pool".
Template arguments:
- \p T - value type
- \p Accessor - a functor to access to the pool object. The pool has the following interface:
\code
template <typename T>
class pool {
typedef T value_type ; // Object type maintained by pool
T * allocate( size_t n ) ; // Allocate an array of object of type T
void deallocate( T * p, size_t n ) ; // Deallocate the array p of size n
};
\endcode
<b>Usage</b>
Suppose, we have a pool with interface above. Usually, the pool is a static object:
\code
static pool<Foo> thePool;
\endcode
The \p %pool_allocator gives \p std::allocator interface for the pool.
It is needed to declare an <i>accessor</i> functor to access to \p thePool:
\code
struct pool_accessor {
typedef typename pool::value_type value_type;
pool& operator()() const
{
return thePool;
}
};
\endcode
Now, <tt>cds::memory::pool_allocator< T, pool_accessor > </tt> can be used instead of \p std::allocator.
*/
template <typename T, typename Accessor>
class pool_allocator
{
//@cond
public:
typedef Accessor accessor_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U> struct rebind {
typedef pool_allocator<U, accessor_type> other;
};
public:
pool_allocator() noexcept
{}
pool_allocator(const pool_allocator&) noexcept
{}
template <class U> pool_allocator(const pool_allocator<U, accessor_type>&) noexcept
{}
~pool_allocator()
{}
pointer address(reference x) const noexcept
{
return &x;
}
const_pointer address(const_reference x) const noexcept
{
return &x;
}
pointer allocate( size_type n, void const * /*hint*/ = 0)
{
static_assert( sizeof(value_type) <= sizeof(typename accessor_type::value_type), "Incompatible type" );
return reinterpret_cast<pointer>( accessor_type()().allocate( n ));
}
void deallocate(pointer p, size_type n) noexcept
{
accessor_type()().deallocate( reinterpret_cast<typename accessor_type::value_type *>( p ), n );
}
size_type max_size() const noexcept
{
return size_t(-1) / sizeof(value_type);
}
template <class U, class... Args>
void construct(U* p, Args&&... args)
{
new((void *)p) U( std::forward<Args>(args)...);
}
template <class U>
void destroy(U* p)
{
p->~U();
}
//@endcond
};
}} // namespace cds::memory
#endif // #ifndef CDSLIB_MEMORY_POOL_ALLOCATOR_H
|