µ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-2023 Liviu Ionescu. All rights reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software
7 * for any purpose is hereby granted, under the terms of the MIT license.
8 *
9 * If a copy of the license was not distributed with this file, it can
10 * be obtained from https://opensource.org/licenses/mit/.
11 */
12
13#ifndef CMSIS_PLUS_MEMORY_FIRST_FIT_TOP_H_
14#define CMSIS_PLUS_MEMORY_FIRST_FIT_TOP_H_
15
16// ----------------------------------------------------------------------------
17
18#if defined(__cplusplus)
19
20// ----------------------------------------------------------------------------
21
22#include <cmsis-plus/rtos/os.h>
23
24// ----------------------------------------------------------------------------
25
26#pragma GCC diagnostic push
27#if defined(__clang__)
28#pragma clang diagnostic ignored "-Wc++98-compat"
29#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
30#endif
31
32// ----------------------------------------------------------------------------
33
34namespace os
35{
36 namespace memory
37 {
38
39 // ========================================================================
40
55 {
56 public:
57
68 first_fit_top (void* addr, std::size_t bytes);
69
76 first_fit_top (const char* name, void* addr, std::size_t bytes);
77
78 protected:
79
84 first_fit_top () = default;
85
90 first_fit_top (const char* name);
91
92 public:
93
98 // The rule of five.
99 first_fit_top (const first_fit_top&) = delete;
100 first_fit_top (first_fit_top&&) = delete;
102 operator= (const first_fit_top&) = delete;
104 operator= (first_fit_top&&) = delete;
105
113 virtual
114 ~first_fit_top () override;
115
120 protected:
121
126#pragma GCC diagnostic push
127#if defined(__clang__)
128#pragma clang diagnostic ignored "-Wpadded"
129#elif defined(__GNUC__)
130#pragma GCC diagnostic ignored "-Wpadded"
131#endif
132
133 // A 'chunk' is where the user block resides; it keeps track of size,
134 // it accommodates alignment and helps maintain the free list.
135 typedef struct chunk_s
136 {
137 // The actual chunk size, in bytes;
138 // the next chunk starts exactly after this number of bytes.
139 // This is the only overhead that applies to all allocated blocks.
140 std::size_t size;
141
142 // For allocated chunks, here, or at the next address that
143 // satisfies the required alignment, starts the payload.
144
145 // When the chunk is in the free list, instead of the
146 // payload, here is a pointer to the next chunk.
147 /* struct */ chunk_s* next;
148 } chunk_t;
149
150#pragma GCC diagnostic pop
151
168 void
169 internal_construct_ (void* addr, std::size_t bytes);
170
176 void
177 internal_reset_ (void) noexcept;
178
186 void*
187 internal_align_ (chunk_t* chunk, std::size_t bytes, std::size_t alignment);
188
195 virtual void*
196 do_allocate (std::size_t bytes, std::size_t alignment) override;
197
206 virtual void
207 do_deallocate (void* addr, std::size_t bytes, std::size_t alignment)
208 noexcept override;
209
216 virtual std::size_t
217 do_max_size (void) const noexcept override;
218
226 virtual void
227 do_reset (void) noexcept override;
228
233 protected:
234
239 // Offset of payload inside the chunk.
240 static constexpr std::size_t chunk_offset = offsetof(chunk_t, next);
241 static constexpr std::size_t chunk_align = sizeof(void*);
242 static constexpr std::size_t chunk_minsize = sizeof(chunk_t);
243
244 static constexpr std::size_t block_minsize = sizeof(void *);
245
246 // Extra padding from chunk to block.
247 static constexpr std::size_t
248 calc_block_padding (std::size_t block_align)
249 {
250 return os::rtos::memory::max (block_align, chunk_align) - chunk_align;
251 }
252
253 // The minimum chunk to it the block.
254 static constexpr std::size_t
255 calc_block_minchunk (std::size_t block_padding)
256 {
257 return chunk_offset + block_minsize + block_padding;
258 }
259
260 void* arena_addr_ = nullptr;
261 // No need for arena_size_bytes_, use total_bytes_.
262
263 chunk_t* free_list_ = nullptr;
264
269 };
270
271 // ========================================================================
272
285 template<std::size_t N>
287 {
288 public:
289
293 static const std::size_t bytes = N;
294
306
311 first_fit_top_inclusive (const char* name);
312
313 public:
314
319 // The rule of five.
323 operator= (const first_fit_top_inclusive&) = delete;
325 operator= (first_fit_top_inclusive&&) = delete;
326
334 virtual
336
341 protected:
342
350 char arena_[bytes];
351
356 };
357
358 // ========================================================================
359
372 template<typename A = os::rtos::memory::allocator<char>>
374 {
375 public:
376
380 using value_type = char;
381
385 using allocator_type = A;
386
390 using allocator_traits = std::allocator_traits<A>;
391
392 // It is recommended to have the same type, but at least the types
393 // should have the same size.
394 static_assert(sizeof(value_type) == sizeof(typename allocator_traits::value_type),
395 "The allocator must be parametrised with a type of same size.");
396
408 first_fit_top_allocated (std::size_t bytes,
409 const allocator_type& allocator =
410 allocator_type ());
411
419 first_fit_top_allocated (const char* name, std::size_t bytes,
420 const allocator_type& allocator =
421 allocator_type ());
422
423 public:
424
429 // The rule of five.
433 operator= (const first_fit_top_allocated&) = delete;
435 operator= (first_fit_top_allocated&&) = delete;
436
444 virtual
446
451 protected:
452
465 allocator_type* allocator_ = nullptr;
466
471 };
472
473 // --------------------------------------------------------------------------
474 } /* namespace memory */
475} /* namespace os */
476
477// ===== Inline & template implementations ====================================
478
479namespace os
480{
481 namespace memory
482 {
483
484 // ========================================================================
485
486 inline
487 first_fit_top::first_fit_top (const char* name) :
488 rtos::memory::memory_resource
489 { name }
490 {
491 }
492
493 inline
494 first_fit_top::first_fit_top (void* addr, std::size_t bytes) :
496 { nullptr, addr, bytes }
497 {
498 }
499
500 inline
501 first_fit_top::first_fit_top (const char* name, void* addr,
502 std::size_t bytes) :
503 rtos::memory::memory_resource
504 { name }
505 {
506 trace::printf ("%s(%p,%u) @%p %s\n", __func__, addr, bytes, this,
507 this->name ());
508
509 internal_construct_ (addr, bytes);
510 }
511
512 // ========================================================================
513
514 template<std::size_t N>
515 inline
518 {
519 }
520
521 template<std::size_t N>
522 inline
525 { name }
526 {
527 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
528
529 internal_construct_ (&arena_[0], bytes);
530 }
531
532 template<std::size_t N>
534 {
535 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
536 }
537
538 // ========================================================================
539
540 template<typename A>
541 inline
543 std::size_t bytes, const allocator_type& allocator) :
544 first_fit_top_allocated (nullptr, bytes, allocator)
545 {
546 }
547
548 template<typename A>
550 const char* name, std::size_t bytes, const allocator_type& allocator) :
552 { name }
553 {
554 trace::printf ("%s(%u) @%p %s\n", __func__, bytes, this, this->name ());
555
556 // Remember the allocator, it'll be used by the destructor.
557 allocator_ =
558 static_cast<allocator_type*> (&const_cast<allocator_type&> (allocator));
559
560 void* addr = allocator_->allocate (bytes);
561 if (addr == nullptr)
562 {
564 }
565
566 internal_construct_ (addr, bytes);
567 }
568
569 template<typename A>
571 {
572 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
573
574 // Skip in case a derived class did the deallocation.
575 if (allocator_ != nullptr)
576 {
577 allocator_->deallocate (
578 static_cast<typename allocator_traits::pointer> (arena_addr_),
579 total_bytes_);
580
581 // Prevent another deallocation.
582 allocator_ = nullptr;
583 }
584 }
585
586 // --------------------------------------------------------------------------
587
588 } /* namespace memory */
589} /* namespace os */
590
591#pragma GCC diagnostic pop
592
593// ----------------------------------------------------------------------------
594
595#endif /* __cplusplus */
596
597// ----------------------------------------------------------------------------
598
599#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:759
Memory resource manager (abstract class).
Definition os-memory.h:160
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:60
void __throw_bad_alloc(void)
constexpr std::size_t max(std::size_t a, std::size_t b)
Definition os-memory.h:74
System namespace.
Single file µOS++ RTOS definitions.