µOS++ IIIe Reference  v6.3.15
“Perfekt ist nicht gut genug”
The third edition of µOS++, a POSIX inspired open source system, written in C++.
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 #include <cmsis-plus/rtos/os.h>
36 
37 // ----------------------------------------------------------------------------
38 
39 namespace os
40 {
41  namespace memory
42  {
43 
44  // ========================================================================
45 
60  {
61  public:
62 
73  first_fit_top (void* addr, std::size_t bytes);
74 
81  first_fit_top (const char* name, void* addr, std::size_t bytes);
82 
83  protected:
84 
89  first_fit_top () = default;
90 
95  first_fit_top (const char* name);
96 
97  public:
98 
103  // The rule of five.
104  first_fit_top (const first_fit_top&) = delete;
105  first_fit_top (first_fit_top&&) = delete;
107  operator= (const first_fit_top&) = delete;
109  operator= (first_fit_top&&) = delete;
110 
118  virtual
119  ~first_fit_top () override;
120 
125  protected:
126 
131 #pragma GCC diagnostic push
132 #pragma GCC diagnostic ignored "-Wpadded"
133 
134  // A 'chunk' is where the user block resides; it keeps track of size,
135  // it accommodates alignment and helps maintain the free list.
136  typedef struct chunk_s
137  {
138  // The actual chunk size, in bytes;
139  // the next chunk starts exactly after this number of bytes.
140  // This is the only overhead that applies to all allocated blocks.
141  std::size_t size;
142 
143  // For allocated chunks, here, or at the next address that
144  // satisfies the required alignment, starts the payload.
145 
146  // When the chunk is in the free list, instead of the
147  // payload, here is a pointer to the next chunk.
148  struct chunk_s* next;
149  } chunk_t;
150 
151 #pragma GCC diagnostic pop
152 
169  void
170  internal_construct_ (void* addr, std::size_t bytes);
171 
177  void
178  internal_reset_ (void) noexcept;
179 
187  void*
188  internal_align_ (chunk_t* chunk, std::size_t bytes, std::size_t alignment);
189 
196  virtual void*
197  do_allocate (std::size_t bytes, std::size_t alignment) override;
198 
207  virtual void
208  do_deallocate (void* addr, std::size_t bytes, std::size_t alignment)
209  noexcept override;
210 
217  virtual std::size_t
218  do_max_size (void) const noexcept override;
219 
227  virtual void
228  do_reset (void) noexcept override;
229 
234  protected:
235 
240  // Offset of payload inside the chunk.
241  static constexpr std::size_t chunk_offset = offsetof(chunk_t, next);
242  static constexpr std::size_t chunk_align = sizeof(void*);
243  static constexpr std::size_t chunk_minsize = sizeof(chunk_t);
244 
245  static constexpr std::size_t block_minsize = sizeof(void *);
246 
247  // Extra padding from chunk to block.
248  static constexpr std::size_t
249  calc_block_padding (std::size_t block_align)
250  {
251  return os::rtos::memory::max (block_align, chunk_align) - chunk_align;
252  }
253 
254  // The minimum chunk to it the block.
255  static constexpr std::size_t
256  calc_block_minchunk (std::size_t block_padding)
257  {
258  return chunk_offset + block_minsize + block_padding;
259  }
260 
261  void* arena_addr_ = nullptr;
262  // No need for arena_size_bytes_, use total_bytes_.
263 
264  chunk_t* free_list_ = nullptr;
265 
270  };
271 
272  // ========================================================================
273 
286  template<std::size_t N>
288  {
289  public:
290 
294  static const std::size_t bytes = N;
295 
307 
312  first_fit_top_inclusive (const char* name);
313 
314  public:
315 
320  // The rule of five.
324  operator= (const first_fit_top_inclusive&) = delete;
326  operator= (first_fit_top_inclusive&&) = delete;
327 
335  virtual
337 
342  protected:
343 
351  char arena_[bytes];
352 
357  };
358 
359  // ========================================================================
360 
373  template<typename A = os::rtos::memory::allocator<char>>
375  {
376  public:
377 
381  using value_type = char;
382 
386  using allocator_type = A;
387 
391  using allocator_traits = std::allocator_traits<A>;
392 
393  // It is recommended to have the same type, but at least the types
394  // should have the same size.
395  static_assert(sizeof(value_type) == sizeof(typename allocator_traits::value_type),
396  "The allocator must be parametrised with a type of same size.");
397 
409  first_fit_top_allocated (std::size_t bytes,
410  const allocator_type& allocator =
411  allocator_type ());
412 
420  first_fit_top_allocated (const char* name, std::size_t bytes,
421  const allocator_type& allocator =
422  allocator_type ());
423 
424  public:
425 
430  // The rule of five.
434  operator= (const first_fit_top_allocated&) = delete;
436  operator= (first_fit_top_allocated&&) = delete;
437 
445  virtual
447 
452  protected:
453 
466  allocator_type* allocator_ = nullptr;
467 
472  };
473 
474  // --------------------------------------------------------------------------
475  } /* namespace memory */
476 } /* namespace os */
477 
478 // ===== Inline & template implementations ====================================
479 
480 namespace os
481 {
482  namespace memory
483  {
484 
485  // ========================================================================
486 
487  inline
489  rtos::memory::memory_resource
490  { name }
491  {
492  ;
493  }
494 
495  inline
496  first_fit_top::first_fit_top (void* addr, std::size_t bytes) :
498  { nullptr, addr, bytes }
499  {
500  ;
501  }
502 
503  inline
504  first_fit_top::first_fit_top (const char* name, void* addr,
505  std::size_t bytes) :
506  rtos::memory::memory_resource
507  { name }
508  {
509  trace::printf ("%s(%p,%u) @%p %s\n", __func__, addr, bytes, this,
510  this->name ());
511 
512  internal_construct_ (addr, bytes);
513  }
514 
515  // ========================================================================
516 
517  template<std::size_t N>
518  inline
520  first_fit_top_inclusive (nullptr)
521  {
522  ;
523  }
524 
525  template<std::size_t N>
526  inline
529  { name }
530  {
531  trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
532 
533  internal_construct_ (&arena_[0], bytes);
534  }
535 
536  template<std::size_t N>
538  {
539  trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
540  }
541 
542  // ========================================================================
543 
544  template<typename A>
545  inline
547  std::size_t bytes, const allocator_type& allocator) :
548  first_fit_top_allocated (nullptr, bytes, allocator)
549  {
550  ;
551  }
552 
553  template<typename A>
555  const char* name, std::size_t bytes, const allocator_type& allocator) :
557  { name }
558  {
559  trace::printf ("%s(%u) @%p %s\n", __func__, bytes, this, this->name ());
560 
561  // Remember the allocator, it'll be used by the destructor.
562  allocator_ =
563  static_cast<allocator_type*> (&const_cast<allocator_type&> (allocator));
564 
565  void* addr = allocator_->allocate (bytes);
566  if (addr == nullptr)
567  {
569  }
570 
571  internal_construct_ (addr, bytes);
572  }
573 
574  template<typename A>
576  {
577  trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
578 
579  // Skip in case a derived class did the deallocation.
580  if (allocator_ != nullptr)
581  {
582  allocator_->deallocate (
583  static_cast<typename allocator_traits::pointer> (arena_addr_),
584  total_bytes_);
585 
586  // Prevent another deallocation.
587  allocator_ = nullptr;
588  }
589  }
590 
591  // --------------------------------------------------------------------------
592 
593  } /* namespace memory */
594 } /* namespace os */
595 
596 // ----------------------------------------------------------------------------
597 
598 #endif /* __cplusplus */
599 
600 #endif /* CMSIS_PLUS_MEMORY_FIRST_FIT_TOP_H_ */
Memory resource manager (abstract class).
Definition: os-memory.h:153
Memory resource implementing the first fit, top-down allocation policies, using an internal arena...
constexpr std::size_t max(std::size_t a, std::size_t b)
Definition: os-memory.h:74
virtual void * do_allocate(std::size_t bytes, std::size_t alignment) override
Implementation of the memory allocator.
first_fit_top()=default
Default constructor. Construct a memory resource object instance.
void * internal_align_(chunk_t *chunk, std::size_t bytes, std::size_t alignment)
Internal function to align a chunk.
void internal_construct_(void *addr, std::size_t bytes)
Internal function to construct the memory resource.
System namespace.
virtual std::size_t do_max_size(void) const noexcept override
Implementation of the function to get max size.
A allocator_type
Standard allocator type definition.
memory_resource()=default
Default constructor. Construct a memory resource object instance.
std::allocator_traits< A > allocator_traits
Standard allocator traits definition.
const char * name(void) const
Get object name.
Definition: os-decls.h:760
first_fit_top_inclusive(void)
Construct a memory resource object instance.
virtual void do_deallocate(void *addr, std::size_t bytes, std::size_t alignment) noexcept override
Implementation of the memory deallocator.
virtual void do_reset(void) noexcept override
Implementation of the function to reset the memory manager.
Single file µOS++ RTOS definitions.
first_fit_top_allocated(std::size_t bytes, const allocator_type &allocator=allocator_type())
Construct a memory resource object instance.
static const std::size_t bytes
Local constant based on template definition.
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition: trace.cpp:74
virtual ~first_fit_top() override
Destruct the memory resource object instance.
char value_type
Standard allocator type definition.
void internal_reset_(void) noexcept
Internal function to reset the memory resource.
virtual ~first_fit_top_inclusive()
Destruct the memory resource object instance.
Memory resource implementing the first fit, top-down allocation policies, using an existing arena...
Definition: first-fit-top.h:59
virtual ~first_fit_top_allocated()
Destruct the memory resource object instance.
Memory resource implementing the first fit, top-down allocation policies, using a dynamically allocat...
allocator_stateless_default_resource< T > allocator
Type of allocator used by the system objects. Must be stateless.
Definition: os-types.h:57
void __throw_bad_alloc(void)