µ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++.
os-mempool.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_RTOS_OS_MEMPOOL_H_
29 #define CMSIS_PLUS_RTOS_OS_MEMPOOL_H_
30 
31 // ----------------------------------------------------------------------------
32 
33 #if defined(__cplusplus)
34 
37 
38 #include <cmsis-plus/diag/trace.h>
39 
40 // ----------------------------------------------------------------------------
41 
42 namespace os
43 {
44  namespace rtos
45  {
46 
47  // ========================================================================
48 
49 #pragma GCC diagnostic push
50 #pragma GCC diagnostic ignored "-Wpadded"
51 
59  {
60  public:
61 
62  // ======================================================================
63 
71  using size_t = uint16_t;
72 
79  static constexpr memory_pool::size_t max_size =
80  static_cast<memory_pool::size_t> (0 - 1);
81 
82  // ======================================================================
83 
90  {
91  public:
92 
103  constexpr
104  attributes ();
105 
106  // The rule of five.
107  attributes (const attributes&) = default;
108  attributes (attributes&&) = default;
109  attributes&
110  operator= (const attributes&) = default;
111  attributes&
112  operator= (attributes&&) = default;
113 
117  ~attributes () = default;
118 
123  public:
124 
130  // Public members; no accessors and mutators required.
131  // Warning: must match the type & order of the C file header.
135  void* mp_pool_address = nullptr;
136 
140  std::size_t mp_pool_size_bytes = 0;
141 
142  // Add more attributes here.
143 
148  }; /* class attributes */
149 
154  static const attributes initializer;
155 
164  template<typename T, std::size_t blocks, std::size_t block_size_bytes>
165  class arena
166  {
167  public:
168  T pool[(blocks * block_size_bytes + sizeof(T) - 1) / sizeof(T)];
169  };
170 
177  template<typename T>
178  constexpr std::size_t
179  compute_allocated_size_bytes (std::size_t blocks,
180  std::size_t block_size_bytes)
181  {
182  // Align each block
183  return (blocks
184  * ((block_size_bytes + (sizeof(T) - 1)) & ~(sizeof(T) - 1)));
185  }
186 
187  // ======================================================================
188 
193 
207  memory_pool (std::size_t blocks, std::size_t block_size_bytes,
208  const attributes& attr = initializer,
219  memory_pool (const char* name, std::size_t blocks,
220  std::size_t block_size_bytes, const attributes& attr =
221  initializer,
223 
224  protected:
225 
230  // Internal constructors, used from templates.
231  memory_pool ();
232  memory_pool (const char* name);
233 
238  public:
239 
244  // The rule of five.
245  memory_pool (const memory_pool&) = delete;
246  memory_pool (memory_pool&&) = delete;
247  memory_pool&
248  operator= (const memory_pool&) = delete;
249  memory_pool&
250  operator= (memory_pool&&) = delete;
251 
256  public:
257 
261  virtual
262  ~memory_pool ();
263 
278  bool
279  operator== (const memory_pool& rhs) const;
280 
285  public:
286 
298  void*
299  alloc (void);
300 
307  void*
308  try_alloc (void);
309 
315  void*
316  timed_alloc (clock::duration_t timeout);
317 
324  result_t
325  free (void* block);
326 
333  std::size_t
334  capacity (void) const;
335 
342  std::size_t
343  count (void) const;
344 
351  std::size_t
352  block_size (void) const;
353 
361  bool
362  empty (void) const;
363 
371  bool
372  full (void) const;
373 
381  result_t
382  reset (void);
383 
390  void*
391  pool (void);
392 
397  protected:
398 
416  void
417  internal_construct_ (std::size_t blocks, std::size_t block_size_bytes,
418  const attributes& attr, void* pool_address,
419  std::size_t pool_size_bytes);
420 
428  void
429  internal_init_ (void);
430 
437  void*
438  internal_try_first_ (void);
439 
448  protected:
449 
459 #if !defined(OS_USE_RTOS_PORT_MEMORY_POOL)
460 
467  clock* clock_ = nullptr;
468 #endif
469 
473  void* pool_addr_ = nullptr;
478  void* allocated_pool_addr_ = nullptr;
479 
483  const void* allocator_ = nullptr;
484 
485 #if defined(OS_USE_RTOS_PORT_MEMORY_POOL)
486  friend class port::memory_pool;
487  os_mempool_port_data_t port_;
488 #endif
489 
494  std::size_t pool_size_bytes_ = 0;
498  std::size_t allocated_pool_size_elements_ = 0;
499 
503  memory_pool::size_t blocks_ = 0;
504 
508  memory_pool::size_t block_size_bytes_ = 0;
509 
513  volatile memory_pool::size_t count_ = 0;
514 
518  void* volatile first_ = nullptr;
519 
528  };
529 
530  // ========================================================================
531 
537  template<typename Allocator = memory::allocator<void*>>
539  {
540  public:
541 
545  using allocator_type = Allocator;
546 
560  memory_pool_allocated (std::size_t blocks, std::size_t block_size_bytes,
561  const attributes& attr = initializer,
562  const allocator_type& allocator =
563  allocator_type ());
564 
574  memory_pool_allocated (const char* name, std::size_t blocks,
575  std::size_t block_size_bytes,
576  const attributes& attr = initializer,
577  const allocator_type& allocator =
578  allocator_type ());
579 
584  // The rule of five.
588  operator= (const memory_pool_allocated&) = delete;
590  operator= (memory_pool_allocated&&) = delete;
591 
599  virtual
601 
606  };
607 
608  // ========================================================================
609 
616  template<typename T, typename Allocator = memory::allocator<void*>>
617  class memory_pool_typed : public memory_pool_allocated<Allocator>
618  {
619  public:
620 
624  using value_type = T;
628  using allocator_type = Allocator;
629 
642  memory_pool_typed (std::size_t blocks,
643  const memory_pool::attributes& attr =
646 
655  memory_pool_typed (const char* name, std::size_t blocks,
656  const memory_pool::attributes& attr =
659 
664  // The rule of five.
665  memory_pool_typed (const memory_pool_typed&) = delete;
668  operator= (const memory_pool_typed&) = delete;
670  operator= (memory_pool_typed&&) = delete;
671 
679  virtual
680  ~memory_pool_typed ();
681 
686  public:
687 
699  value_type*
700  alloc (void);
701 
708  value_type*
709  try_alloc (void);
710 
716  value_type*
717  timed_alloc (clock::duration_t timeout);
718 
726  result_t
727  free (value_type* block);
728 
733  };
734 
735  // ========================================================================
736 
743  template<typename T, std::size_t N>
745  {
746  public:
747 
751  using value_type = T;
752 
756  static const std::size_t blocks = N;
757 
768 
774  memory_pool_inclusive (const char* name, const attributes& attr =
775  initializer);
776 
781  // The rule of five.
785  operator= (const memory_pool_inclusive&) = delete;
787  operator= (memory_pool_inclusive&&) = delete;
788 
796  virtual
798 
803  protected:
804 
819 
824  public:
825 
837  value_type*
838  alloc (void);
839 
846  value_type*
847  try_alloc (void);
848 
854  value_type*
855  timed_alloc (clock::duration_t timeout);
856 
864  result_t
865  free (value_type* block);
866 
871  };
872 
873 #pragma GCC diagnostic pop
874 
875  } /* namespace rtos */
876 } /* namespace os */
877 
878 // ===== Inline & template implementations ====================================
879 
880 namespace os
881 {
882  namespace rtos
883  {
884  constexpr
886  {
887  ;
888  }
889 
890  // ========================================================================
891 
896  inline bool
898  {
899  return this == &rhs;
900  }
901 
907  inline std::size_t
909  {
910  return blocks_;
911  }
912 
918  inline std::size_t
920  {
921  return block_size_bytes_;
922  }
923 
929  inline std::size_t
930  memory_pool::count (void) const
931  {
932  return count_;
933  }
934 
940  inline bool
941  memory_pool::empty (void) const
942  {
943  return (count () == 0);
944  }
945 
951  inline bool
952  memory_pool::full (void) const
953  {
954  return (count () == capacity ());
955  }
956 
962  inline void*
964  {
965  return pool_addr_;
966  }
967 
968  // ========================================================================
969 
995  template<typename Allocator>
996  inline
998  std::size_t blocks, std::size_t block_size_bytes,
999  const attributes& attr, const allocator_type& allocator) :
1001  { nullptr, blocks, block_size_bytes, attr, allocator }
1002  {
1003  ;
1004  }
1005 
1031  template<typename Allocator>
1033  const char* name, std::size_t blocks, std::size_t block_size_bytes,
1034  const attributes& attr, const allocator_type& allocator) :
1035  memory_pool
1036  { name }
1037  {
1038 #if defined(OS_TRACE_RTOS_MEMPOOL)
1039  trace::printf ("%s() @%p %s %d %d\n", __func__, this, this->name (),
1040  blocks, block_size_bytes);
1041 #endif
1042  if (attr.mp_pool_address != nullptr)
1043  {
1044  // Do not use any allocator at all.
1045  internal_construct_ (blocks, block_size_bytes, attr, nullptr, 0);
1046  }
1047  else
1048  {
1049  allocator_ = &allocator;
1050 
1051  // If no user storage was provided via attributes,
1052  // allocate it dynamically via the allocator.
1053  allocated_pool_size_elements_ = (compute_allocated_size_bytes<
1054  typename allocator_type::value_type> (blocks, block_size_bytes)
1055  + sizeof(typename allocator_type::value_type) - 1)
1056  / sizeof(typename allocator_type::value_type);
1057 
1058  allocated_pool_addr_ =
1059  const_cast<allocator_type&> (allocator).allocate (
1060  allocated_pool_size_elements_);
1061 
1062  internal_construct_ (
1063  blocks,
1064  block_size_bytes,
1065  attr,
1066  allocated_pool_addr_,
1067  allocated_pool_size_elements_
1068  * sizeof(typename allocator_type::value_type));
1069  }
1070  }
1071 
1088  template<typename Allocator>
1090  {
1091 #if defined(OS_TRACE_RTOS_MEMPOOL)
1092  trace::printf ("%s() @%p %s\n", __func__, this, name ());
1093 #endif
1094  typedef typename std::allocator_traits<allocator_type>::pointer pointer;
1095 
1096  if (allocated_pool_addr_ != nullptr)
1097  {
1098  static_cast<allocator_type*> (const_cast<void*> (allocator_))->deallocate (
1099  static_cast<pointer> (allocated_pool_addr_),
1100  allocated_pool_size_elements_);
1101 
1102  allocated_pool_addr_ = nullptr;
1103  }
1104  }
1105 
1106  // ========================================================================
1107 
1136  template<typename T, typename Allocator>
1137  inline
1139  std::size_t blocks, const memory_pool::attributes& attr,
1140  const allocator_type& allocator) :
1141  memory_pool_allocated<allocator_type> (blocks, sizeof(T), attr,
1142  allocator)
1143  {
1144  ;
1145  }
1146 
1175  template<typename T, typename Allocator>
1176  inline
1178  const char* name, std::size_t blocks,
1179  const memory_pool::attributes& attr, const allocator_type& allocator) :
1180  memory_pool_allocated<allocator_type> (name, blocks, sizeof(T), attr,
1181  allocator)
1182  {
1183  ;
1184  }
1185 
1204  template<typename T, typename Allocator>
1206  {
1207  ;
1208  }
1209 
1217  template<typename T, typename Allocator>
1220  {
1221  return static_cast<value_type*> (memory_pool_allocated<allocator_type>::alloc ());
1222  }
1223 
1231  template<typename T, typename Allocator>
1234  {
1236  }
1237 
1245  template<typename T, typename Allocator>
1248  {
1250  timeout));
1251  }
1252 
1260  template<typename T, typename Allocator>
1261  inline result_t
1263  {
1265  }
1266 
1267  // ========================================================================
1268 
1295  template<typename T, std::size_t N>
1297  const attributes& attr)
1298  {
1299  internal_construct_ (blocks, sizeof(T), attr, &arena_, sizeof(arena_));
1300  }
1301 
1328  template<typename T, std::size_t N>
1330  const char* name, const attributes& attr) :
1331  memory_pool
1332  { name }
1333  {
1334  internal_construct_ (blocks, sizeof(T), attr, &arena_, sizeof(arena_));
1335  }
1336 
1350  template<typename T, std::size_t N>
1352  {
1353  ;
1354  }
1355 
1363  template<typename T, std::size_t N>
1366  {
1367  return static_cast<value_type*> (memory_pool::alloc ());
1368  }
1369 
1377  template<typename T, std::size_t N>
1380  {
1381  return static_cast<value_type*> (memory_pool::try_alloc ());
1382  }
1383 
1391  template<typename T, std::size_t N>
1394  {
1395  return static_cast<value_type*> (memory_pool::timed_alloc (timeout));
1396  }
1397 
1405  template<typename T, std::size_t N>
1406  inline result_t
1408  {
1409  return memory_pool::free (block);
1410  }
1411 
1412  } /* namespace rtos */
1413 } /* namespace os */
1414 
1415 // ----------------------------------------------------------------------------
1416 
1417 #endif /* __cplusplus */
1418 
1419 #endif /* CMSIS_PLUS_RTOS_OS_MEMPOOL_H_ */
value_type * alloc(void)
Allocate a memory block.
Definition: os-mempool.h:1365
virtual ~memory_pool_inclusive()
Destruct the memory pool object instance.
Definition: os-mempool.h:1351
value_type * try_alloc(void)
Allocate a memory block.
Definition: os-mempool.h:1233
constexpr std::size_t compute_allocated_size_bytes(std::size_t blocks, std::size_t block_size_bytes)
Calculator for pool storage requirements.
Definition: os-mempool.h:179
result_t free(value_type *block)
Free the memory block.
Definition: os-mempool.h:1407
std::size_t capacity(void) const
Get memory pool capacity.
Definition: os-mempool.h:908
std::size_t mp_pool_size_bytes
Size of the user defined storage for the memory pool.
Definition: os-mempool.h:140
void deallocate(value_type *addr, std::size_t elements) noexcept
Deallocate the number of memory blocks of type value_type.
Definition: os-memory.h:1500
virtual ~memory_pool()
Destruct the memory pool object instance.
Definition: os-mempool.cpp:398
Priority ordered list of threads.
Definition: os-lists.h:536
void * timed_alloc(clock::duration_t timeout)
Allocate a memory block with timeout.
Definition: os-mempool.cpp:656
attributes & operator=(const attributes &)=default
bool empty(void) const
Check if the memory pool is empty.
Definition: os-mempool.h:941
Base class for attributes.
Definition: os-decls.h:562
arena< void *, blocks, sizeof(T)> arena_
Local storage for the pool.
Definition: os-mempool.h:818
std::size_t block_size(void) const
Get block size.
Definition: os-mempool.h:919
System namespace.
memory_pool_typed(std::size_t blocks, const memory_pool::attributes &attr=memory_pool::initializer, const allocator_type &allocator=allocator_type())
Construct a memory pool object instance.
Definition: os-mempool.h:1138
virtual ~memory_pool_typed()
Destruct the memory pool object instance.
Definition: os-mempool.h:1205
virtual ~memory_pool_allocated()
Destruct the memory pool object instance.
Definition: os-mempool.h:1089
static const attributes initializer
Default memory pool initialiser.
Definition: os-mempool.h:154
void * pool(void)
Get the pool storage address.
Definition: os-mempool.h:963
Storage for a memory pool.
Definition: os-mempool.h:165
const char * name(void) const
Get object name.
Definition: os-decls.h:760
Base class for named system objects.
Definition: os-decls.h:444
T value_type
Standard allocator type definition.
Definition: os-mempool.h:624
void * alloc(void)
Allocate a memory block.
Definition: os-mempool.cpp:494
Template of a synchronised memory pool with block type and allocator.
Definition: os-mempool.h:617
port::clock::duration_t duration_t
Type of variables holding clock durations.
Definition: os-clocks.h:72
result_t reset(void)
Reset the memory pool.
Definition: os-mempool.cpp:816
result_t free(value_type *block)
Free the memory block.
Definition: os-mempool.h:1262
Synchronised memory pool, using the default RTOS allocator.
Definition: os-mempool.h:58
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition: trace.cpp:74
static constexpr memory_pool::size_t max_size
Maximum pool size.
Definition: os-mempool.h:79
memory_pool_allocated(std::size_t blocks, std::size_t block_size_bytes, const attributes &attr=initializer, const allocator_type &allocator=allocator_type())
Construct a memory pool object instance.
Definition: os-mempool.h:997
Template of a synchronised memory pool with allocator.
Definition: os-mempool.h:538
value_type * timed_alloc(clock::duration_t timeout)
Allocate a memory block with timeout.
Definition: os-mempool.h:1393
T value_type
Type of elements to be allocated.
Definition: os-memory.h:539
memory_pool(std::size_t blocks, std::size_t block_size_bytes, const attributes &attr=initializer, const allocator_type &allocator=allocator_type())
Construct a memory pool object instance.
Definition: os-mempool.cpp:228
value_type * alloc(void)
Allocate a memory block.
Definition: os-mempool.h:1219
T value_type
Local type of message.
Definition: os-mempool.h:751
void * try_alloc(void)
Try to allocate a memory block.
Definition: os-mempool.cpp:590
std::size_t count(void) const
Get blocks count.
Definition: os-mempool.h:930
value_type * timed_alloc(clock::duration_t timeout)
Allocate a memory block with timeout.
Definition: os-mempool.h:1247
memory_pool_inclusive(const attributes &attr=initializer)
Construct a memory pool object instance.
Definition: os-mempool.h:1296
Generic clock.
Definition: os-clocks.h:54
void * mp_pool_address
Address of the user defined storage for the memory pool.
Definition: os-mempool.h:135
bool full(void) const
Check if the memory pool is full.
Definition: os-mempool.h:952
value_type * try_alloc(void)
Allocate a memory block.
Definition: os-mempool.h:1379
result_t free(void *block)
Free the memory block.
Definition: os-mempool.cpp:764
uint32_t result_t
Type of values returned by RTOS functions.
Definition: os-decls.h:96
bool operator==(const memory_pool &rhs) const
Compare memory pools.
Definition: os-mempool.h:897
uint16_t size_t
Type of memory pool size storage.
Definition: os-mempool.h:71
allocator_stateless_default_resource< T > allocator
Type of allocator used by the system objects. Must be stateless.
Definition: os-types.h:57
Template of a synchronised memory pool with block type and local storage.
Definition: os-mempool.h:744
Standard allocator based on the RTOS system default memory manager.
Definition: os-decls.h:82
Memory pool attributes.
Definition: os-mempool.h:89
~attributes()=default
Destruct the memory pool attributes object instance.
constexpr attributes()
Construct a memory pool attributes object instance.
Definition: os-mempool.h:885