GCC Code Coverage Report


Directory: codebase/
File: codebase/library/include/public/lib.Heap.hpp
Date: 2023-03-16 04:37:09
Exec Total Coverage
Lines: 165 185 89.2%
Functions: 22 26 84.6%
Branches: 83 108 76.9%

Line Branch Exec Source
1 /**
2 * @file lib.Heap.hpp
3 * @author Sergey Baigudin, sergey@baigudin.software
4 * @copyright 2014-2022, Sergey Baigudin, Baigudin Software
5 */
6 #ifndef LIB_HEAP_HPP_
7 #define LIB_HEAP_HPP_
8
9 #include "api.Heap.hpp"
10 #include "lib.MutexGuard.hpp"
11
12 namespace eoos
13 {
14 namespace lib
15 {
16
17 /**
18 * @class Heap
19 * @brief Heap memory.
20 *
21 * Hardware address for system heap memory has to be aligned to eight.
22 */
23 class Heap : public api::Heap
24 {
25 typedef Heap Self;
26
27 class NoAllocator;
28
29 public:
30
31 /**
32 * @brief Constructor.
33 *
34 * @param size Total heap size.
35 * @param mutex A mutex to protect memory allocation.
36 */
37 7 Heap(size_t size, api::Mutex& mutex)
38 7 : api::Heap()
39 7 , data_(size, mutex)
40 7 , temp_() {
41
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 bool_t const isConstructed( construct() );
42 7 setConstructed( isConstructed );
43 7 }
44
45 /**
46 * @brief Destructor.
47 */
48 virtual ~Heap() ///< UT Justified Branch: Language dependency
49 {
50 data_.key = 0;
51 }
52
53 /**
54 * @copydoc eoos::api::Object::isConstructed()
55 */
56 102 virtual bool_t isConstructed() const
57 {
58
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 if( data_.key != HEAP_KEY )
59 { ///< UT Justified Branch: HW dependency
60 return false;
61 }
62
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 102 times.
102 if( !getFirstHeapBlock()->isConstructed() )
63 { ///< UT Justified Branch: HW dependency
64 return false;
65 }
66 102 return true;
67 }
68
69 /**
70 * @copydoc eoos::api::Heap::allocate(size_t,void*)
71 */
72 47 virtual void* allocate(size_t const size, void* ptr)
73 {
74
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 46 times.
47 if( !isConstructed() )
75 {
76 1 return NULLPTR;
77 }
78
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if( ptr == NULLPTR )
79 {
80
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 MutexGuard<NoAllocator> guard( *data_.mutex );
81
1/2
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
46 ptr = getFirstHeapBlock()->alloc(size);
82 46 }
83 46 return ptr;
84 }
85
86 /**
87 * @copydoc eoos::api::Heap::free(void*)
88 */
89 29 virtual void free(void* ptr)
90 {
91
3/4
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 28 times.
29 if( !isConstructed() )
92 {
93 2 return;
94 }
95
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 if( ptr == NULLPTR )
96 {
97 1 return;
98 }
99
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MutexGuard<NoAllocator> guard( *data_.mutex );
100
1/2
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
27 getHeapBlock(ptr)->free();
101 27 }
102
103 /**
104 * @brief Operator new.
105 *
106 * Function initiates a building of heap memory
107 * checks and tests self memory structure data
108 * and leads to call the class constructor.
109 *
110 * @param size Unused.
111 * @param ptr Aligned to eight memory address.
112 * @return Address of memory or NULLPTR.
113 */
114 8 static void* operator new(size_t, uintptr_t const ptr) EOOS_KEYWORD_NOEXCEPT
115 {
116 void* memory;
117 8 void* address( reinterpret_cast< void* >(ptr) ); ///< SCA MISRA-C++:2008 Justified Rule 5-2-8
118
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if(address == NULLPTR)
119 {
120 // No class constructor call
121 1 memory = address;
122 }
123 else
124 {
125 // Create the heap
126 7 memory = create(address);
127 }
128 8 return memory;
129 }
130
131 /**
132 * @brief Operator delete.
133 */
134 static void operator delete(void*, uintptr_t) {} ///< UT Justified Branch: Language dependency
135
136 /**
137 * @brief Operator delete.
138 */
139 static void operator delete(void*) {} ///< UT Justified Branch: Language dependency
140
141 private:
142
143 class HeapBlock;
144
145 /**
146 * @copydoc eoos::lib::Object::setConstructed(bool_t)
147 */
148 7 void setConstructed(bool_t const flag)
149 {
150
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(data_.key == HEAP_KEY)
151 {
152
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 data_.key = flag ? HEAP_KEY : 0;
153 }
154 7 }
155
156 /**
157 * @brief Constructor.
158 *
159 * @return True if object has been constructed successfully.
160 */
161 7 bool_t construct()
162 {
163 // Crop a size to multiple of eight
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if( (sizeof(HeapBlock) + 16UL) > data_.size )
165 { ///< UT Justified Branch: HW dependency
166 return false;
167 }
168 // Test Heap and HeapBlock structures sizes witch has to be multipled to eight
169 if( (sizeof(Heap) & 0x7UL) != 0UL )
170 { ///< UT Justified Branch: HW dependency
171 return false;
172 }
173 if( (sizeof(HeapBlock) & 0x7UL) != 0UL )
174 { ///< UT Justified Branch: HW dependency
175 return false;
176 }
177 // Test memory
178 7 uintptr_t const addr( reinterpret_cast<uintptr_t>(this) + sizeof(Heap) ); ///< SCA MISRA-C++:2008 Justified Rule 5-2-9
179 7 void* ptr ( reinterpret_cast<void*>(addr) ); ///< SCA MISRA-C++:2008 Justified Rule 5-2-8
180
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if( !isMemoryAvailable(ptr, data_.size) )
181 { ///< UT Justified Branch: HW dependency
182 return false;
183 }
184 // Alloc first heap block
185 7 data_.block = new ( getFirstHeapBlock() ) HeapBlock(this, data_.size);
186 7 return (data_.block != NULLPTR) ? true : false;
187 }
188
189 /**
190 * @brief Returns a first heap block address.
191 *
192 * @return Pointer to heap block.
193 */
194 155 HeapBlock* getFirstHeapBlock() const
195 {
196 155 uintptr_t const addr( reinterpret_cast<uintptr_t>(this) + sizeof(Heap) ); ///< SCA MISRA-C++:2008 Justified Rule 5-2-9
197 155 return reinterpret_cast<HeapBlock*>(addr); ///< SCA MISRA-C++:2008 Justified Rule 5-2-8
198 }
199
200 /**
201 * @brief Returns a heap block by user data address.
202 *
203 * @return Pointer to heap block.
204 */
205 27 static HeapBlock* getHeapBlock(void* const data)
206 {
207 27 uintptr_t const addr( reinterpret_cast<uintptr_t>(data) - sizeof(HeapBlock) ); ///< SCA MISRA-C++:2008 Justified Rule 5-2-9
208 27 return reinterpret_cast<HeapBlock*>(addr); ///< SCA MISRA-C++:2008 Justified Rule 5-2-8
209 }
210
211 /**
212 * @brief Allocates memory for heap.
213 *
214 * Function initiates a building of heap memory
215 * checks and tests self memory structure data
216 * and leads to call the class constructor.
217 *
218 * @param ptr Aligned to eight memory address.
219 * @return Address of memory or NULLPTR.
220 */
221 7 static void* create(void* ptr)
222 {
223 // Size of this class has to be multipled to eight
224 if( (sizeof(Heap) & 0x7UL) != 0UL )
225 { ///< UT Justified Branch: HW dependency
226 ptr = NULLPTR;
227 }
228 // Testing memory for self structure data
229 //
230 // @todo copy constructor of the Heap class for
231 // temporary copying the tested memory to that
232 // class. This way would help to restore original
233 // memory data if the test were failed.
234
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if( !isMemoryAvailable(ptr, sizeof(Heap)) )
235 { ///< UT Justified Branch: HW dependency
236 ptr = NULLPTR;
237 }
238 // Memory address has to be aligned to eight
239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if( (reinterpret_cast<uintptr_t>(ptr) & 0x7UL) != 0UL ) ///< SCA MISRA-C++:2008 Justified Rule 5-2-9
240 { ///< UT Justified Branch: HW dependency
241 ptr = NULLPTR;
242 }
243 7 return ptr;
244 }
245
246 /**
247 * @brief Tests memory.
248 *
249 * @todo normal type casts should be done.
250 *
251 * @param addr Memory address pointer.
252 * @param size Size in byte.
253 * @return True if test complete.
254 */
255 14 static bool_t isMemoryAvailable(void* const addr, size_t const size)
256 {
257 14 size_t mask( static_cast<ucell_t>(-1) );
258 14 ucell_t* ptr( reinterpret_cast<ucell_t*>(addr) ); ///< SCA MISRA-C++:2008 Justified Rule 5-2-8
259 // Value test
260
2/2
✓ Branch 0 taken 25600 times.
✓ Branch 1 taken 14 times.
25614 for( size_t i(0UL); i<size; i++)
261 {
262 25600 ptr[i] = static_cast<ucell_t>(i & mask);
263 }
264
2/2
✓ Branch 0 taken 25600 times.
✓ Branch 1 taken 14 times.
25614 for( size_t i(0UL); i<size; i++)
265 {
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25600 times.
25600 if(ptr[i] != static_cast<ucell_t>(i & mask))
267 { ///< UT Justified Branch: HW dependency
268 return false;
269 }
270 }
271 // 0x55 test
272
2/2
✓ Branch 0 taken 25600 times.
✓ Branch 1 taken 14 times.
25614 for( size_t i(0UL); i<size; i++)
273 {
274 25600 ptr[i] = static_cast<ucell_t>(0x55555555UL & mask);
275 }
276
2/2
✓ Branch 0 taken 25600 times.
✓ Branch 1 taken 14 times.
25614 for( size_t i(0UL); i<size; i++)
277 {
278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25600 times.
25600 if(ptr[i] != static_cast<ucell_t>(0x55555555UL & mask))
279 { ///< UT Justified Branch: HW dependency
280 return false;
281 }
282 }
283 // 0xAA test
284
2/2
✓ Branch 0 taken 25600 times.
✓ Branch 1 taken 14 times.
25614 for( size_t i(0UL); i<size; i++)
285 {
286 25600 ptr[i] = static_cast<ucell_t>(0xAAAAAAAAUL & mask);
287 }
288
2/2
✓ Branch 0 taken 25600 times.
✓ Branch 1 taken 14 times.
25614 for( size_t i(0UL); i<size; i++)
289 {
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25600 times.
25600 if(ptr[i] != static_cast<ucell_t>(0xAAAAAAAAUL & mask))
291 { ///< UT Justified Branch: HW dependency
292 return false;
293 }
294 }
295 // Zero test
296
2/2
✓ Branch 0 taken 25600 times.
✓ Branch 1 taken 14 times.
25614 for( size_t i(0UL); i<size; i++)
297 {
298 25600 ptr[i] = 0x00U;
299 }
300
2/2
✓ Branch 0 taken 25600 times.
✓ Branch 1 taken 14 times.
25614 for( size_t i(0UL); i<size; i++)
301 {
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25600 times.
25600 if(ptr[i] != 0x00U)
303 { ///< UT Justified Branch: HW dependency
304 return false;
305 }
306 }
307 14 return true;
308 }
309
310 /**
311 * @copydoc eoos::Object::Object(Object const&)
312 */
313 Heap(Heap const&); ///< SCA MISRA-C++:2008 Justified Rule 3-2-2 and Rule 3-2-4
314
315 /**
316 * @copydoc eoos::Object::operator=(Object const&)
317 */
318 Heap& operator=(Heap const&); ///< SCA MISRA-C++:2008 Justified Rule 3-2-2 and Rule 3-2-4
319
320 #if EOOS_CPP_STANDARD >= 2011
321
322 /**
323 * @copydoc eoos::Object::Object(Object&&)
324 */
325 Heap(Heap&&) noexcept = delete;
326
327 /**
328 * @copydoc eoos::Object::operator=(Object&&)
329 */
330 Heap& operator=(Heap&&) & noexcept = delete;
331
332 #endif // EOOS_CPP_STANDARD >= 2011
333
334 /**
335 * @class NoAllocator
336 * @brief No allocator for creating MutexGuard on stack.
337 */
338 class NoAllocator
339 {
340
341 public:
342
343 /**
344 * @copydoc eoos::lib::Allocator::allocate(size_t)
345 */
346 static void* allocate(size_t)
347 {
348 return NULLPTR;
349 }
350
351 /**
352 * @copydoc eoos::lib::Allocator::allocate(size_t).
353 */
354 static void free(void*) ///< UT Justified Branch: Language dependency
355 {
356 }
357 };
358
359 /**
360 * @struct Aligner<S>
361 * @brief Heap class aligner aligns that to eight.
362 *
363 * @note If given S is already multiple 8, the class size will be 8 bytes.
364 *
365 * @tparam S Size of Heap class.
366 */
367 template <size_t S>
368 struct Aligner
369 {
370
371 public:
372
373 /**
374 * @brief Constructor.
375 */
376 7 Aligner()
377 {
378 #ifdef EOOS_DEBUG
379 for(size_t i(0U); i<SIZE; i++)
380 {
381 val_[i] = 0x0AUL;
382 }
383 #endif
384 7 }
385
386 private:
387
388 /**
389 * @brief Aligning data size.
390 */
391 static const size_t SIZEOF = S;
392
393 /**
394 * @brief Aligning data size.
395 */
396 static const size_t MASK = ~0x7UL;
397
398 /**
399 * @brief Aligning data size.
400 */
401 static const size_t SIZE = ( ( SIZEOF & MASK ) + 0x8UL ) - SIZEOF;
402
403 /**
404 * @brief Temp array.
405 */
406 ucell_t val_[SIZE];
407
408 };
409
410 /**
411 * @class VirtualTable
412 * @brief Contains a Virtual Function Table only.
413 *
414 * Probably, the solution of using this empty class
415 * is not delicate, but it works for understanding
416 * about size of a virtual function table of this Heap class.
417 *
418 * @note This uint64_t variable of the class is used, because some compilers
419 * might put 64 bit variable to aligned 8 memory address. Therefore, size of classes
420 * with 32 bit pointer to virtual table and one 64 bit variable is 16 bytes.
421 */
422 class VirtualTable : public api::Heap{uint64_t temp;};
423
424 /**
425 * @class HeapBlock
426 * @brief Heap memory block.
427 *
428 * The class data has to be aligned to 8.
429 */
430 class HeapBlock
431 {
432
433 public:
434
435 /**
436 * @brief Constructor.
437 *
438 * @param heap Pointer to heap class.
439 * @param size Size of byte given to this new block.
440 */
441 49 HeapBlock(api::Heap* heap, size_t size)
442 49 : heap_(heap)
443 49 , prev_(NULLPTR)
444 49 , next_(NULLPTR)
445 49 , attr_(0)
446 49 , size_(size - sizeof(HeapBlock))
447 49 , key_(BLOCK_KEY) {
448 49 }
449
450 /**
451 * @brief Destructor.
452 */
453 ~HeapBlock()
454 {
455 }
456
457 /**
458 * @brief Tests if this object has been constructed.
459 *
460 * @return True if object has been constructed successfully.
461 */
462 129 bool_t isConstructed() const
463 {
464 129 return (key_ == BLOCK_KEY) ? true : false;
465 }
466
467 /**
468 * @brief Allocates a memory block.
469 *
470 * @param size Size in byte.
471 * @return Pointer to an allocated memory.
472 */
473 46 void* alloc(size_t size)
474 {
475
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 45 times.
46 if(size == 0UL)
476 {
477 1 return NULLPTR;
478 }
479 // Align a size to 8 byte boudary
480
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 44 times.
45 if((size & 0x7UL) != 0UL)
481 {
482 1 size = (size & ~0x7UL) + 0x8UL;
483 }
484 45 HeapBlock* curr( this );
485
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 1 times.
336 while(curr != NULLPTR)
486 {
487
6/6
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 289 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 291 times.
✓ Branch 6 taken 44 times.
335 if(curr->isUsed() || (curr->size_ < size) )
488 {
489 291 curr = curr->next_;
490 }
491 else
492 {
493 44 break;
494 }
495 }
496
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 44 times.
45 if(curr == NULLPTR)
497 {
498 1 return NULLPTR;
499 }
500 // Has required memory size for data and a new heap block
501
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 2 times.
44 if( curr->size_ >= (size + sizeof(HeapBlock)) )
502 {
503 42 HeapBlock* next( new ( curr->next(size) ) HeapBlock(heap_, curr->size_ - size) );
504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if(next == NULLPTR)
505 { ///< UT Justified Branch: HW dependency
506 return NULLPTR;
507 }
508 42 next->next_ = curr->next_;
509 42 next->prev_ = curr;
510
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 41 times.
42 if(next->next_ != NULLPTR)
511 {
512 1 next->next_->prev_ = next;
513 }
514 42 curr->next_ = next;
515 42 curr->size_ = size;
516 }
517 44 curr->attr_ |= ATTR_USED;
518 44 return curr->data();
519 }
520
521 /**
522 * @brief Frees allocated memory by this block.
523 */
524 27 void free()
525 {
526
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
27 if( !canDelete() )
527 { ///< UT Justified Branch: HW dependency
528 return;
529 }
530 27 uint32_t sibling( 0UL );
531
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 3 times.
27 if( prev_ != NULLPTR )
532 {
533
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 18 times.
24 if( !prev_->isUsed() )
534 {
535 6 sibling |= PREV_FREE;
536 }
537 }
538
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 1 times.
27 if( next_ != NULLPTR )
539 {
540
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 8 times.
26 if( !next_->isUsed() )
541 {
542 18 sibling |= NEXT_FREE;
543 }
544 }
545
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 7 times.
27 switch(sibling)
546 {
547 4 case PREV_FREE | NEXT_FREE:
548 {
549 4 prev_->size_ += ( 2UL * sizeof(HeapBlock) ) + size_ + next_->size_;
550 4 prev_->next_ = next_->next_;
551
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if(prev_->next_ != NULLPTR)
552 {
553 1 prev_->next_->prev_ = prev_;
554 }
555 4 break;
556 }
557 2 case PREV_FREE:
558 {
559 2 prev_->size_ += sizeof(HeapBlock) + size_;
560 2 prev_->next_ = next_;
561
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(next_ != NULLPTR)
562 {
563 2 next_->prev_ = prev_;
564 }
565 2 break;
566 }
567 14 case NEXT_FREE:
568 {
569 14 size_ += sizeof(HeapBlock) + next_->size_;
570 14 next_ = next_->next_;
571
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10 times.
14 if(next_ != NULLPTR)
572 {
573 4 next_->prev_ = this;
574 }
575 14 attr_ &= MASK_UNUSED;
576 14 break;
577 }
578 7 default:
579 {
580 7 attr_ &= MASK_UNUSED;
581 7 break;
582 }
583 }
584 }
585
586 /**
587 * @brief Operator new.
588 *
589 * @param size Unused.
590 * @param ptr Address of memory.
591 * @return Address of memory.
592 */
593 49 static void* operator new(size_t, void* const ptr)
594 {
595 49 void* memory( NULLPTR );
596 do
597 {
598 // Size of this class must be multipled to eight
599 if((sizeof(HeapBlock) & 0x7UL) != 0UL)
600 { ///< UT Justified Branch: HW dependency
601 break;
602 }
603 // The passed address must be multipled to eight
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if((reinterpret_cast<uintptr_t>(ptr) & 0x7UL) != 0UL) ///< SCA MISRA-C++:2008 Justified Rule 5-2-9
605 { ///< UT Justified Branch: HW dependency
606 break;
607 }
608 49 memory = ptr;
609 }
610 while(false);
611 49 return memory;
612 }
613
614 /**
615 * @brief Operator delete.
616 */
617 static void operator delete(void*, void*) {} ///< UT Justified Branch: Language dependency
618
619 private:
620
621 /**
622 * @brief Tests if this memory block is available for deleting.
623 *
624 * @return True if it may be deleted.
625 */
626 27 bool_t canDelete() const
627 {
628
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
27 if( !isConstructed() )
629 { ///< UT Justified Branch: HW dependency
630 return false;
631 }
632
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
27 if( !heap_->isConstructed() )
633 { ///< UT Justified Branch: HW dependency
634 return false;
635 }
636 27 return true;
637 }
638
639 /**
640 * @brief Tests if this memory block is available.
641 *
642 * @return True if memory block is available.
643 */
644 385 bool_t isUsed() const
645 {
646 385 return ( (attr_ & ATTR_USED) != 0UL ) ? true : false;
647 }
648
649 /**
650 * @brief Returns an address to data of this block.
651 *
652 * @return Pointer to memory.
653 */
654 44 void* data()
655 {
656 44 uintptr_t const addr( reinterpret_cast<uintptr_t>(this) + sizeof(HeapBlock) ); ///< SCA MISRA-C++:2008 Justified Rule 5-2-9
657 44 return reinterpret_cast<void*>(addr); ///< SCA MISRA-C++:2008 Justified Rule 5-2-8
658 }
659
660 /**
661 * @brief Returns an address to next block.
662 *
663 * @return PSinter to memory.
664 */
665 42 void* next(size_t const size)
666 {
667 42 uintptr_t const addr( reinterpret_cast<uintptr_t>(this) + sizeof(HeapBlock) + size ); ///< SCA MISRA-C++:2008 Justified Rule 5-2-9
668 42 return reinterpret_cast<void*>(addr); ///< SCA MISRA-C++:2008 Justified Rule 5-2-8
669 }
670
671 /**
672 * @copydoc eoos::Object::Object(Object const&)
673 */
674 HeapBlock(HeapBlock const&); ///< SCA MISRA-C++:2008 Justified Rule 3-2-2 and Rule 3-2-4
675
676 /**
677 * @copydoc eoos::Object::operator=(Object const&)
678 */
679 HeapBlock& operator=(HeapBlock const&); ///< SCA MISRA-C++:2008 Justified Rule 3-2-2 and Rule 3-2-4
680
681 #if EOOS_CPP_STANDARD >= 2011
682
683 /**
684 * @copydoc eoos::Object::Object(Object&&)
685 */
686 HeapBlock(HeapBlock&&) noexcept = delete;
687
688 /**
689 * @copydoc eoos::Object::operator=(Object&&)
690 */
691 HeapBlock& operator=(HeapBlock&&) & noexcept = delete;
692
693 #endif // EOOS_CPP_STANDARD >= 2011
694
695 /**
696 * @brief Heap block definition key.
697 */
698 static const size_t BLOCK_KEY = 0x20140515UL;
699
700 /**
701 * @brief Block is used.
702 */
703 static const uint32_t ATTR_USED = 0x00000001UL;
704
705 /**
706 * @brief Next block is free.
707 */
708 static const uint32_t NEXT_FREE = 0x00000001UL;
709
710 /**
711 * @brief Previous block is free.
712 */
713 static const uint32_t PREV_FREE = 0x00000002UL;
714
715 /**
716 * @brief Mask block is unused.
717 */
718 static const uint32_t MASK_UNUSED = 0xFFFFFFFEUL;
719
720 /**
721 * @brief Heap page of this block.
722 */
723 api::Heap* heap_;
724
725 /**
726 * @brief Next block.
727 */
728 HeapBlock* prev_;
729
730 /**
731 * @brief Previous block.
732 */
733 HeapBlock* next_;
734
735 /**
736 * @brief Attributes of this block.
737 */
738 uint32_t attr_;
739
740 /**
741 * @brief Size in byte of this block.
742 */
743 size_t size_;
744
745 /**
746 * @brief Heap block definition key.
747 */
748 size_t key_;
749
750 };
751
752 /**
753 * @struct HeapData
754 * @brief Heap data.
755 *
756 * This structure is needed for aligning heap data or otherwise
757 * this Heap class can not de aligned because it is incompleted.
758 */
759 struct HeapData
760 {
761 /**
762 * @brief Constructor.
763 *
764 * @param isize Total heap size.
765 * @param mutex A mutex to protect memory allocation.
766 */
767 7 HeapData(size_t isize, api::Mutex& imutex)
768 7 : block(NULLPTR)
769 7 , mutex(&imutex)
770 7 , size(0)
771 7 , key(HEAP_KEY) {
772 7 size = (isize & ~0x7UL) - sizeof(Heap);
773 7 }
774
775 /**
776 * @brief First memory block of heap page memory.
777 */
778 HeapBlock* block; ///< SCA MISRA-C++:2008 Justified Rule 11-0-1
779
780 /**
781 * @brief Thread allocation protection.
782 */
783 api::Mutex* mutex; ///< SCA MISRA-C++:2008 Justified Rule 11-0-1
784
785 /**
786 * @brief Actual size of heap.
787 */
788 size_t size; ///< SCA MISRA-C++:2008 Justified Rule 11-0-1
789
790 /**
791 * @brief Heap page memory definition key.
792 */
793 int32_t key; ///< SCA MISRA-C++:2008 Justified Rule 11-0-1
794
795 private:
796
797 /**
798 * @copydoc eoos::Object::Object(Object const&)
799 */
800 HeapData(HeapData const&); ///< SCA MISRA-C++:2008 Justified Rule 3-2-2 and Rule 3-2-4
801
802 /**
803 * @copydoc eoos::Object::operator=(Object const&)
804 */
805 HeapData& operator=(HeapData const&); ///< SCA MISRA-C++:2008 Justified Rule 3-2-2 and Rule 3-2-4
806
807 #if EOOS_CPP_STANDARD >= 2011
808
809 /**
810 * @copydoc eoos::Object::Object(Object&&)
811 */
812 HeapData(HeapData&&) noexcept = delete;
813
814 /**
815 * @copydoc eoos::Object::operator=(Object&&)
816 */
817 HeapData& operator=(HeapData&&) & noexcept = delete;
818
819 #endif // EOOS_CPP_STANDARD >= 2011
820
821 };
822
823 /**
824 * @brief Size of this Heap class without aligned data.
825 */
826 static const size_t SIZEOF_HEAP = ( sizeof(HeapData) + sizeof(VirtualTable) ) - sizeof(uint64_t);
827
828 /**
829 * @brief Heap page memory definition key.
830 */
831 static const int32_t HEAP_KEY = 0x19820401;
832
833 /**
834 * @brief Data of this heap.
835 */
836 HeapData data_;
837
838 /**
839 * @brief Aligning data.
840 */
841 Aligner<SIZEOF_HEAP> temp_;
842
843 };
844
845 } // namespace lib
846 } // namespace eoos
847 #endif // LIB_HEAP_HPP_
848