1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
12 #define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
13 
14 #ifndef BOOST_CONFIG_HPP
15 #  include <boost/config.hpp>
16 #endif
17 
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 #  pragma once
20 #endif
21 
22 #include <boost/container/detail/config_begin.hpp>
23 #include <boost/container/detail/workaround.hpp>
24 
25 #include <boost/intrusive/set.hpp>
26 #include <boost/container/detail/multiallocation_chain.hpp>
27 #include <boost/container/detail/pool_common_alloc.hpp>
28 #include <boost/container/detail/mutex.hpp>
29 #include <boost/container/detail/adaptive_node_pool_impl.hpp>
30 #include <boost/container/detail/multiallocation_chain.hpp>
31 #include <boost/container/detail/type_traits.hpp>
32 
33 #include <cstddef>
34 #include <cmath>
35 #include <cassert>
36 
37 
38 namespace boost {
39 namespace container {
40 namespace dtl {
41 
42 //!Pooled memory allocator using an smart adaptive pool. Includes
43 //!a reference count but the class does not delete itself, this is
44 //!responsibility of user classes. Node size (NodeSize) and the number of
45 //!nodes allocated per block (NodesPerBlock) are known at compile time.
46 template< std::size_t NodeSize
47         , std::size_t NodesPerBlock
48         , std::size_t MaxFreeBlocks
49         , std::size_t OverheadPercent
50         >
51 class private_adaptive_node_pool
52    :  public private_adaptive_node_pool_impl_ct
53             < fake_segment_manager
54             , MaxFreeBlocks
55             , NodeSize
56             , NodesPerBlock
57             , OverheadPercent
58             , unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only
59                | ::boost::container::adaptive_pool_flag::size_ordered
60                | ::boost::container::adaptive_pool_flag::address_ordered
61             >
62 {
63    typedef private_adaptive_node_pool_impl_ct
64             < fake_segment_manager
65             , MaxFreeBlocks
66             , NodeSize
67             , NodesPerBlock
68             , OverheadPercent
69             , unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only
70                | ::boost::container::adaptive_pool_flag::size_ordered
71                | ::boost::container::adaptive_pool_flag::address_ordered
72             > base_t;
73 
74    //Non-copyable
75    private_adaptive_node_pool(const private_adaptive_node_pool &);
76    private_adaptive_node_pool &operator=(const private_adaptive_node_pool &);
77 
78    public:
79    static const std::size_t nodes_per_block = NodesPerBlock;
80 
81    //!Constructor. Never throws
private_adaptive_node_pool()82    private_adaptive_node_pool()
83       : base_t(0)
84    {}
85 };
86 
87 //!Pooled memory allocator using adaptive pool. Includes
88 //!a reference count but the class does not delete itself, this is
89 //!responsibility of user classes. Node size (NodeSize) and the number of
90 //!nodes allocated per block (NodesPerBlock) are known at compile time
91 template< std::size_t NodeSize
92         , std::size_t NodesPerBlock
93         , std::size_t MaxFreeBlocks
94         , std::size_t OverheadPercent
95         >
96 class shared_adaptive_node_pool
97    : public private_adaptive_node_pool
98       <NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
99 {
100  private:
101    typedef private_adaptive_node_pool
102       <NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent> private_node_allocator_t;
103  public:
104    typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain;
105 
106    //!Constructor. Never throws
shared_adaptive_node_pool()107    shared_adaptive_node_pool()
108    : private_node_allocator_t(){}
109 
110    //!Destructor. Deallocates all allocated blocks. Never throws
~shared_adaptive_node_pool()111    ~shared_adaptive_node_pool()
112    {}
113 
114    //!Allocates array of count elements. Can throw std::bad_alloc
allocate_node()115    void *allocate_node()
116    {
117       //-----------------------
118       scoped_lock<default_mutex> guard(mutex_);
119       //-----------------------
120       return private_node_allocator_t::allocate_node();
121    }
122 
123    //!Deallocates an array pointed by ptr. Never throws
deallocate_node(void * ptr)124    void deallocate_node(void *ptr)
125    {
126       //-----------------------
127       scoped_lock<default_mutex> guard(mutex_);
128       //-----------------------
129       private_node_allocator_t::deallocate_node(ptr);
130    }
131 
132    //!Allocates a singly linked list of n nodes ending in null pointer.
133    //!can throw std::bad_alloc
allocate_nodes(const std::size_t n,multiallocation_chain & chain)134    void allocate_nodes(const std::size_t n, multiallocation_chain &chain)
135    {
136       //-----------------------
137       scoped_lock<default_mutex> guard(mutex_);
138       //-----------------------
139       return private_node_allocator_t::allocate_nodes(n, chain);
140    }
141 
deallocate_nodes(multiallocation_chain & chain)142    void deallocate_nodes(multiallocation_chain &chain)
143    {
144       //-----------------------
145       scoped_lock<default_mutex> guard(mutex_);
146       //-----------------------
147       private_node_allocator_t::deallocate_nodes(chain);
148    }
149 
150    //!Deallocates all the free blocks of memory. Never throws
deallocate_free_blocks()151    void deallocate_free_blocks()
152    {
153       //-----------------------
154       scoped_lock<default_mutex> guard(mutex_);
155       //-----------------------
156       private_node_allocator_t::deallocate_free_blocks();
157    }
158 
159    private:
160    default_mutex mutex_;
161 };
162 
163 }  //namespace dtl {
164 }  //namespace container {
165 }  //namespace boost {
166 
167 #include <boost/container/detail/config_end.hpp>
168 
169 #endif   //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
170