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  @return address of the allocated memory block or nullptr in case of no memory available.
101 
102  @note You may call this function from ISR context.
103  */
105  {
106  return (T *)osMemoryPoolAlloc(_id, 0);
107  }
108 
109  /** Allocate a memory block from a memory pool, optionally blocking.
110  @param millisec timeout value (osWaitForever to wait forever)
111  @return address of the allocated memory block or nullptr in case of no memory available.
112 
113  @note You may call this function from ISR context if the millisec parameter is set to 0.
114  @deprecated Replaced with `try_alloc_for`. For example use `try_alloc_for(5s)` rather than `alloc_for(5000)`.
115  */
116  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)`.")
117  T *alloc_for(uint32_t millisec)
118  {
119  return try_alloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
120  }
121 
122  /** Allocate a memory block from a memory pool, optionally blocking.
123  @param rel_time timeout value (Kernel::wait_for_u32_forever 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 rel_time parameter is set to 0.
127  */
128  T *try_alloc_for(Kernel::Clock::duration_u32 rel_time)
129  {
130  return (T *)osMemoryPoolAlloc(_id, rel_time.count());
131  }
132 
133  /** Allocate a memory block from a memory pool, blocking.
134  @param millisec absolute timeout time, referenced to Kernel::get_ms_count().
135  @return address of the allocated memory block or nullptr in case of no memory available.
136 
137  @note You cannot call this function from ISR context.
138  @note the underlying RTOS may have a limit to the maximum wait time
139  due to internal 32-bit computations, but this is guaranteed to work if the
140  wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
141  the wait will time out earlier than specified.
142  @deprecated Replaced with `try_alloc_until`. For example use `try_alloc_until(Kernel::Clock::now() + 5s)`
143  rather than `alloc_until(Kernel::get_ms_count() + 5000)`.
144  */
145  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)`.")
146  T *alloc_until(uint64_t millisec)
147  {
148  return try_alloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
149  }
150 
151  /** Allocate a memory block from a memory pool, blocking.
152  @param abs_time absolute timeout time, referenced to Kernel::Clock.
153  @return address of the allocated memory block or nullptr in case of no memory available.
154 
155  @note You cannot call this function from ISR context.
156  @note the underlying RTOS may have a limit to the maximum wait time
157  due to internal 32-bit computations, but this is guaranteed to work if the
158  wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
159  the wait will time out earlier than specified.
160  */
161  T *try_alloc_until(Kernel::Clock::time_point abs_time)
162  {
163  Kernel::Clock::time_point now = Kernel::Clock::now();
164  Kernel::Clock::duration_u32 rel_time;
165  if (now >= abs_time) {
166  rel_time = rel_time.zero();
167  } else if (abs_time - now > Kernel::wait_for_u32_max) {
168  rel_time = Kernel::wait_for_u32_max;
169  } else {
170  rel_time = abs_time - now;
171  }
172  return try_alloc_for(rel_time);
173  }
174 
175  /** Allocate a memory block from a memory pool, without blocking, and set memory block to zero.
176  @return address of the allocated memory block or nullptr in case of no memory available.
177 
178  @note You may call this function from ISR context.
179  @deprecated Replaced with try_calloc. In future calloc() will be an untimed blocking call.
180  */
181  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_calloc. In future calloc() will be an untimed blocking call.")
182  T *calloc()
183  {
184  return try_calloc();
185  }
186 
187  /** Allocate a memory block from a memory pool, without blocking, and set memory block to zero.
188  @return address of the allocated memory block or nullptr in case of no memory available.
189 
190  @note You may call this function from ISR context.
191  */
193  {
194  T *item = try_alloc();
195  if (item != nullptr) {
196  memset(item, 0, sizeof(T));
197  }
198  return item;
199  }
200 
201  /** Allocate a memory block from a memory pool, optionally blocking, and set memory block to zero.
202  @param millisec timeout value (osWaitForever to wait forever)
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 if the millisec parameter is set to 0.
206  @deprecated Replaced with `try_calloc_for`. For example use `try_calloc_for(5s)` rather than `calloc_for(5000)`.
207  */
208  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)`.")
209  T *calloc_for(uint32_t millisec)
210  {
211  return try_calloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
212  }
213 
214  /** Allocate a memory block from a memory pool, optionally blocking, and set memory block to zero.
215  @param rel_time timeout value (Kernel::wait_for_u32_forever to wait forever)
216  @return address of the allocated memory block or nullptr in case of no memory available.
217 
218  @note You may call this function from ISR context if the rel_time parameter is set to 0.
219  */
220  T *try_calloc_for(Kernel::Clock::duration_u32 rel_time)
221  {
222  T *item = try_alloc_for(rel_time);
223  if (item != nullptr) {
224  memset(item, 0, sizeof(T));
225  }
226  return item;
227  }
228 
229  /** Allocate a memory block from a memory pool, blocking, and set memory block to zero.
230  @param millisec absolute timeout time, referenced to Kernel::get_ms_count().
231  @return address of the allocated memory block or nullptr in case of no memory available.
232 
233  @note You cannot call this function from ISR context.
234  @note the underlying RTOS may have a limit to the maximum wait time
235  due to internal 32-bit computations, but this is guaranteed to work if the
236  wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
237  the wait will time out earlier than specified.
238  @deprecated Replaced with `try_calloc_until`. For example use `try_calloc_until(Kernel::Clock::now() + 5s)`
239  rather than `calloc_until(Kernel::get_ms_count() + 5000)`.
240  */
241  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)`.")
242  T *calloc_until(uint64_t millisec)
243  {
244  return try_calloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
245  }
246 
247  /** Allocate a memory block from a memory pool, blocking, and set memory block to zero.
248  @param abs_time absolute timeout time, referenced to Kernel::Clock.
249  @return address of the allocated memory block or nullptr in case of no memory available.
250 
251  @note You cannot call this function from ISR context.
252  @note the underlying RTOS may have a limit to the maximum wait time
253  due to internal 32-bit computations, but this is guaranteed to work if the
254  wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
255  the wait will time out earlier than specified.
256  */
257  T *try_calloc_until(Kernel::Clock::time_point abs_time)
258  {
259  T *item = try_alloc_until(abs_time);
260  if (item != nullptr) {
261  memset(item, 0, sizeof(T));
262  }
263  return item;
264  }
265 
266  /** Free a memory block.
267  @param block address of the allocated memory block to be freed.
268  @return osOK on successful deallocation, osErrorParameter if given memory block id
269  is nullptr or invalid, or osErrorResource if given memory block is in an
270  invalid memory pool state.
271 
272  @note You may call this function from ISR context.
273  */
274  osStatus free(T *block)
275  {
276  return osMemoryPoolFree(_id, block);
277  }
278 
279 private:
280  osMemoryPoolId_t _id;
281  char _pool_mem[MBED_RTOS_STORAGE_MEM_POOL_MEM_SIZE(pool_sz, sizeof(T))];
282  mbed_rtos_storage_mem_pool_t _obj_mem;
283 };
284 /** @}*/
285 /** @}*/
286 }
287 #endif
288 #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:242
T * alloc_until(uint64_t millisec)
Allocate a memory block from a memory pool, blocking.
Definition: MemoryPool.h:146
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:220
T * alloc_for(uint32_t millisec)
Allocate a memory block from a memory pool, optionally blocking.
Definition: MemoryPool.h:117
T * try_alloc_for(Kernel::Clock::duration_u32 rel_time)
Allocate a memory block from a memory pool, optionally blocking.
Definition: MemoryPool.h:128
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:274
#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:161
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:104
T * calloc()
Allocate a memory block from a memory pool, without blocking, and set memory block to zero...
Definition: MemoryPool.h:182
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:209
T * try_calloc()
Allocate a memory block from a memory pool, without blocking, and set memory block to zero...
Definition: MemoryPool.h:192
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:257
#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.