]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // (C) Copyright Ion Gaztanaga 2015-2015. 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_POOL_RESOURCE_HPP | |
12 | #define BOOST_CONTAINER_POOL_RESOURCE_HPP | |
13 | ||
14 | #if defined (_MSC_VER) | |
15 | # pragma once | |
16 | #endif | |
17 | ||
18 | #include <boost/container/detail/config_begin.hpp> | |
19 | #include <boost/container/detail/workaround.hpp> | |
20 | #include <boost/container/pmr/memory_resource.hpp> | |
21 | #include <boost/container/detail/block_list.hpp> | |
22 | #include <boost/container/pmr/pool_options.hpp> | |
23 | ||
24 | #include <cstddef> | |
25 | ||
26 | namespace boost { | |
27 | namespace container { | |
28 | namespace pmr { | |
29 | ||
30 | #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) | |
31 | ||
32 | class pool_data_t; | |
33 | ||
34 | static const std::size_t pool_options_minimum_max_blocks_per_chunk = 1u; | |
35 | static const std::size_t pool_options_default_max_blocks_per_chunk = 32u; | |
36 | static const std::size_t pool_options_minimum_largest_required_pool_block = | |
37 | memory_resource::max_align > 2*sizeof(void*) ? memory_resource::max_align : 2*sizeof(void*); | |
38 | static const std::size_t pool_options_default_largest_required_pool_block = | |
39 | pool_options_minimum_largest_required_pool_block > 4096u | |
40 | ? pool_options_minimum_largest_required_pool_block : 4096u; | |
41 | ||
42 | #endif //BOOST_CONTAINER_DOXYGEN_INVOKED | |
43 | ||
44 | class pool_resource | |
45 | { | |
46 | typedef block_list_base<> block_list_base_t; | |
47 | ||
48 | pool_options m_options; | |
49 | memory_resource& m_upstream; | |
50 | block_list_base_t m_oversized_list; | |
51 | pool_data_t *m_pool_data; | |
52 | std::size_t m_pool_count; | |
53 | ||
54 | static void priv_limit_option(std::size_t &val, std::size_t min, std::size_t max); | |
55 | static std::size_t priv_pool_index(std::size_t block_size); | |
56 | static std::size_t priv_pool_block(std::size_t index); | |
57 | ||
58 | void priv_fix_options(); | |
59 | void priv_init_pools(); | |
60 | void priv_constructor_body(); | |
61 | ||
62 | public: | |
63 | ||
64 | //! <b>Requires</b>: `upstream` is the address of a valid memory resource. | |
65 | //! | |
66 | //! <b>Effects</b>: Constructs a pool resource object that will obtain memory | |
67 | //! from upstream whenever the pool resource is unable to satisfy a memory | |
68 | //! request from its own internal data structures. The resulting object will hold | |
69 | //! a copy of upstream, but will not own the resource to which upstream points. | |
70 | //! [ Note: The intention is that calls to upstream->allocate() will be | |
71 | //! substantially fewer than calls to this->allocate() in most cases. - end note | |
72 | //! The behavior of the pooling mechanism is tuned according to the value of | |
73 | //! the opts argument. | |
74 | //! | |
75 | //! <b>Throws</b>: Nothing unless upstream->allocate() throws. It is unspecified if | |
76 | //! or under what conditions this constructor calls upstream->allocate(). | |
77 | pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT; | |
78 | ||
79 | //! <b>Effects</b>: Same as | |
80 | //! `pool_resource(pool_options(), get_default_resource())`. | |
81 | pool_resource() BOOST_NOEXCEPT; | |
82 | ||
83 | //! <b>Effects</b>: Same as | |
84 | //! `pool_resource(pool_options(), upstream)`. | |
85 | explicit pool_resource(memory_resource* upstream) BOOST_NOEXCEPT; | |
86 | ||
87 | //! <b>Effects</b>: Same as | |
88 | //! `pool_resource(opts, get_default_resource())`. | |
89 | explicit pool_resource(const pool_options& opts) BOOST_NOEXCEPT; | |
90 | ||
91 | #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) | |
92 | pool_resource(const pool_resource&) = delete; | |
93 | pool_resource operator=(const pool_resource&) = delete; | |
94 | #else | |
95 | private: | |
96 | pool_resource (const pool_resource&); | |
97 | pool_resource operator=(const pool_resource&); | |
98 | public: | |
99 | #endif | |
100 | ||
101 | //! <b>Effects</b>: Calls | |
102 | //! `this->release()`. | |
103 | virtual ~pool_resource(); | |
104 | ||
105 | //! <b>Effects</b>: Calls Calls `upstream_resource()->deallocate()` as necessary | |
106 | //! to release all allocated memory. [ Note: memory is released back to | |
107 | //! `upstream_resource()` even if deallocate has not been called for some | |
108 | //! of the allocated blocks. - end note ] | |
109 | void release(); | |
110 | ||
111 | //! <b>Returns</b>: The value of the upstream argument provided to the | |
112 | //! constructor of this object. | |
113 | memory_resource* upstream_resource() const; | |
114 | ||
115 | //! <b>Returns</b>: The options that control the pooling behavior of this resource. | |
116 | //! The values in the returned struct may differ from those supplied to the pool | |
117 | //! resource constructor in that values of zero will be replaced with | |
118 | //! implementation-defined defaults and sizes may be rounded to unspecified granularity. | |
119 | pool_options options() const; | |
120 | ||
121 | public: //public so that [un]synchronized_pool_resource can use them | |
122 | ||
123 | //! <b>Returns</b>: A pointer to allocated storage with a size of at least `bytes`. | |
124 | //! The size and alignment of the allocated memory shall meet the requirements for | |
125 | //! a class derived from `memory_resource`. | |
126 | //! | |
127 | //! <b>Effects</b>: If the pool selected for a block of size bytes is unable to | |
128 | //! satisfy the memory request from its own internal data structures, it will call | |
129 | //! `upstream_resource()->allocate()` to obtain more memory. If `bytes` is larger | |
130 | //! than that which the largest pool can handle, then memory will be allocated | |
131 | //! using `upstream_resource()->allocate()`. | |
132 | //! | |
133 | //! <b>Throws</b>: Nothing unless `upstream_resource()->allocate()` throws. | |
134 | virtual void* do_allocate(std::size_t bytes, std::size_t alignment); | |
135 | ||
136 | //! <b>Effects</b>: Return the memory at p to the pool. It is unspecified if or under | |
137 | //! what circumstances this operation will result in a call to | |
138 | //! `upstream_resource()->deallocate()`. | |
139 | //! | |
140 | //! <b>Throws</b>: Nothing. | |
141 | virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment); | |
142 | ||
143 | //! <b>Returns</b>: | |
144 | //! `this == dynamic_cast<const pool_resource*>(&other)`. | |
145 | virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT; | |
146 | ||
147 | //Non-standard observers | |
148 | public: | |
149 | //! <b>Returns</b>: The number of pools that will be used in the pool resource. | |
150 | //! | |
151 | //! <b>Note</b>: Non-standard extension. | |
152 | std::size_t pool_count() const; | |
153 | ||
154 | //! <b>Returns</b>: The index of the pool that will be used to serve the allocation of `bytes`. | |
155 | //! from the pool specified by `pool_index`. Returns `pool_count()` if `bytes` is bigger | |
156 | //! than `options().largest_required_pool_block` (no pool will be used to serve this). | |
157 | //! | |
158 | //! <b>Note</b>: Non-standard extension. | |
159 | std::size_t pool_index(std::size_t bytes) const; | |
160 | ||
161 | //! <b>Requires</b>: `pool_idx < pool_index()` | |
162 | //! | |
163 | //! <b>Returns</b>: The number blocks that will be allocated in the next chunk | |
164 | //! from the pool specified by `pool_idx`. | |
165 | //! | |
166 | //! <b>Note</b>: Non-standard extension. | |
167 | std::size_t pool_next_blocks_per_chunk(std::size_t pool_idx) const; | |
168 | ||
169 | //! <b>Requires</b>: `pool_idx < pool_index()` | |
170 | //! | |
171 | //! <b>Returns</b>: The number of bytes of the block that the specified `pool_idx` pool manages. | |
172 | //! | |
173 | //! <b>Note</b>: Non-standard extension. | |
174 | std::size_t pool_block(std::size_t pool_idx) const; | |
175 | ||
176 | //! <b>Requires</b>: `pool_idx < pool_index()` | |
177 | //! | |
178 | //! <b>Returns</b>: The number of blocks that the specified `pool_idx` pool has cached | |
179 | //! and will be served without calling the upstream_allocator. | |
180 | //! | |
181 | //! <b>Note</b>: Non-standard extension. | |
182 | std::size_t pool_cached_blocks(std::size_t pool_idx) const; | |
183 | }; | |
184 | ||
185 | } //namespace pmr { | |
186 | } //namespace container { | |
187 | } //namespace boost { | |
188 | ||
189 | #include <boost/container/detail/config_end.hpp> | |
190 | ||
191 | #endif //BOOST_CONTAINER_POOL_RESOURCE_HPP |