Embedded Template Library 1.0
ipool.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2014 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_IPOOL_INCLUDED
32#define ETL_IPOOL_INCLUDED
33
34#include "platform.h"
35#include "error_handler.h"
36#include "exception.h"
37#include "static_assert.h"
38#include "utility.h"
39#include "memory.h"
40#include "placement_new.h"
41
42#define ETL_POOL_CPP03_CODE 0
43
44namespace etl
45{
46 //***************************************************************************
49 //***************************************************************************
51 {
52 public:
53
54 pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
55 : exception(reason_, file_name_, line_number_)
56 {}
57 };
58
59 //***************************************************************************
62 //***************************************************************************
64 {
65 public:
66
67 explicit pool_no_allocation(string_type file_name_, numeric_type line_number_)
68 : pool_exception(ETL_ERROR_TEXT("pool:allocation", ETL_POOL_FILE_ID"A"), file_name_, line_number_)
69 {}
70 };
71
72 //***************************************************************************
75 //***************************************************************************
77 {
78 public:
79
80 pool_object_not_in_pool(string_type file_name_, numeric_type line_number_)
81 : pool_exception(ETL_ERROR_TEXT("pool:not in pool", ETL_POOL_FILE_ID"B"), file_name_, line_number_)
82 {}
83 };
84
85 //***************************************************************************
88 //***************************************************************************
90 {
91 public:
92
93 pool_element_size(string_type file_name_, numeric_type line_number_)
94 : pool_exception(ETL_ERROR_TEXT("pool:element size", ETL_POOL_FILE_ID"C"), file_name_, line_number_)
95 {}
96 };
97
98 //***************************************************************************
100 //***************************************************************************
101 class ipool
102 {
103 public:
104
105 typedef size_t size_type;
106
107 //*************************************************************************
111 //*************************************************************************
112 template <typename T>
114 {
115 if (sizeof(T) > Item_Size)
116 {
117 ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size));
118 }
119
120 return reinterpret_cast<T*>(allocate_item());
121 }
122
123#if ETL_CPP11_NOT_SUPPORTED || ETL_POOL_CPP03_CODE || ETL_USING_STLPORT
124 //*************************************************************************
128 //*************************************************************************
129 template <typename T>
131 {
132 T* p = allocate<T>();
133
134 if (p)
135 {
136 ::new (p) T();
137 }
138
139 return p;
140 }
141
142 //*************************************************************************
146 //*************************************************************************
147 template <typename T, typename T1>
148 T* create(const T1& value1)
149 {
150 T* p = allocate<T>();
151
152 if (p)
153 {
154 ::new (p) T(value1);
155 }
156
157 return p;
158 }
159
160 template <typename T, typename T1, typename T2>
161 T* create(const T1& value1, const T2& value2)
162 {
163 T* p = allocate<T>();
164
165 if (p)
166 {
167 ::new (p) T(value1, value2);
168 }
169
170 return p;
171 }
172
173 template <typename T, typename T1, typename T2, typename T3>
174 T* create(const T1& value1, const T2& value2, const T3& value3)
175 {
176 T* p = allocate<T>();
177
178 if (p)
179 {
180 ::new (p) T(value1, value2, value3);
181 }
182
183 return p;
184 }
185
186 template <typename T, typename T1, typename T2, typename T3, typename T4>
187 T* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
188 {
189 T* p = allocate<T>();
190
191 if (p)
192 {
193 ::new (p) T(value1, value2, value3, value4);
194 }
195
196 return p;
197 }
198#else
199 //*************************************************************************
201 //*************************************************************************
202 template <typename T, typename... Args>
203 T* create(Args&&... args)
204 {
205 T* p = allocate<T>();
206
207 if (p)
208 {
209 ::new (p) T(etl::forward<Args>(args)...);
210 }
211
212 return p;
213 }
214#endif
215
216 //*************************************************************************
220 //*************************************************************************
221 template <typename T>
222 void destroy(const T* const p_object)
223 {
224 if (sizeof(T) > Item_Size)
225 {
226 ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size));
227 }
228
229 p_object->~T();
230 release(p_object);
231 }
232
233 //*************************************************************************
238 //*************************************************************************
239 void release(const void* const p_object)
240 {
241 const uintptr_t p = uintptr_t(p_object);
242 release_item((char*)p);
243 }
244
245 //*************************************************************************
247 //*************************************************************************
249 {
250 items_allocated = 0;
251 items_initialised = 0;
252 p_next = p_buffer;
253 }
254
255 //*************************************************************************
259 //*************************************************************************
260 bool is_in_pool(const void* const p_object) const
261 {
262 const uintptr_t p = uintptr_t(p_object);
263 return is_item_in_pool((const char*)p);
264 }
265
266 //*************************************************************************
268 //*************************************************************************
269 size_t max_size() const
270 {
271 return Max_Size;
272 }
273
274 //*************************************************************************
276 //*************************************************************************
277 size_t capacity() const
278 {
279 return Max_Size;
280 }
281
282 //*************************************************************************
284 //*************************************************************************
285 size_t available() const
286 {
287 return Max_Size - items_allocated;
288 }
289
290 //*************************************************************************
292 //*************************************************************************
293 size_t size() const
294 {
295 return items_allocated;
296 }
297
298 //*************************************************************************
301 //*************************************************************************
302 bool empty() const
303 {
304 return items_allocated == 0;
305 }
306
307 //*************************************************************************
310 //*************************************************************************
311 bool full() const
312 {
313 return items_allocated == Max_Size;
314 }
315
316 protected:
317
318 //*************************************************************************
320 //*************************************************************************
321 ipool(char* p_buffer_, uint32_t item_size_, uint32_t max_size_)
322 : p_buffer(p_buffer_),
323 p_next(p_buffer_),
324 items_allocated(0),
325 items_initialised(0),
326 Item_Size(item_size_),
327 Max_Size(max_size_)
328 {
329 }
330
331 private:
332
333 //*************************************************************************
335 //*************************************************************************
336 char* allocate_item()
337 {
338 char* p_value = ETL_NULLPTR;
339
340 // Any free space left?
341 if (items_allocated < Max_Size)
342 {
343 // Initialise another one if necessary.
344 if (items_initialised < Max_Size)
345 {
346 char* p = p_buffer + (items_initialised * Item_Size);
347 char* np = p + Item_Size;
348 *reinterpret_cast<char**>(p) = np;
349 ++items_initialised;
350 }
351
352 // Get the address of new allocated item.
353 p_value = p_next;
354
355 ++items_allocated;
356 if (items_allocated < Max_Size)
357 {
358 // Set up the pointer to the next free item
359 p_next = *reinterpret_cast<char**>(p_next);
360 }
361 else
362 {
363 // No more left!
364 p_next = ETL_NULLPTR;
365 }
366 }
367 else
368 {
369 ETL_ASSERT(false, ETL_ERROR(pool_no_allocation));
370 }
371
372 return p_value;
373 }
374
375 //*************************************************************************
377 //*************************************************************************
378 void release_item(char* p_value)
379 {
380 // Does it belong to us?
381 ETL_ASSERT(is_item_in_pool(p_value), ETL_ERROR(pool_object_not_in_pool));
382
383 if (p_next != ETL_NULLPTR)
384 {
385 // Point it to the current free item.
386 *(uintptr_t*)p_value = reinterpret_cast<uintptr_t>(p_next);
387 }
388 else
389 {
390 // This is the only free item.
391 *((uintptr_t*)p_value) = 0;
392 }
393
394 p_next = p_value;
395
396 --items_allocated;
397 }
398
399 //*************************************************************************
401 //*************************************************************************
402 bool is_item_in_pool(const char* p) const
403 {
404 // Within the range of the buffer?
405 intptr_t distance = p - p_buffer;
406 bool is_within_range = (distance >= 0) && (distance <= intptr_t((Item_Size * Max_Size) - Item_Size));
407
408 // Modulus and division can be slow on some architectures, so only do this in debug.
409#if ETL_IS_DEBUG_BUILD
410 // Is the address on a valid object boundary?
411 bool is_valid_address = ((distance % Item_Size) == 0);
412#else
413 bool is_valid_address = true;
414#endif
415
416 return is_within_range && is_valid_address;
417 }
418
419 // Disable copy construction and assignment.
420 ipool(const ipool&);
421 ipool& operator =(const ipool&);
422
423 char* p_buffer;
424 char* p_next;
425
426 uint32_t items_allocated;
427 uint32_t items_initialised;
428
429 const uint32_t Item_Size;
430 const uint32_t Max_Size;
431
432 //*************************************************************************
434 //*************************************************************************
435#if defined(ETL_POLYMORPHIC_POOL) || defined(ETL_POLYMORPHIC_CONTAINERS)
436 public:
437 virtual ~ipool()
438 {
439 }
440#else
441 protected:
443 {
444 }
445#endif
446 };
447}
448
449#endif
450
#define ETL_ASSERT(b, e)
Definition: error_handler.h:316
ETL_CONSTEXPR exception(string_type reason_, string_type, numeric_type line_)
Constructor.
Definition: exception.h:69
Definition: exception.h:47
size_t size() const
Returns the number of allocated items in the pool.
Definition: ipool.h:293
~ipool()
Destructor.
Definition: ipool.h:442
bool empty() const
Definition: ipool.h:302
void release_all()
Release all objects in the pool.
Definition: ipool.h:248
bool full() const
Definition: ipool.h:311
size_t max_size() const
Returns the maximum number of items in the pool.
Definition: ipool.h:269
T * allocate()
Definition: ipool.h:113
void release(const void *const p_object)
Definition: ipool.h:239
size_t capacity() const
Returns the maximum number of items in the pool.
Definition: ipool.h:277
ipool(char *p_buffer_, uint32_t item_size_, uint32_t max_size_)
Constructor.
Definition: ipool.h:321
bool is_in_pool(const void *const p_object) const
Definition: ipool.h:260
size_t available() const
Returns the number of free items in the pool.
Definition: ipool.h:285
T * create()
Definition: ipool.h:130
void destroy(const T *const p_object)
Definition: ipool.h:222
T * create(const T1 &value1)
Definition: ipool.h:148
Definition: ipool.h:102
Definition: ipool.h:90
Definition: ipool.h:51
Definition: ipool.h:64
Definition: ipool.h:77
bitset_ext
Definition: absolute.h:38