Embedded Template Library 1.0
Loading...
Searching...
No Matches
reference_counted_message_pool.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2020 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_REFERENCE_COUNTED_MESSAGE_POOL_INCLUDED
32#define ETL_REFERENCE_COUNTED_MESSAGE_POOL_INCLUDED
33
34#include "platform.h"
35#include "atomic.h"
36#include "error_handler.h"
39#include "largest.h"
40#include "memory.h"
41#include "message.h"
42#include "reference_counted_message.h"
43#include "static_assert.h"
44#include "utility.h"
45
46namespace etl
47{
48 //***************************************************************************
50 //***************************************************************************
51 class reference_counted_message_pool_exception : public etl::exception
52 {
53 public:
54
55 reference_counted_message_pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
56 : exception(reason_, file_name_, line_number_)
57 {
58 }
59 };
60
61 //***************************************************************************
63 //***************************************************************************
64 class reference_counted_message_pool_allocation_failure : public etl::reference_counted_message_pool_exception
65 {
66 public:
67
68 reference_counted_message_pool_allocation_failure(string_type file_name_, numeric_type line_number_)
69 : reference_counted_message_pool_exception(
70 ETL_ERROR_TEXT("reference_counted_message_pool:allocation failure", ETL_REFERENCE_COUNTER_MESSAGE_POOL_FILE_ID"A"), file_name_, line_number_)
71 {
72 }
73 };
74
75 //***************************************************************************
77 //***************************************************************************
78 class reference_counted_message_pool_release_failure : public etl::reference_counted_message_pool_exception
79 {
80 public:
81
82 reference_counted_message_pool_release_failure(string_type file_name_, numeric_type line_number_)
83 : reference_counted_message_pool_exception(
84 ETL_ERROR_TEXT("reference_counted_message_pool:release failure", ETL_REFERENCE_COUNTER_MESSAGE_POOL_FILE_ID"B"), file_name_, line_number_)
85 {
86 }
87 };
88
89 //***************************************************************************
91 //***************************************************************************
92 template <typename TCounter>
94 {
95 public:
96
97 //*************************************************************************
99 //*************************************************************************
101 : memory_block_allocator(memory_block_allocator_)
102 {
103 }
104
105#if ETL_USING_CPP11
106 //*************************************************************************
108 //*************************************************************************
109 template <typename TMessage, typename... TArgs>
111 {
112 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage>::value), "Not a message type");
113
115 typedef rcm_t* prcm_t;
116
117 prcm_t p = ETL_NULLPTR;
118
119 lock();
120 p = static_cast<prcm_t>(memory_block_allocator.allocate(sizeof(rcm_t), etl::alignment_of<rcm_t>::value));
121 unlock();
122
123 if (p != ETL_NULLPTR)
124 {
125 ::new (p) rcm_t(*this, etl::forward<TArgs>(args)...);
126 }
127
129
130 return p;
131 }
132#endif
133
134 //*************************************************************************
136 //*************************************************************************
137 template <typename TMessage>
139 {
140 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage>::value), "Not a message type");
141
143 typedef rcm_t* prcm_t;
144
145 prcm_t p = ETL_NULLPTR;
146
147 lock();
148 p = static_cast<prcm_t>(memory_block_allocator.allocate(sizeof(rcm_t), etl::alignment_of<rcm_t>::value));
149 unlock();
150
151 if (p != ETL_NULLPTR)
152 {
153 ::new (p) rcm_t(message, *this);
154 }
155
157
158 return p;
159 }
160
161 //*************************************************************************
163 //*************************************************************************
164 template <typename TMessage>
166 {
167 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage>::value), "Not a message type");
168
170 typedef rcm_t* prcm_t;
171
172 prcm_t p = ETL_NULLPTR;
173
174 lock();
175 p = static_cast<prcm_t>(memory_block_allocator.allocate(sizeof(rcm_t), etl::alignment_of<rcm_t>::value));
176 unlock();
177
178 if (p != ETL_NULLPTR)
179 {
180 ::new (p) rcm_t(*this);
181 }
182
184
185 return p;
186 }
187
188 //*************************************************************************
190 //*************************************************************************
192 {
193 bool released = false;
194
195 lock();
196 if (memory_block_allocator.is_owner_of(&rcmessage))
197 {
198 rcmessage.~ireference_counted_message();
199 released = memory_block_allocator.release(&rcmessage);
200 }
201 unlock();
202
204 }
205
206#if ETL_USING_CPP11
207 //*****************************************************
208 template <typename TMessage1, typename... TMessages>
209 struct pool_message_parameters
210 {
211 private:
212
213 // Size of the first pool message type.
214 static constexpr size_t size1 = sizeof(etl::reference_counted_message<TMessage1, TCounter>);
215
216 // Maximum size of the rest of the pool message types.
217 static constexpr size_t size2 = pool_message_parameters<TMessages...>::max_size;
218
219 // Size of the first pool message type.
220 static constexpr size_t alignment1 = etl::alignment_of< etl::reference_counted_message<TMessage1, TCounter>>::value;
221
222 // Maximum size of the rest of the pool message types.
223 static constexpr size_t alignment2 = pool_message_parameters<TMessages...>::max_alignment;
224
225 public:
226
227 // The maximum size.
228 static constexpr size_t max_size = (size1 < size2) ? size2 : size1;
229
230 // The maximum alignment.
231 static constexpr size_t max_alignment = (alignment1 < alignment2) ? alignment2 : alignment1;
232 };
233
234 //*****************************************************
235 template <typename TMessage1>
236 struct pool_message_parameters<TMessage1>
237 {
238 public:
239
240 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage not derived from etl::imessage");
241
242 // The size of this pool message type.
243 static constexpr size_t max_size = sizeof(etl::reference_counted_message<TMessage1, TCounter>);
244
245 // The maximum alignment.
246 static constexpr size_t max_alignment = etl::alignment_of< etl::reference_counted_message<TMessage1, TCounter>>::value;
247 };
248
249#else
250 template <typename TMessage1, typename TMessage2 = TMessage1, typename TMessage3 = TMessage1, typename TMessage4 = TMessage1,
251 typename TMessage5 = TMessage1, typename TMessage6 = TMessage1, typename TMessage7 = TMessage1, typename TMessage8 = TMessage1>
253 {
254 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage1 not derived from etl::imessage");
255 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage2 not derived from etl::imessage");
256 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage3 not derived from etl::imessage");
257 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage4 not derived from etl::imessage");
258 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage5 not derived from etl::imessage");
259 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage6 not derived from etl::imessage");
260 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage7 not derived from etl::imessage");
261 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage8 not derived from etl::imessage");
262
263 static ETL_CONSTANT size_t max_size =
268
269 static ETL_CONSTANT size_t max_alignment =
274 };
275
276#endif
277
278 private:
279
281 imemory_block_allocator& memory_block_allocator;
282
283 // Should not be copied.
286 };
287
288#if ETL_USING_CPP11
289
290 template <typename TCounter>
291 template <typename TMessage1, typename... TMessages>
292 constexpr size_t reference_counted_message_pool< TCounter>::pool_message_parameters< TMessage1, TMessages...>::max_size;
293
294 template <typename TCounter>
295 template <typename TMessage1, typename... TMessages>
296 constexpr size_t reference_counted_message_pool< TCounter>::pool_message_parameters< TMessage1, TMessages...>::max_alignment;
297
298#else
299
300 template <typename TCounter>
301 template <typename TMessage1, typename TMessage2, typename TMessage3, typename TMessage4, typename TMessage5, typename TMessage6,
302 typename TMessage7, typename TMessage8>
303 const size_t reference_counted_message_pool<TCounter>::pool_message_parameters< TMessage1, TMessage2, TMessage3, TMessage4, TMessage5, TMessage6,
304 TMessage7, TMessage8>::max_size;
305
306 template <typename TCounter>
307 template <typename TMessage1, typename TMessage2, typename TMessage3, typename TMessage4, typename TMessage5, typename TMessage6,
308 typename TMessage7, typename TMessage8>
309 const size_t reference_counted_message_pool<TCounter>::pool_message_parameters< TMessage1, TMessage2, TMessage3, TMessage4, TMessage5, TMessage6,
310 TMessage7, TMessage8>::max_alignment;
311
312#endif
313
314#if ETL_USING_CPP11 && ETL_HAS_ATOMIC
315 using atomic_counted_message_pool = reference_counted_message_pool<etl::atomic_int>;
316#endif
317} // namespace etl
318
319#endif
The interface for a memory block pool.
Definition imemory_block_allocator.h:44
void * allocate(size_t required_size, size_t required_alignment)
Definition imemory_block_allocator.h:57
Interface for a reference counted message pool.
Definition ireference_counted_message_pool.h:44
virtual void unlock()
Definition ireference_counted_message_pool.h:65
virtual void lock()
Definition ireference_counted_message_pool.h:56
Definition reference_counted_message.h:48
Definition message.h:94
Exception if the allocation failed.
Definition reference_counted_message_pool.h:65
Exception type for etl::reference_counted_message_pool.
Definition reference_counted_message_pool.h:52
Exception if the release failed.
Definition reference_counted_message_pool.h:79
A pool for allocating reference counted messages.
Definition reference_counted_message_pool.h:94
void release(const etl::ireference_counted_message &rcmessage)
Destruct a message and send it back to the allocator.
Definition reference_counted_message_pool.h:191
reference_counted_message_pool(etl::imemory_block_allocator &memory_block_allocator_)
Constructor.
Definition reference_counted_message_pool.h:100
etl::reference_counted_message< TMessage, TCounter > * allocate(const TMessage &message)
Allocate a reference counted message from the pool.
Definition reference_counted_message_pool.h:138
etl::reference_counted_message< TMessage, TCounter > * allocate()
Allocate a reference counted message from the pool.
Definition reference_counted_message_pool.h:165
Definition reference_counted_message.h:69
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition exception.h:59
Definition largest.h:45
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1192
Definition reference_counted_message_pool.h:253