From Jason Turner

[mem.res.pool]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmphjpick1g/{from.md → to.md} +235 -0
tmp/tmphjpick1g/{from.md → to.md} RENAMED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Pool resource classes <a id="mem.res.pool">[[mem.res.pool]]</a>
2
+
3
+ #### Classes `synchronized_pool_resource` and `unsynchronized_pool_resource` <a id="mem.res.pool.overview">[[mem.res.pool.overview]]</a>
4
+
5
+ The `synchronized_pool_resource` and `unsynchronized_pool_resource`
6
+ classes (collectively called *pool resource classes*) are
7
+ general-purpose memory resources having the following qualities:
8
+
9
+ - Each resource frees its allocated memory on destruction, even if
10
+ `deallocate` has not been called for some of the allocated blocks.
11
+ - A pool resource consists of a collection of *pools*, serving requests
12
+ for different block sizes. Each individual pool manages a collection
13
+ of *chunks* that are in turn divided into blocks of uniform size,
14
+ returned via calls to `do_allocate`. Each call to
15
+ `do_allocate(size, alignment)` is dispatched to the pool serving the
16
+ smallest blocks accommodating at least `size` bytes.
17
+ - When a particular pool is exhausted, allocating a block from that pool
18
+ results in the allocation of an additional chunk of memory from the
19
+ *upstream allocator* (supplied at construction), thus replenishing the
20
+ pool. With each successive replenishment, the chunk size obtained
21
+ increases geometrically. \[*Note 1*: By allocating memory in chunks,
22
+ the pooling strategy increases the chance that consecutive allocations
23
+ will be close together in memory. — *end note*]
24
+ - Allocation requests that exceed the largest block size of any pool are
25
+ fulfilled directly from the upstream allocator.
26
+ - A `pool_options` struct may be passed to the pool resource
27
+ constructors to tune the largest block size and the maximum chunk
28
+ size.
29
+
30
+ A `synchronized_pool_resource` may be accessed from multiple threads
31
+ without external synchronization and may have thread-specific pools to
32
+ reduce synchronization costs. An `unsynchronized_pool_resource` class
33
+ may not be accessed from multiple threads simultaneously and thus avoids
34
+ the cost of synchronization entirely in single-threaded applications.
35
+
36
+ ``` cpp
37
+ struct pool_options {
38
+ size_t max_blocks_per_chunk = 0;
39
+ size_t largest_required_pool_block = 0;
40
+ };
41
+
42
+ class synchronized_pool_resource : public memory_resource {
43
+ public:
44
+ synchronized_pool_resource(const pool_options& opts,
45
+ memory_resource* upstream);
46
+
47
+ synchronized_pool_resource()
48
+ : synchronized_pool_resource(pool_options(), get_default_resource()) {}
49
+ explicit synchronized_pool_resource(memory_resource* upstream)
50
+ : synchronized_pool_resource(pool_options(), upstream) {}
51
+ explicit synchronized_pool_resource(const pool_options& opts)
52
+ : synchronized_pool_resource(opts, get_default_resource()) {}
53
+
54
+ synchronized_pool_resource(const synchronized_pool_resource&) = delete;
55
+ virtual ~synchronized_pool_resource();
56
+
57
+ synchronized_pool_resource&
58
+ operator=(const synchronized_pool_resource&) = delete;
59
+
60
+ void release();
61
+ memory_resource* upstream_resource() const;
62
+ pool_options options() const;
63
+
64
+ protected:
65
+ void *do_allocate(size_t bytes, size_t alignment) override;
66
+ void do_deallocate(void *p, size_t bytes, size_t alignment) override;
67
+
68
+ bool do_is_equal(const memory_resource& other) const noexcept override;
69
+ };
70
+
71
+ class unsynchronized_pool_resource : public memory_resource {
72
+ public:
73
+ unsynchronized_pool_resource(const pool_options& opts,
74
+ memory_resource* upstream);
75
+
76
+ unsynchronized_pool_resource()
77
+ : unsynchronized_pool_resource(pool_options(), get_default_resource()) {}
78
+ explicit unsynchronized_pool_resource(memory_resource* upstream)
79
+ : unsynchronized_pool_resource(pool_options(), upstream) {}
80
+ explicit unsynchronized_pool_resource(const pool_options& opts)
81
+ : unsynchronized_pool_resource(opts, get_default_resource()) {}
82
+
83
+ unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete;
84
+ virtual ~unsynchronized_pool_resource();
85
+
86
+ unsynchronized_pool_resource&
87
+ operator=(const unsynchronized_pool_resource&) = delete;
88
+
89
+ void release();
90
+ memory_resource *upstream_resource() const;
91
+ pool_options options() const;
92
+
93
+ protected:
94
+ void* do_allocate(size_t bytes, size_t alignment) override;
95
+ void do_deallocate(void* p, size_t bytes, size_t alignment) override;
96
+
97
+ bool do_is_equal(const memory_resource& other) const noexcept override;
98
+ };
99
+ ```
100
+
101
+ #### `pool_options` data members <a id="mem.res.pool.options">[[mem.res.pool.options]]</a>
102
+
103
+ The members of `pool_options` comprise a set of constructor options for
104
+ pool resources. The effect of each option on the pool resource behavior
105
+ is described below:
106
+
107
+ ``` cpp
108
+ size_t max_blocks_per_chunk;
109
+ ```
110
+
111
+ The maximum number of blocks that will be allocated at once from the
112
+ upstream memory resource ([[mem.res.monotonic.buffer]]) to replenish a
113
+ pool. If the value of `max_blocks_per_chunk` is zero or is greater than
114
+ an *implementation-defined* limit, that limit is used instead. The
115
+ implementation may choose to use a smaller value than is specified in
116
+ this field and may use different values for different pools.
117
+
118
+ ``` cpp
119
+ size_t largest_required_pool_block;
120
+ ```
121
+
122
+ The largest allocation size that is required to be fulfilled using the
123
+ pooling mechanism. Attempts to allocate a single block larger than this
124
+ threshold will be allocated directly from the upstream memory resource.
125
+ If `largest_required_pool_block` is zero or is greater than an
126
+ *implementation-defined* limit, that limit is used instead. The
127
+ implementation may choose a pass-through threshold larger than specified
128
+ in this field.
129
+
130
+ #### Pool resource constructors and destructors <a id="mem.res.pool.ctor">[[mem.res.pool.ctor]]</a>
131
+
132
+ ``` cpp
133
+ synchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
134
+ unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
135
+ ```
136
+
137
+ *Requires:* `upstream` is the address of a valid memory resource.
138
+
139
+ *Effects:* Constructs a pool resource object that will obtain memory
140
+ from `upstream` whenever the pool resource is unable to satisfy a memory
141
+ request from its own internal data structures. The resulting object will
142
+ hold a copy of `upstream`, but will not own the resource to which
143
+ `upstream` points.
144
+
145
+ [*Note 1*: The intention is that calls to `upstream->allocate()` will
146
+ be substantially fewer than calls to `this->allocate()` in most
147
+ cases. — *end note*]
148
+
149
+ The behavior of the pooling mechanism is tuned according to the value of
150
+ the `opts` argument.
151
+
152
+ *Throws:* Nothing unless `upstream->allocate()` throws. It is
153
+ unspecified if, or under what conditions, this constructor calls
154
+ `upstream->allocate()`.
155
+
156
+ ``` cpp
157
+ virtual ~synchronized_pool_resource();
158
+ virtual ~unsynchronized_pool_resource();
159
+ ```
160
+
161
+ *Effects:* Calls `release()`.
162
+
163
+ #### Pool resource members <a id="mem.res.pool.mem">[[mem.res.pool.mem]]</a>
164
+
165
+ ``` cpp
166
+ void release();
167
+ ```
168
+
169
+ *Effects:* Calls `upstream_resource()->deallocate()` as necessary to
170
+ release all allocated memory.
171
+
172
+ [*Note 1*: The memory is released back to `upstream_resource()` even if
173
+ `deallocate` has not been called for some of the allocated
174
+ blocks. — *end note*]
175
+
176
+ ``` cpp
177
+ memory_resource* upstream_resource() const;
178
+ ```
179
+
180
+ *Returns:* The value of the `upstream` argument provided to the
181
+ constructor of this object.
182
+
183
+ ``` cpp
184
+ pool_options options() const;
185
+ ```
186
+
187
+ *Returns:* The options that control the pooling behavior of this
188
+ resource. The values in the returned struct may differ from those
189
+ supplied to the pool resource constructor in that values of zero will be
190
+ replaced with *implementation-defined* defaults, and sizes may be
191
+ rounded to unspecified granularity.
192
+
193
+ ``` cpp
194
+ void* do_allocate(size_t bytes, size_t alignment) override;
195
+ ```
196
+
197
+ *Returns:* A pointer to allocated storage
198
+ ([[basic.stc.dynamic.deallocation]]) with a size of at least `bytes`.
199
+ The size and alignment of the allocated memory shall meet the
200
+ requirements for a class derived from `memory_resource` ([[mem.res]]).
201
+
202
+ *Effects:* If the pool selected for a block of size `bytes` is unable to
203
+ satisfy the memory request from its own internal data structures, it
204
+ will call `upstream_resource()->allocate()` to obtain more memory. If
205
+ `bytes` is larger than that which the largest pool can handle, then
206
+ memory will be allocated using `upstream_resource()->allocate()`.
207
+
208
+ *Throws:* Nothing unless `upstream_resource()->allocate()` throws.
209
+
210
+ ``` cpp
211
+ void do_deallocate(void* p, size_t bytes, size_t alignment) override;
212
+ ```
213
+
214
+ *Effects:* Returns the memory at `p` to the pool. It is unspecified if,
215
+ or under what circumstances, this operation will result in a call to
216
+ `upstream_resource()->deallocate()`.
217
+
218
+ *Throws:* Nothing.
219
+
220
+ ``` cpp
221
+ bool synchronized_pool_resource::do_is_equal(
222
+ const memory_resource& other) const noexcept override;
223
+ ```
224
+
225
+ *Returns:*
226
+ `this == dynamic_cast<const synchronized_pool_resource*>(&other)`.
227
+
228
+ ``` cpp
229
+ bool unsynchronized_pool_resource::do_is_equal(
230
+ const memory_resource& other) const noexcept override;
231
+ ```
232
+
233
+ *Returns:*
234
+ `this == dynamic_cast<const unsynchronized_pool_resource*>(&other)`.
235
+