Embedded Template Library 1.0
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 "message.h"
38#include "reference_counted_message.h"
39#include "static_assert.h"
40#include "error_handler.h"
41#include "utility.h"
42#include "atomic.h"
43#include "memory.h"
44#include "largest.h"
45
46namespace etl
47{
48 //***************************************************************************
50 //***************************************************************************
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 //***************************************************************************
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(ETL_ERROR_TEXT("reference_counted_message_pool:allocation failure", ETL_REFERENCE_COUNTER_MESSAGE_POOL_FILE_ID"A"), file_name_, line_number_)
70 {
71 }
72 };
73
74 //***************************************************************************
76 //***************************************************************************
78 {
79 public:
80
81 reference_counted_message_pool_release_failure(string_type file_name_, numeric_type line_number_)
82 : reference_counted_message_pool_exception(ETL_ERROR_TEXT("reference_counted_message_pool:release failure", ETL_REFERENCE_COUNTER_MESSAGE_POOL_FILE_ID"B"), file_name_, line_number_)
83 {
84 }
85 };
86
87 //***************************************************************************
89 //***************************************************************************
90 template <typename TCounter>
92 {
93 public:
94
95 //*************************************************************************
97 //*************************************************************************
99 : memory_block_allocator(memory_block_allocator_)
100 {
101 }
102
103 //*************************************************************************
105 //*************************************************************************
106 template <typename TMessage>
108 {
109 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage>::value), "Not a message type");
110
112 typedef rcm_t* prcm_t;
113
114 prcm_t p = ETL_NULLPTR;
115
116 lock();
117 p = static_cast<prcm_t>(memory_block_allocator.allocate(sizeof(rcm_t), etl::alignment_of<rcm_t>::value));
118 unlock();
119
120 if (p != ETL_NULLPTR)
121 {
122 ::new(p) rcm_t(message, *this);
123 }
124
126
127 return p;
128 }
129
130 //*************************************************************************
132 //*************************************************************************
133 template <typename TMessage>
135 {
136 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage>::value), "Not a message type");
137
139 typedef rcm_t* prcm_t;
140
141 prcm_t p = ETL_NULLPTR;
142
143 lock();
144 p = static_cast<prcm_t>(memory_block_allocator.allocate(sizeof(rcm_t), etl::alignment_of<rcm_t>::value));
145 unlock();
146
147 if (p != ETL_NULLPTR)
148 {
149 ::new(p) rcm_t(*this);
150 }
151
153
154 return p;
155 }
156
157 //*************************************************************************
159 //*************************************************************************
161 {
162 bool released = false;
163
164 lock();
165 if (memory_block_allocator.is_owner_of(&rcmessage))
166 {
167 rcmessage.~ireference_counted_message();
168 released = memory_block_allocator.release(&rcmessage);
169 }
170 unlock();
171
173 }
174
175#if ETL_USING_CPP11
176 //*****************************************************
177 template <typename TMessage1, typename... TMessages>
178 struct pool_message_parameters
179 {
180 private:
181
182 // Size of the first pool message type.
183 static constexpr size_t size1 = sizeof(etl::reference_counted_message<TMessage1, TCounter>);
184
185 // Maximum size of the the rest of the pool message types.
186 static constexpr size_t size2 = pool_message_parameters<TMessages...>::max_size;
187
188 // Size of the first pool message type.
189 static constexpr size_t alignment1 = etl::alignment_of<etl::reference_counted_message<TMessage1, TCounter>>::value;
190
191 // Maximum size of the the rest of the pool message types.
192 static constexpr size_t alignment2 = pool_message_parameters<TMessages...>::max_alignment;
193
194 public:
195
196 // The maximum size.
197 static constexpr size_t max_size = (size1 < size2) ? size2 : size1;
198
199 // The maximum alignment.
200 static constexpr size_t max_alignment = (alignment1 < alignment2) ? alignment2 : alignment1;
201 };
202
203 //*****************************************************
204 template <typename TMessage1>
205 struct pool_message_parameters<TMessage1>
206 {
207 public:
208
209 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage not derived from etl::imessage");
210
211 // The size of this pool message type.
212 static constexpr size_t max_size = sizeof(etl::reference_counted_message<TMessage1, TCounter>);
213
214 // The maximum alignment.
215 static constexpr size_t max_alignment = etl::alignment_of<etl::reference_counted_message<TMessage1, TCounter>>::value;
216 };
217
218#else
219 template <typename TMessage1, typename TMessage2 = TMessage1, typename TMessage3 = TMessage1, typename TMessage4 = TMessage1,
220 typename TMessage5 = TMessage1, typename TMessage6 = TMessage1, typename TMessage7 = TMessage1, typename TMessage8 = TMessage1>
222 {
223 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage1 not derived from etl::imessage");
224 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage2 not derived from etl::imessage");
225 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage3 not derived from etl::imessage");
226 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage4 not derived from etl::imessage");
227 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage5 not derived from etl::imessage");
228 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage6 not derived from etl::imessage");
229 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage7 not derived from etl::imessage");
230 ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage8 not derived from etl::imessage");
231
232 static ETL_CONSTANT size_t max_size = etl::largest<etl::reference_counted_message<TMessage1, TCounter>,
240
241
242 static ETL_CONSTANT size_t max_alignment = etl::largest<etl::reference_counted_message<TMessage1, TCounter>,
250 };
251
252#endif
253
254 private:
255
257 imemory_block_allocator& memory_block_allocator;
258
259 // Should not be copied.
262 };
263
264#if ETL_USING_CPP11
265
266 template <typename TCounter>
267 template <typename TMessage1, typename... TMessages>
269
270 template <typename TCounter>
271 template <typename TMessage1, typename... TMessages>
272 constexpr size_t reference_counted_message_pool<TCounter>::pool_message_parameters<TMessage1, TMessages...>::max_alignment;
273
274#else
275
276 template <typename TCounter>
277 template <typename TMessage1, typename TMessage2, typename TMessage3, typename TMessage4,
278 typename TMessage5, typename TMessage6, typename TMessage7, typename TMessage8>
279 const size_t reference_counted_message_pool<TCounter>::pool_message_parameters<TMessage1, TMessage2, TMessage3, TMessage4, TMessage5, TMessage6, TMessage7, TMessage8>::max_size;
280
281 template <typename TCounter>
282 template <typename TMessage1, typename TMessage2, typename TMessage3, typename TMessage4,
283 typename TMessage5, typename TMessage6, typename TMessage7, typename TMessage8>
284 const size_t reference_counted_message_pool<TCounter>::pool_message_parameters<TMessage1, TMessage2, TMessage3, TMessage4, TMessage5, TMessage6, TMessage7, TMessage8>::max_alignment;
285
286#endif
287
288#if ETL_USING_CPP11 && ETL_HAS_ATOMIC
289 using atomic_counted_message_pool = reference_counted_message_pool<etl::atomic_int>;
290#endif
291}
292
293#endif
The interface for a memory block pool.
Definition: imemory_block_allocator.h:44
bool release(const void *const p)
Definition: imemory_block_allocator.h:81
bool is_owner_of(const void *const p) const
Definition: imemory_block_allocator.h:103
void * allocate(size_t required_size, size_t required_alignment)
Definition: imemory_block_allocator.h:58
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:84
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:78
A pool for allocating reference counted messages.
Definition: reference_counted_message_pool.h:92
void release(const etl::ireference_counted_message &rcmessage)
Destruct a message and send it back to the allocator.
Definition: reference_counted_message_pool.h:160
reference_counted_message_pool(etl::imemory_block_allocator &memory_block_allocator_)
Constructor.
Definition: reference_counted_message_pool.h:98
etl::reference_counted_message< TMessage, TCounter > * allocate(const TMessage &message)
Allocate a reference counted message from the pool.
Definition: reference_counted_message_pool.h:107
etl::reference_counted_message< TMessage, TCounter > * allocate()
Allocate a reference counted message from the pool.
Definition: reference_counted_message_pool.h:134
Definition: reference_counted_message.h:64
#define ETL_ASSERT(b, e)
Definition: error_handler.h:316
ETL_CONSTEXPR exception(string_type reason_, string_type, numeric_type line_)
Constructor.
Definition: exception.h:69
Definition: exception.h:47
Definition: largest.h:367
add_rvalue_reference
Definition: type_traits_generator.h:1327
is_base_of
Definition: type_traits_generator.h:1252
bitset_ext
Definition: absolute.h:38
size_t max_size() const
Returns the maximum number of items in the variant_pool.
Definition: variant_pool_generator.h:281
Definition: reference_counted_message_pool.h:222