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