Mistake on this page?
Report an issue in GitHub or email us
MemoryPool.h
1 /* mbed Microcontroller Library
2  * Copyright (c) 2006-2019 ARM Limited
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 #ifndef MEMORYPOOL_H
24 #define MEMORYPOOL_H
25 
26 #include <stdint.h>
27 #include <string.h>
28 
29 #include "rtos/mbed_rtos_types.h"
30 #include "rtos/internal/mbed_rtos1_types.h"
31 #include "rtos/internal/mbed_rtos_storage.h"
32 #include "platform/NonCopyable.h"
33 #include "platform/mbed_assert.h"
34 #include "rtos/Kernel.h"
35 
36 
37 #if MBED_CONF_RTOS_PRESENT || defined(DOXYGEN_ONLY)
38 namespace rtos {
39 /** \addtogroup rtos-public-api */
40 /** @{*/
41 
42 /**
43  * \defgroup rtos_MemoryPool MemoryPool class
44  * @{
45  */
46 
47 /** Define and manage fixed-size memory pools of objects of a given type.
48  @tparam T data type of a single object (element).
49  @tparam queue_sz maximum number of objects (elements) in the memory pool.
50 
51  @note
52  Memory considerations: The memory pool data store and control structures will be created on current thread's stack,
53  both for the mbed OS and underlying RTOS objects (static or dynamic RTOS memory pools are not being used).
54 
55  @note
56  Bare metal profile: This class is not supported.
57 */
58 template<typename T, uint32_t pool_sz>
59 class MemoryPool : private mbed::NonCopyable<MemoryPool<T, pool_sz> > {
60  static_assert(pool_sz > 0, "Invalid memory pool size. Must be greater than 0.");
61 public:
62  /** Create and Initialize a memory pool.
63  *
64  * @note You cannot call this function from ISR context.
65  */
67  {
68  memset(_pool_mem, 0, sizeof(_pool_mem));
69  osMemoryPoolAttr_t attr = { 0 };
70  attr.mp_mem = _pool_mem;
71  attr.mp_size = sizeof(_pool_mem);
72  attr.cb_mem = &_obj_mem;
73  attr.cb_size = sizeof(_obj_mem);
74  _id = osMemoryPoolNew(pool_sz, sizeof(T), &attr);
75  MBED_ASSERT(_id);
76  }
77 
78  /** Destroy a memory pool
79  *
80  * @note You cannot call this function from ISR context.
81  */
83  {
84  osMemoryPoolDelete(_id);
85  }
86 
87  /** Allocate a memory block from a memory pool, without blocking.
88  @return address of the allocated memory block or nullptr in case of no memory available.
89 
90  @note You may call this function from ISR context.
91  @deprecated Replaced with try_alloc. In future alloc() will be an untimed blocking call.
92  */
93  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_alloc. In future alloc() will be an untimed blocking call.")
94  T *alloc()
95  {
96  return try_alloc();
97  }
98 
99  /** Allocate a memory block from a memory pool, without blocking.
100 
101  This method works like `std::malloc` or `std::allocator<T>::allocate` in that the
102  returned memory block is not initialized. For types with a non-trivial constructor
103  placement new must be used to construct an object in the returned storage.
104 
105  Example:
106  @code
107  MyObject *obj = pool.alloc();
108  if (obj) {
109  new (obj) MyObject(1, 2);
110  }
111  @endcode
112 
113  @return address of the allocated memory block or nullptr in case of no memory available.
114 
115  @note You may call this function from ISR context.
116  */
118  {
119  return (T *)osMemoryPoolAlloc(_id, 0);
120  }
121 
122  /** Allocate a memory block from a memory pool, optionally blocking.
123  @param millisec timeout value (osWaitForever to wait forever)
124  @return address of the allocated memory block or nullptr in case of no memory available.
125 
126  @note You may call this function from ISR context if the millisec parameter is set to 0.
127  @deprecated Replaced with `try_alloc_for`. For example use `try_alloc_for(5s)` rather than `alloc_for(5000)`.
128  */
129  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with `try_alloc_for`. For example use `try_alloc_for(5s)` rather than `alloc_for(5000)`.")
130  T *alloc_for(uint32_t millisec)
131  {
132  return try_alloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
133  }
134 
135  /** Allocate a memory block from a memory pool, optionally blocking.
136  @see MemoryPool::try_alloc
137  @param rel_time timeout value (Kernel::wait_for_u32_forever to wait forever)
138  @return address of the allocated memory block or nullptr in case of no memory available.
139 
140  @note You may call this function from ISR context if the rel_time parameter is set to 0.
141  */
142  T *try_alloc_for(Kernel::Clock::duration_u32 rel_time)
143  {
144  return (T *)osMemoryPoolAlloc(_id, rel_time.count());
145  }
146 
147  /** Allocate a memory block from a memory pool, blocking.
148  @param millisec absolute timeout time, referenced to Kernel::get_ms_count().
149  @return address of the allocated memory block or nullptr in case of no memory available.
150 
151  @note You cannot call this function from ISR context.
152  @note the underlying RTOS may have a limit to the maximum wait time
153  due to internal 32-bit computations, but this is guaranteed to work if the
154  wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
155  the wait will time out earlier than specified.
156  @deprecated Replaced with `try_alloc_until`. For example use `try_alloc_until(Kernel::Clock::now() + 5s)`
157  rather than `alloc_until(Kernel::get_ms_count() + 5000)`.
158  */
159  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with `try_alloc_until`. For example use `try_alloc_until(Kernel::Clock::now() + 5s)` rather than `alloc_until(Kernel::get_ms_count() + 5000)`.")
160  T *alloc_until(uint64_t millisec)
161  {
162  return try_alloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
163  }
164 
165  /** Allocate a memory block from a memory pool, blocking.
166  @see MemoryPool::try_alloc
167  @param abs_time absolute timeout time, referenced to Kernel::Clock.
168  @return address of the allocated memory block or nullptr in case of no memory available.
169 
170  @note You cannot call this function from ISR context.
171  @note the underlying RTOS may have a limit to the maximum wait time
172  due to internal 32-bit computations, but this is guaranteed to work if the
173  wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
174  the wait will time out earlier than specified.
175  */
176  T *try_alloc_until(Kernel::Clock::time_point abs_time)
177  {
178  Kernel::Clock::time_point now = Kernel::Clock::now();
179  Kernel::Clock::duration_u32 rel_time;
180  if (now >= abs_time) {
181  rel_time = rel_time.zero();
182  } else if (abs_time - now > Kernel::wait_for_u32_max) {
183  rel_time = Kernel::wait_for_u32_max;
184  } else {
185  rel_time = abs_time - now;
186  }
187  return try_alloc_for(rel_time);
188  }
189 
190  /** Allocate a memory block from a memory pool, without blocking, and set memory block to zero.
191  @return address of the allocated memory block or nullptr in case of no memory available.
192 
193  @note You may call this function from ISR context.
194  @deprecated Replaced with try_calloc. In future calloc() will be an untimed blocking call.
195  */
196  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_calloc. In future calloc() will be an untimed blocking call.")
197  T *calloc()
198  {
199  return try_calloc();
200  }
201 
202  /** Allocate a memory block from a memory pool, without blocking, and set memory block to zero.
203  @return address of the allocated memory block or nullptr in case of no memory available.
204 
205  @note You may call this function from ISR context.
206  */
208  {
209  T *item = try_alloc();
210  if (item != nullptr) {
211  memset(item, 0, sizeof(T));
212  }
213  return item;
214  }
215 
216  /** Allocate a memory block from a memory pool, optionally blocking, and set memory block to zero.
217  @param millisec timeout value (osWaitForever to wait forever)
218  @return address of the allocated memory block or nullptr in case of no memory available.
219 
220  @note You may call this function from ISR context if the millisec parameter is set to 0.
221  @deprecated Replaced with `try_calloc_for`. For example use `try_calloc_for(5s)` rather than `calloc_for(5000)`.
222  */
223  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with `try_calloc_for`. For example use `try_calloc_for(5s)` rather than `calloc_for(5000)`.")
224  T *calloc_for(uint32_t millisec)
225  {
226  return try_calloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
227  }
228 
229  /** Allocate a memory block from a memory pool, optionally blocking, and set memory block to zero.
230  @param rel_time timeout value (Kernel::wait_for_u32_forever to wait forever)
231  @return address of the allocated memory block or nullptr in case of no memory available.
232 
233  @note You may call this function from ISR context if the rel_time parameter is set to 0.
234  */
235  T *try_calloc_for(Kernel::Clock::duration_u32 rel_time)
236  {
237  T *item = try_alloc_for(rel_time);
238  if (item != nullptr) {
239  memset(item, 0, sizeof(T));
240  }
241  return item;
242  }
243 
244  /** Allocate a memory block from a memory pool, blocking, and set memory block to zero.
245  @param millisec absolute timeout time, referenced to Kernel::get_ms_count().
246  @return address of the allocated memory block or nullptr in case of no memory available.
247 
248  @note You cannot call this function from ISR context.
249  @note the underlying RTOS may have a limit to the maximum wait time
250  due to internal 32-bit computations, but this is guaranteed to work if the
251  wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
252  the wait will time out earlier than specified.
253  @deprecated Replaced with `try_calloc_until`. For example use `try_calloc_until(Kernel::Clock::now() + 5s)`
254  rather than `calloc_until(Kernel::get_ms_count() + 5000)`.
255  */
256  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with `try_calloc_until`. For example use `try_calloc_until(Kernel::Clock::now() + 5s)` rather than `calloc_until(Kernel::get_ms_count() + 5000)`.")
257  T *calloc_until(uint64_t millisec)
258  {
259  return try_calloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
260  }
261 
262  /** Allocate a memory block from a memory pool, blocking, and set memory block to zero.
263  @param abs_time absolute timeout time, referenced to Kernel::Clock.
264  @return address of the allocated memory block or nullptr in case of no memory available.
265 
266  @note You cannot call this function from ISR context.
267  @note the underlying RTOS may have a limit to the maximum wait time
268  due to internal 32-bit computations, but this is guaranteed to work if the
269  wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
270  the wait will time out earlier than specified.
271  */
272  T *try_calloc_until(Kernel::Clock::time_point abs_time)
273  {
274  T *item = try_alloc_until(abs_time);
275  if (item != nullptr) {
276  memset(item, 0, sizeof(T));
277  }
278  return item;
279  }
280 
281  /** Free a memory block.
282 
283  This method works like `std::free` or `std::allocator<T>::deallocate` in that any
284  object in the memory is not destroyed. For types with a non-trivial destructor
285  that destructor must be called manually before freeing the memory.
286 
287  Example:
288  @code
289  obj->~MyObject();
290  pool.free(obj);
291  @endcode
292 
293  @param block address of the allocated memory block to be freed.
294  @return osOK on successful deallocation, osErrorParameter if given memory block id
295  is nullptr or invalid, or osErrorResource if given memory block is in an
296  invalid memory pool state.
297 
298  @note You may call this function from ISR context.
299  */
300  osStatus free(T *block)
301  {
302  return osMemoryPoolFree(_id, block);
303  }
304 
305 private:
306  osMemoryPoolId_t _id;
307  char _pool_mem[MBED_RTOS_STORAGE_MEM_POOL_MEM_SIZE(pool_sz, sizeof(T))];
308  mbed_rtos_storage_mem_pool_t _obj_mem;
309 };
310 /** @}*/
311 /** @}*/
312 }
313 #endif
314 #endif
~MemoryPool()
Destroy a memory pool.
Definition: MemoryPool.h:82
Define and manage fixed-size memory pools of objects of a given type.
Definition: MemoryPool.h:59
T * calloc_until(uint64_t millisec)
Allocate a memory block from a memory pool, blocking, and set memory block to zero.
Definition: MemoryPool.h:257
T * alloc_until(uint64_t millisec)
Allocate a memory block from a memory pool, blocking.
Definition: MemoryPool.h:160
T * try_calloc_for(Kernel::Clock::duration_u32 rel_time)
Allocate a memory block from a memory pool, optionally blocking, and set memory block to zero...
Definition: MemoryPool.h:235
T * alloc_for(uint32_t millisec)
Allocate a memory block from a memory pool, optionally blocking.
Definition: MemoryPool.h:130
T * try_alloc_for(Kernel::Clock::duration_u32 rel_time)
Allocate a memory block from a memory pool, optionally blocking.
Definition: MemoryPool.h:142
Prevents generation of copy constructor and copy assignment operator in derived classes.
Definition: NonCopyable.h:162
constexpr Clock::duration_u32 wait_for_u32_max
Maximum duration for Kernel::Clock::duration_u32-based APIs.
Definition: Kernel.h:114
osStatus free(T *block)
Free a memory block.
Definition: MemoryPool.h:300
#define MBED_ASSERT(expr)
MBED_ASSERT Declare runtime assertions: results in runtime error if condition is false.
Definition: mbed_assert.h:66
T * try_alloc_until(Kernel::Clock::time_point abs_time)
Allocate a memory block from a memory pool, blocking.
Definition: MemoryPool.h:176
T * alloc()
Allocate a memory block from a memory pool, without blocking.
Definition: MemoryPool.h:94
T * try_alloc()
Allocate a memory block from a memory pool, without blocking.
Definition: MemoryPool.h:117
T * calloc()
Allocate a memory block from a memory pool, without blocking, and set memory block to zero...
Definition: MemoryPool.h:197
Definition: TaskBase.h:25
MemoryPool()
Create and Initialize a memory pool.
Definition: MemoryPool.h:66
T * calloc_for(uint32_t millisec)
Allocate a memory block from a memory pool, optionally blocking, and set memory block to zero...
Definition: MemoryPool.h:224
T * try_calloc()
Allocate a memory block from a memory pool, without blocking, and set memory block to zero...
Definition: MemoryPool.h:207
T * try_calloc_until(Kernel::Clock::time_point abs_time)
Allocate a memory block from a memory pool, blocking, and set memory block to zero.
Definition: MemoryPool.h:272
#define MBED_DEPRECATED_SINCE(D, M)
MBED_DEPRECATED("message string") Mark a function declaration as deprecated, if it used then a warnin...
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.