µ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++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2016-2025 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can
9 * be obtained from https://opensource.org/licenses/mit.
10 */
11
12#ifndef CMSIS_PLUS_MEMORY_FIRST_FIT_TOP_H_
13#define CMSIS_PLUS_MEMORY_FIRST_FIT_TOP_H_
14
15// ----------------------------------------------------------------------------
16
17#if defined(__cplusplus)
18
19// ----------------------------------------------------------------------------
20
21#include <cmsis-plus/rtos/os.h>
22
23// ----------------------------------------------------------------------------
24
25#pragma GCC diagnostic push
26#if defined(__clang__)
27#pragma clang diagnostic ignored "-Wc++98-compat"
28#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
29#endif
30
31// ----------------------------------------------------------------------------
32
33namespace os
34{
35 namespace memory
36 {
37
38 // ========================================================================
39
54 {
55 public:
66 first_fit_top (void* addr, std::size_t bytes);
67
74 first_fit_top (const char* name, void* addr, std::size_t bytes);
75
76 protected:
81 first_fit_top () = default;
82
87 first_fit_top (const char* name);
88
89 public:
94 // The rule of five.
95 first_fit_top (const first_fit_top&) = delete;
96 first_fit_top (first_fit_top&&) = delete;
98 operator= (const first_fit_top&)
99 = delete;
101 operator= (first_fit_top&&)
102 = delete;
103
111 virtual ~first_fit_top () override;
112
117 protected:
122#pragma GCC diagnostic push
123#if defined(__clang__)
124#pragma clang diagnostic ignored "-Wpadded"
125#elif defined(__GNUC__)
126#pragma GCC diagnostic ignored "-Wpadded"
127#endif
128
129 // A 'chunk' is where the user block resides; it keeps track of size,
130 // it accommodates alignment and helps maintain the free list.
131 typedef struct chunk_s
132 {
133 // The actual chunk size, in bytes;
134 // the next chunk starts exactly after this number of bytes.
135 // This is the only overhead that applies to all allocated blocks.
136 std::size_t size;
137
138 // For allocated chunks, here, or at the next address that
139 // satisfies the required alignment, starts the payload.
140
141 // When the chunk is in the free list, instead of the
142 // payload, here is a pointer to the next chunk.
143 /* struct */ chunk_s* next;
144 } chunk_t;
145
146#pragma GCC diagnostic pop
147
164 void
165 internal_construct_ (void* addr, std::size_t bytes);
166
172 void
173 internal_reset_ (void) noexcept;
174
182 void*
183 internal_align_ (chunk_t* chunk, std::size_t bytes,
184 std::size_t alignment);
185
192 virtual void*
193 do_allocate (std::size_t bytes, std::size_t alignment) override;
194
203 virtual void
204 do_deallocate (void* addr, std::size_t bytes,
205 std::size_t alignment) noexcept override;
206
213 virtual std::size_t
214 do_max_size (void) const noexcept override;
215
223 virtual void
224 do_reset (void) noexcept override;
225
230 protected:
235 // Offset of payload inside the chunk.
236 static constexpr std::size_t chunk_offset = offsetof (chunk_t, next);
237 static constexpr std::size_t chunk_align = sizeof (void*);
238 static constexpr std::size_t chunk_minsize = sizeof (chunk_t);
239
240 static constexpr std::size_t block_minsize = sizeof (void*);
241
242 // Extra padding from chunk to block.
243 static constexpr std::size_t
244 calc_block_padding (std::size_t block_align)
245 {
246 return os::rtos::memory::max (block_align, chunk_align) - chunk_align;
247 }
248
249 // The minimum chunk to it the block.
250 static constexpr std::size_t
251 calc_block_minchunk (std::size_t block_padding)
252 {
253 return chunk_offset + block_minsize + block_padding;
254 }
255
256 void* arena_addr_ = nullptr;
257 // No need for arena_size_bytes_, use total_bytes_.
258
259 chunk_t* free_list_ = nullptr;
260
264 };
265
266 // ========================================================================
267
280 template <std::size_t N>
282 {
283 public:
287 static const std::size_t bytes = N;
288
300
305 first_fit_top_inclusive (const char* name);
306
307 public:
312 // The rule of five.
316 operator= (const first_fit_top_inclusive&)
317 = delete;
319 operator= (first_fit_top_inclusive&&)
320 = delete;
321
329 virtual ~first_fit_top_inclusive ();
330
335 protected:
343 char arena_[bytes];
344
348 };
349
350 // ========================================================================
351
364 template <typename A = os::rtos::memory::allocator<char>>
366 {
367 public:
371 using value_type = char;
372
376 using allocator_type = A;
377
381 using allocator_traits = std::allocator_traits<A>;
382
383 // It is recommended to have the same type, but at least the types
384 // should have the same size.
385 static_assert (
386 sizeof (value_type)
387 == sizeof (typename allocator_traits::value_type),
388 "The allocator must be parametrised with a type of same size.");
389
401 first_fit_top_allocated (std::size_t bytes,
402 const allocator_type& allocator
403 = allocator_type ());
404
412 first_fit_top_allocated (const char* name, std::size_t bytes,
413 const allocator_type& allocator
414 = allocator_type ());
415
416 public:
421 // The rule of five.
425 operator= (const first_fit_top_allocated&)
426 = delete;
428 operator= (first_fit_top_allocated&&)
429 = delete;
430
438 virtual ~first_fit_top_allocated ();
439
444 protected:
458 allocator_type* allocator_ = nullptr;
459
463 };
464
465 // ------------------------------------------------------------------------
466 } /* namespace memory */
467} /* namespace os */
468
469// ===== Inline & template implementations ====================================
470
471namespace os
472{
473 namespace memory
474 {
475
476 // ========================================================================
477
478 inline first_fit_top::first_fit_top (const char* name)
479 : rtos::memory::memory_resource{ name }
480 {
481 }
482
483 inline first_fit_top::first_fit_top (void* addr, std::size_t bytes)
484 : first_fit_top{ nullptr, addr, bytes }
485 {
486 }
487
488 inline first_fit_top::first_fit_top (const char* name, void* addr,
489 std::size_t bytes)
490 : rtos::memory::memory_resource{ name }
491 {
492 trace::printf ("%s(%p,%u) @%p %s\n", __func__, addr, bytes, this,
493 this->name ());
494
495 internal_construct_ (addr, bytes);
496 }
497
498 // ========================================================================
499
500 template <std::size_t N>
502 : first_fit_top_inclusive (nullptr)
503 {
504 }
505
506 template <std::size_t N>
508 const char* name)
509 : first_fit_top{ name }
510 {
511 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
512
513 internal_construct_ (&arena_[0], bytes);
514 }
515
516 template <std::size_t N>
518 {
519 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
520 }
521
522 // ========================================================================
523
524 template <typename A>
526 std::size_t bytes, const allocator_type& allocator)
527 : first_fit_top_allocated (nullptr, bytes, allocator)
528 {
529 }
530
531 template <typename A>
533 const char* name, std::size_t bytes, const allocator_type& allocator)
534 : first_fit_top{ name }
535 {
536 trace::printf ("%s(%u) @%p %s\n", __func__, bytes, this, this->name ());
537
538 // Remember the allocator, it'll be used by the destructor.
539 allocator_ = static_cast<allocator_type*> (
540 &const_cast<allocator_type&> (allocator));
541
542 void* addr = allocator_->allocate (bytes);
543 if (addr == nullptr)
544 {
546 }
547
548 internal_construct_ (addr, bytes);
549 }
550
551 template <typename A>
553 {
554 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
555
556 // Skip in case a derived class did the deallocation.
557 if (allocator_ != nullptr)
558 {
559 allocator_->deallocate (
560 static_cast<typename allocator_traits::pointer> (arena_addr_),
561 total_bytes_);
562
563 // Prevent another deallocation.
564 allocator_ = nullptr;
565 }
566 }
567
568 // ------------------------------------------------------------------------
569
570 } /* namespace memory */
571} /* namespace os */
572
573#pragma GCC diagnostic pop
574
575// ----------------------------------------------------------------------------
576
577#endif /* __cplusplus */
578
579// ----------------------------------------------------------------------------
580
581#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:753
Memory resource manager (abstract class).
Definition os-memory.h:159
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:59
void __throw_bad_alloc(void)
constexpr std::size_t max(std::size_t a, std::size_t b)
Definition os-memory.h:73
System namespace.
Single file µOS++ RTOS definitions.