File: pool_allocator.h

package info (click to toggle)
libcds 2.3.3-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,632 kB
  • sloc: cpp: 135,002; ansic: 7,234; perl: 243; sh: 237; makefile: 6
file content (125 lines) | stat: -rw-r--r-- 3,885 bytes parent folder | download | duplicates (3)
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