µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
first-fit-top.h
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ distribution.
3 * (https://github.com/micro-os-plus)
4 * Copyright (c) 2016 Liviu Ionescu.
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following
13 * conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#ifndef CMSIS_PLUS_MEMORY_FIRST_FIT_TOP_H_
29#define CMSIS_PLUS_MEMORY_FIRST_FIT_TOP_H_
30
31// ----------------------------------------------------------------------------
32
33#if defined(__cplusplus)
34
35// ----------------------------------------------------------------------------
36
37#include <cmsis-plus/rtos/os.h>
38
39// ----------------------------------------------------------------------------
40
41#pragma GCC diagnostic push
42
43#if defined(__clang__)
44#pragma clang diagnostic ignored "-Wc++98-compat"
45#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
46#endif
47
48// ----------------------------------------------------------------------------
49
50namespace os
51{
52 namespace memory
53 {
54
55 // ========================================================================
56
71 {
72 public:
73
84 first_fit_top (void* addr, std::size_t bytes);
85
92 first_fit_top (const char* name, void* addr, std::size_t bytes);
93
94 protected:
95
100 first_fit_top () = default;
101
106 first_fit_top (const char* name);
107
108 public:
109
114 // The rule of five.
115 first_fit_top (const first_fit_top&) = delete;
116 first_fit_top (first_fit_top&&) = delete;
118 operator= (const first_fit_top&) = delete;
120 operator= (first_fit_top&&) = delete;
121
129 virtual
130 ~first_fit_top () override;
131
136 protected:
137
142#pragma GCC diagnostic push
143#pragma GCC diagnostic ignored "-Wpadded"
144
145 // A 'chunk' is where the user block resides; it keeps track of size,
146 // it accommodates alignment and helps maintain the free list.
147 typedef struct chunk_s
148 {
149 // The actual chunk size, in bytes;
150 // the next chunk starts exactly after this number of bytes.
151 // This is the only overhead that applies to all allocated blocks.
152 std::size_t size;
153
154 // For allocated chunks, here, or at the next address that
155 // satisfies the required alignment, starts the payload.
156
157 // When the chunk is in the free list, instead of the
158 // payload, here is a pointer to the next chunk.
159 struct chunk_s* next;
160 } chunk_t;
161
162#pragma GCC diagnostic pop
163
180 void
181 internal_construct_ (void* addr, std::size_t bytes);
182
188 void
189 internal_reset_ (void) noexcept;
190
198 void*
199 internal_align_ (chunk_t* chunk, std::size_t bytes, std::size_t alignment);
200
207 virtual void*
208 do_allocate (std::size_t bytes, std::size_t alignment) override;
209
218 virtual void
219 do_deallocate (void* addr, std::size_t bytes, std::size_t alignment)
220 noexcept override;
221
228 virtual std::size_t
229 do_max_size (void) const noexcept override;
230
238 virtual void
239 do_reset (void) noexcept override;
240
245 protected:
246
251 // Offset of payload inside the chunk.
252 static constexpr std::size_t chunk_offset = offsetof(chunk_t, next);
253 static constexpr std::size_t chunk_align = sizeof(void*);
254 static constexpr std::size_t chunk_minsize = sizeof(chunk_t);
255
256 static constexpr std::size_t block_minsize = sizeof(void *);
257
258 // Extra padding from chunk to block.
259 static constexpr std::size_t
260 calc_block_padding (std::size_t block_align)
261 {
262 return os::rtos::memory::max (block_align, chunk_align) - chunk_align;
263 }
264
265 // The minimum chunk to it the block.
266 static constexpr std::size_t
267 calc_block_minchunk (std::size_t block_padding)
268 {
269 return chunk_offset + block_minsize + block_padding;
270 }
271
272 void* arena_addr_ = nullptr;
273 // No need for arena_size_bytes_, use total_bytes_.
274
275 chunk_t* free_list_ = nullptr;
276
281 };
282
283 // ========================================================================
284
297 template<std::size_t N>
299 {
300 public:
301
305 static const std::size_t bytes = N;
306
318
323 first_fit_top_inclusive (const char* name);
324
325 public:
326
331 // The rule of five.
335 operator= (const first_fit_top_inclusive&) = delete;
337 operator= (first_fit_top_inclusive&&) = delete;
338
346 virtual
348
353 protected:
354
362 char arena_[bytes];
363
368 };
369
370 // ========================================================================
371
384 template<typename A = os::rtos::memory::allocator<char>>
386 {
387 public:
388
392 using value_type = char;
393
397 using allocator_type = A;
398
402 using allocator_traits = std::allocator_traits<A>;
403
404 // It is recommended to have the same type, but at least the types
405 // should have the same size.
406 static_assert(sizeof(value_type) == sizeof(typename allocator_traits::value_type),
407 "The allocator must be parametrised with a type of same size.");
408
420 first_fit_top_allocated (std::size_t bytes,
421 const allocator_type& allocator =
422 allocator_type ());
423
431 first_fit_top_allocated (const char* name, std::size_t bytes,
432 const allocator_type& allocator =
433 allocator_type ());
434
435 public:
436
441 // The rule of five.
445 operator= (const first_fit_top_allocated&) = delete;
447 operator= (first_fit_top_allocated&&) = delete;
448
456 virtual
458
463 protected:
464
477 allocator_type* allocator_ = nullptr;
478
483 };
484
485 // --------------------------------------------------------------------------
486 } /* namespace memory */
487} /* namespace os */
488
489// ===== Inline & template implementations ====================================
490
491namespace os
492{
493 namespace memory
494 {
495
496 // ========================================================================
497
498 inline
499 first_fit_top::first_fit_top (const char* name) :
500 rtos::memory::memory_resource
501 { name }
502 {
503 ;
504 }
505
506 inline
507 first_fit_top::first_fit_top (void* addr, std::size_t bytes) :
509 { nullptr, addr, bytes }
510 {
511 ;
512 }
513
514 inline
515 first_fit_top::first_fit_top (const char* name, void* addr,
516 std::size_t bytes) :
517 rtos::memory::memory_resource
518 { name }
519 {
520 trace::printf ("%s(%p,%u) @%p %s\n", __func__, addr, bytes, this,
521 this->name ());
522
523 internal_construct_ (addr, bytes);
524 }
525
526 // ========================================================================
527
528 template<std::size_t N>
529 inline
532 {
533 ;
534 }
535
536 template<std::size_t N>
537 inline
540 { name }
541 {
542 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
543
544 internal_construct_ (&arena_[0], bytes);
545 }
546
547 template<std::size_t N>
549 {
550 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
551 }
552
553 // ========================================================================
554
555 template<typename A>
556 inline
558 std::size_t bytes, const allocator_type& allocator) :
559 first_fit_top_allocated (nullptr, bytes, allocator)
560 {
561 ;
562 }
563
564 template<typename A>
566 const char* name, std::size_t bytes, const allocator_type& allocator) :
568 { name }
569 {
570 trace::printf ("%s(%u) @%p %s\n", __func__, bytes, this, this->name ());
571
572 // Remember the allocator, it'll be used by the destructor.
573 allocator_ =
574 static_cast<allocator_type*> (&const_cast<allocator_type&> (allocator));
575
576 void* addr = allocator_->allocate (bytes);
577 if (addr == nullptr)
578 {
580 }
581
582 internal_construct_ (addr, bytes);
583 }
584
585 template<typename A>
587 {
588 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
589
590 // Skip in case a derived class did the deallocation.
591 if (allocator_ != nullptr)
592 {
593 allocator_->deallocate (
594 static_cast<typename allocator_traits::pointer> (arena_addr_),
595 total_bytes_);
596
597 // Prevent another deallocation.
598 allocator_ = nullptr;
599 }
600 }
601
602 // --------------------------------------------------------------------------
603
604 } /* namespace memory */
605} /* namespace os */
606
607#pragma GCC diagnostic pop
608
609// ----------------------------------------------------------------------------
610
611#endif /* __cplusplus */
612
613// ----------------------------------------------------------------------------
614
615#endif /* CMSIS_PLUS_MEMORY_FIRST_FIT_TOP_H_ */
Memory resource implementing the first fit, top-down allocation policies, using a dynamically allocat...
first_fit_top_allocated(std::size_t bytes, const allocator_type &allocator=allocator_type())
Construct a memory resource object instance.
A allocator_type
Standard allocator type definition.
std::allocator_traits< A > allocator_traits
Standard allocator traits definition.
virtual ~first_fit_top_allocated()
Destruct the memory resource object instance.
char value_type
Standard allocator type definition.
Memory resource implementing the first fit, top-down allocation policies, using an internal arena.
virtual ~first_fit_top_inclusive()
Destruct the memory resource object instance.
first_fit_top_inclusive(void)
Construct a memory resource object instance.
static const std::size_t bytes
Local constant based on template definition.
Memory resource implementing the first fit, top-down allocation policies, using an existing arena.
first_fit_top()=default
Default constructor. Construct a memory resource object instance.
virtual ~first_fit_top() override
Destruct the memory resource object instance.
virtual void do_reset(void) noexcept override
Implementation of the function to reset the memory manager.
void * internal_align_(chunk_t *chunk, std::size_t bytes, std::size_t alignment)
Internal function to align a chunk.
virtual void do_deallocate(void *addr, std::size_t bytes, std::size_t alignment) noexcept override
Implementation of the memory deallocator.
void internal_reset_(void) noexcept
Internal function to reset the memory resource.
virtual void * do_allocate(std::size_t bytes, std::size_t alignment) override
Implementation of the memory allocator.
virtual std::size_t do_max_size(void) const noexcept override
Implementation of the function to get max size.
void internal_construct_(void *addr, std::size_t bytes)
Internal function to construct the memory resource.
const char * name(void) const
Get object name.
Definition os-decls.h:774
Memory resource manager (abstract class).
Definition os-memory.h:165
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:74
void __throw_bad_alloc(void)
constexpr std::size_t max(std::size_t a, std::size_t b)
Definition os-memory.h:85
System namespace.
Single file µOS++ RTOS definitions.