Embedded Template Library 1.0
Loading...
Searching...
No Matches
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 "iterator.h"
38#include "memory.h"
39#include "placement_new.h"
40#include "utility.h"
41
42#include <stddef.h>
43
44#define ETL_POOL_CPP03_CODE 0
45
46namespace etl
47{
48 //***************************************************************************
51 //***************************************************************************
52 class pool_exception : public exception
53 {
54 public:
55
56 pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
57 : exception(reason_, file_name_, line_number_)
58 {
59 }
60 };
61
62 //***************************************************************************
65 //***************************************************************************
66 class pool_no_allocation : public pool_exception
67 {
68 public:
69
70 explicit pool_no_allocation(string_type file_name_, numeric_type line_number_)
71 : pool_exception(ETL_ERROR_TEXT("pool:allocation", ETL_POOL_FILE_ID"A"), file_name_, line_number_)
72 {
73 }
74 };
75
76 //***************************************************************************
80 //***************************************************************************
81 class pool_object_not_in_pool : public pool_exception
82 {
83 public:
84
85 pool_object_not_in_pool(string_type file_name_, numeric_type line_number_)
86 : pool_exception(ETL_ERROR_TEXT("pool:not in pool", ETL_POOL_FILE_ID"B"), file_name_, line_number_)
87 {
88 }
89 };
90
91 //***************************************************************************
95 //***************************************************************************
96 class pool_element_size : public pool_exception
97 {
98 public:
99
100 pool_element_size(string_type file_name_, numeric_type line_number_)
101 : pool_exception(ETL_ERROR_TEXT("pool:element size", ETL_POOL_FILE_ID"C"), file_name_, line_number_)
102 {
103 }
104 };
105
106 //***************************************************************************
108 //***************************************************************************
109 class ipool
110 {
111 public:
112
113 typedef size_t size_type;
114
115 private:
116
117 //***************************************************************************
119 //***************************************************************************
120
121 const char* buffer_end() const
122 {
123 return p_buffer + Item_Size * items_initialised;
124 }
125
126 //***************************************************************************
131 //***************************************************************************
132 bool is_pointing_into_pool_or_end_or_nullptr(const char* address) const
133 {
134 return address == ETL_NULLPTR || (p_buffer <= address && address <= buffer_end());
135 }
136
137 //***************************************************************************
139 //***************************************************************************
140 bool is_in_free_list(const char* address) const
141 {
142 const char* i = p_next;
143 while (i != ETL_NULLPTR)
144 {
145 if (address == i)
146 {
147 return true;
148 }
149 i = *reinterpret_cast<const char* const*>(i);
150 }
151 return false;
152 }
153
154 public:
155
156 //***************************************************************************
157 template <bool is_const>
158 class ipool_iterator
159 {
160 public:
161
162 friend class ipool;
163
164 typedef typename etl::conditional<is_const, const char*, char*>::type value_type;
165 typedef typename etl::conditional<is_const, const char*&, char*&>::type reference;
166 typedef typename etl::conditional<is_const, const char**, char**>::type pointer;
167 typedef ptrdiff_t difference_type;
168 typedef ETL_OR_STD::forward_iterator_tag iterator_category;
169 typedef typename etl::conditional<is_const, const void*, void*>::type void_type;
170 typedef typename etl::conditional<is_const, const ipool, ipool>::type pool_type;
171 typedef typename etl::conditional<is_const, const char* const*, char**>::type pointer_type;
172
173 //***************************************************************************
174 ipool_iterator(const ipool_iterator& other)
175 : p_current(other.p_current)
176 , p_pool(other.p_pool)
177 {
178 find_allocated();
179 }
180
181 //***************************************************************************
182 ipool_iterator& operator++()
183 {
184 p_current = p_current + p_pool->Item_Size;
185 find_allocated();
186 return *this;
187 }
188
189 //***************************************************************************
190 ipool_iterator operator++(int)
191 {
192 ipool_iterator temp(*this);
193 p_current = p_current + p_pool->Item_Size;
194 find_allocated();
195 return temp;
196 }
197
198 //***************************************************************************
199 ipool_iterator& operator=(const ipool_iterator& other)
200 {
201 p_current = other.p_current;
202 p_pool = other.p_pool;
203 return *this;
204 }
205
206 //***************************************************************************
207 void_type operator*() const
208 {
209 return p_current;
210 }
211
212 //***************************************************************************
213 template <typename T>
214 T& get() const
215 {
216 return *reinterpret_cast<T*>(p_current);
217 }
218
219 //***************************************************************************
220 friend bool operator==(const ipool_iterator& lhs, const ipool_iterator& rhs)
221 {
222 return lhs.p_current == rhs.p_current;
223 }
224
225 //***************************************************************************
226 friend bool operator!=(const ipool_iterator& lhs, const ipool_iterator& rhs)
227 {
228 return !(lhs == rhs);
229 }
230
231 private:
232
233 //***************************************************************************
236 //***************************************************************************
237 void find_allocated()
238 {
239 while (p_current < p_pool->buffer_end())
240 {
241 value_type value = *reinterpret_cast<pointer_type>(p_current);
242 if (!p_pool->is_pointing_into_pool_or_end_or_nullptr(value))
243 {
244 return;
245 }
246 if (!p_pool->is_in_free_list(p_current))
247 {
248 return;
249 }
250 p_current += p_pool->Item_Size;
251 }
252 }
253
254 //***************************************************************************
256 //***************************************************************************
257 ipool_iterator(value_type p, pool_type* pool_)
258 : p_current(p)
259 , p_pool(pool_)
260 {
261 find_allocated();
262 }
263
264 value_type p_current;
265 pool_type* p_pool;
266 };
267
268 template <bool is_const>
269 friend class ipool_iterator;
270
271 typedef ipool_iterator<false> iterator;
272
273 //***************************************************************************
274 class const_iterator : public ipool_iterator<true>
275 {
276 public:
277
278 const_iterator(const ipool_iterator& other)
279 : ipool_iterator(other)
280 {
281 }
282 const_iterator(const ipool_iterator<false>& other)
283 : ipool_iterator(other.p_current, other.p_pool)
284 {
285 }
286 const_iterator(value_type p, pool_type* pool_)
287 : ipool_iterator<true>(p, pool_)
288 {
289 }
290 };
291
292 //***************************************************************************
293 iterator begin()
294 {
295 return iterator(p_buffer, this);
296 }
297
298 //***************************************************************************
299 iterator end()
300 {
301 return iterator(p_buffer + Item_Size * items_initialised, this);
302 }
303
304 //***************************************************************************
305 const_iterator begin() const
306 {
307 return const_iterator(p_buffer, this);
308 }
309
310 //***************************************************************************
311 const_iterator end() const
312 {
313 return const_iterator(p_buffer + Item_Size * items_initialised, this);
314 }
315
316 //***************************************************************************
317 const_iterator cbegin() const
318 {
319 return const_iterator(p_buffer, this);
320 }
321
322 //***************************************************************************
323 const_iterator cend() const
324 {
325 return const_iterator(p_buffer + Item_Size * items_initialised, this);
326 }
327
328 //*************************************************************************
332 //*************************************************************************
333 template <typename T>
335 {
336 if (sizeof(T) > Item_Size)
337 {
338 ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size));
339 }
340
341 return reinterpret_cast<T*>(allocate_item());
342 }
343
344#if ETL_CPP11_NOT_SUPPORTED || ETL_POOL_CPP03_CODE || ETL_USING_STLPORT
345 //*************************************************************************
349 //*************************************************************************
350 template <typename T>
352 {
353 T* p = allocate<T>();
354
355 if (p)
356 {
357 ::new (p) T();
358 }
359
360 return p;
361 }
362
363 //*************************************************************************
368 //*************************************************************************
369 template <typename T, typename T1>
370 T* create(const T1& value1)
371 {
372 T* p = allocate<T>();
373
374 if (p)
375 {
376 ::new (p) T(value1);
377 }
378
379 return p;
380 }
381
382 template <typename T, typename T1, typename T2>
383 T* create(const T1& value1, const T2& value2)
384 {
385 T* p = allocate<T>();
386
387 if (p)
388 {
389 ::new (p) T(value1, value2);
390 }
391
392 return p;
393 }
394
395 template <typename T, typename T1, typename T2, typename T3>
396 T* create(const T1& value1, const T2& value2, const T3& value3)
397 {
398 T* p = allocate<T>();
399
400 if (p)
401 {
402 ::new (p) T(value1, value2, value3);
403 }
404
405 return p;
406 }
407
408 template <typename T, typename T1, typename T2, typename T3, typename T4>
409 T* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
410 {
411 T* p = allocate<T>();
412
413 if (p)
414 {
415 ::new (p) T(value1, value2, value3, value4);
416 }
417
418 return p;
419 }
420#else
421 //*************************************************************************
423 //*************************************************************************
424 template <typename T, typename... Args>
425 T* create(Args&&... args)
426 {
427 T* p = allocate<T>();
428
429 if (p)
430 {
431 ::new (p) T(etl::forward<Args>(args)...);
432 }
433
434 return p;
435 }
436#endif
437
438 //*************************************************************************
442 //*************************************************************************
443 template <typename T>
444 void destroy(const T* const p_object)
445 {
446 if (sizeof(T) > Item_Size)
447 {
448 ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size));
449 }
450
451 p_object->~T();
452 release(p_object);
453 }
454
455 //*************************************************************************
460 //*************************************************************************
461 void release(const void* const p_object)
462 {
463 const uintptr_t p = uintptr_t(p_object);
464 release_item((char*)p);
465 }
466
467 //*************************************************************************
469 //*************************************************************************
471 {
472 items_allocated = 0;
473 items_initialised = 0;
474 p_next = p_buffer;
475 }
476
477 //*************************************************************************
481 //*************************************************************************
482 bool is_in_pool(const void* const p_object) const
483 {
484 const uintptr_t p = uintptr_t(p_object);
485 return is_item_in_pool((const char*)p);
486 }
487
488 //*************************************************************************
490 //*************************************************************************
491 size_t max_size() const
492 {
493 return Max_Size;
494 }
495
496 //*************************************************************************
498 //*************************************************************************
499 size_t max_item_size() const
500 {
501 return Item_Size;
502 }
503
504 //*************************************************************************
506 //*************************************************************************
507 size_t capacity() const
508 {
509 return Max_Size;
510 }
511
512 //*************************************************************************
514 //*************************************************************************
515 size_t available() const
516 {
517 return Max_Size - items_allocated;
518 }
519
520 //*************************************************************************
522 //*************************************************************************
523 size_t size() const
524 {
525 return items_allocated;
526 }
527
528 //*************************************************************************
531 //*************************************************************************
532 bool empty() const
533 {
534 return items_allocated == 0;
535 }
536
537 //*************************************************************************
540 //*************************************************************************
541 bool full() const
542 {
543 return items_allocated == Max_Size;
544 }
545
546 protected:
547
548 //*************************************************************************
550 //*************************************************************************
551 ipool(char* p_buffer_, uint32_t item_size_, uint32_t max_size_)
552 : p_buffer(p_buffer_)
553 , p_next(p_buffer_)
554 , items_allocated(0)
555 , items_initialised(0)
556 , Item_Size(item_size_)
557 , Max_Size(max_size_)
558 {
559 }
560
561 private:
562
563 static ETL_CONSTANT uintptr_t invalid_item_ptr = 1;
564
565 //*************************************************************************
567 //*************************************************************************
568 char* allocate_item()
569 {
570 char* p_value = ETL_NULLPTR;
571
572 // Any free space left?
573 if (items_allocated < Max_Size)
574 {
575 // Initialise another one if necessary.
576 if (items_initialised < Max_Size)
577 {
578 char* p = p_buffer + (items_initialised * Item_Size);
579 char* np = p + Item_Size;
580 *reinterpret_cast<char**>(p) = np;
581 ++items_initialised;
582 }
583
584 // Get the address of new allocated item.
585 p_value = p_next;
586
587 ++items_allocated;
588 if (items_allocated < Max_Size)
589 {
590 // Set up the pointer to the next free item
591 p_next = *reinterpret_cast<char**>(p_next);
592 }
593 else
594 {
595 // No more left!
596 p_next = ETL_NULLPTR;
597 }
598
599 // invalid pointer, outside pool
600 // needs to be different from ETL_NULLPTR since ETL_NULLPTR is used
601 // as list endmarker
602 *reinterpret_cast<uintptr_t*>(p_value) = invalid_item_ptr;
603 }
604 else
605 {
606 ETL_ASSERT(false, ETL_ERROR(pool_no_allocation));
607 }
608
609 return p_value;
610 }
611
612 //*************************************************************************
614 //*************************************************************************
615 void release_item(char* p_value)
616 {
617 // Does it belong to us?
618 ETL_ASSERT(is_item_in_pool(p_value), ETL_ERROR(pool_object_not_in_pool));
619
620 if (items_allocated > 0)
621 {
622 // Point it to the current free item.
623 *(uintptr_t*)p_value = reinterpret_cast<uintptr_t>(p_next);
624
625 p_next = p_value;
626
627 --items_allocated;
628 }
629 else
630 {
631 ETL_ASSERT_FAIL(ETL_ERROR(pool_no_allocation));
632 }
633 }
634
635 //*************************************************************************
637 //*************************************************************************
638 bool is_item_in_pool(const char* p) const
639 {
640 // Within the range of the buffer?
641 intptr_t distance = p - p_buffer;
642 bool is_within_range = (distance >= 0) && (distance <= intptr_t((Item_Size * Max_Size) - Item_Size));
643
644 // Modulus and division can be slow on some architectures, so only do this
645 // in debug.
646#if ETL_IS_DEBUG_BUILD
647 // Is the address on a valid object boundary?
648 bool is_valid_address = ((static_cast<size_t>(distance) % Item_Size) == 0);
649#else
650 bool is_valid_address = true;
651#endif
652
653 return is_within_range && is_valid_address;
654 }
655
656 // Disable copy construction and assignment.
657 ipool(const ipool&);
658 ipool& operator=(const ipool&);
659
660 char* p_buffer;
661 char* p_next;
662
663 uint32_t items_allocated;
664 uint32_t items_initialised;
665
666 const uint32_t Item_Size;
667 const uint32_t Max_Size;
668
669 //*************************************************************************
671 //*************************************************************************
672#if defined(ETL_POLYMORPHIC_POOL) || defined(ETL_POLYMORPHIC_CONTAINERS)
673
674 public:
675
676 virtual ~ipool() {}
677#else
678
679 protected:
680
682#endif
683 };
684} // namespace etl
685
686#endif
Definition ipool.h:275
Definition ipool.h:159
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
size_t size() const
Returns the number of allocated items in the pool.
Definition ipool.h:523
~ipool()
Destructor.
Definition ipool.h:681
bool empty() const
Definition ipool.h:532
void release_all()
Release all objects in the pool.
Definition ipool.h:470
bool full() const
Definition ipool.h:541
size_t max_size() const
Returns the maximum number of items in the pool.
Definition ipool.h:491
T * allocate()
Definition ipool.h:334
void release(const void *const p_object)
Definition ipool.h:461
size_t capacity() const
Returns the maximum number of items in the pool.
Definition ipool.h:507
ipool(char *p_buffer_, uint32_t item_size_, uint32_t max_size_)
Constructor.
Definition ipool.h:551
size_t max_item_size() const
Returns the maximum size of an item in the pool.
Definition ipool.h:499
bool is_in_pool(const void *const p_object) const
Definition ipool.h:482
size_t available() const
Returns the number of free items in the pool.
Definition ipool.h:515
T * create()
Definition ipool.h:351
void destroy(const T *const p_object)
Definition ipool.h:444
T * create(const T1 &value1)
Definition ipool.h:370
Definition ipool.h:97
Definition absolute.h:40
TContainer::iterator end(TContainer &container)
Definition iterator.h:1166
iterator
Definition iterator.h:482
ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Equality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:903
ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Inequality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:937