Mbed OS Reference
Loading...
Searching...
No Matches
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)
38namespace 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*/
58template<typename T, uint32_t pool_sz>
59class MemoryPool : private mbed::NonCopyable<MemoryPool<T, pool_sz> > {
60 static_assert(pool_sz > 0, "Invalid memory pool size. Must be greater than 0.");
61public:
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 \c std\::malloc or \c std\::allocator&lt;T&gt;\::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.")
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 \c std\::free or \c std\::allocator&lt;T&gt;\::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
305private:
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
Prevents generation of copy constructor and copy assignment operator in derived classes.
Definition: NonCopyable.h:162
Define and manage fixed-size memory pools of objects of a given type.
Definition: MemoryPool.h:59
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
~MemoryPool()
Destroy a memory pool.
Definition: MemoryPool.h:82
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 * 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
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_for(uint32_t millisec)
Allocate a memory block from a memory pool, optionally blocking.
Definition: MemoryPool.h:130
osStatus free(T *block)
Free a memory block.
Definition: MemoryPool.h:300
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
T * try_alloc_for(Kernel::Clock::duration_u32 rel_time)
Allocate a memory block from a memory pool, optionally blocking.
Definition: MemoryPool.h:142
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
MemoryPool()
Create and Initialize a memory pool.
Definition: MemoryPool.h:66
T * try_calloc()
Allocate a memory block from a memory pool, without blocking, and set memory block to zero.
Definition: MemoryPool.h:207
T * alloc_until(uint64_t millisec)
Allocate a memory block from a memory pool, blocking.
Definition: MemoryPool.h:160
#define MBED_ASSERT(expr)
MBED_ASSERT Declare runtime assertions: results in runtime error if condition is false.
Definition: mbed_assert.h:66
#define MBED_DEPRECATED_SINCE(D, M)
MBED_DEPRECATED("message string") Mark a function declaration as deprecated, if it used then a warnin...
constexpr Clock::duration_u32 wait_for_u32_max
Maximum duration for Kernel::Clock::duration_u32-based APIs.
Definition: Kernel.h:114