mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Updates to pools and memory allocators
This commit is contained in:
parent
b40349ca9d
commit
db8841ff0d
93
include/etl/file_error_numbers.h
Normal file
93
include/etl/file_error_numbers.h
Normal file
@ -0,0 +1,93 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2020 jwellbelove
|
||||
|
||||
Permission is hereby granted" free of charge" to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software")" to deal
|
||||
in the Software without restriction" including without limitation the rights
|
||||
to use" copy" modify" merge" publish" distribute" sublicense" and / or sell
|
||||
copies of the Software" and to permit persons to whom the Software is
|
||||
furnished to do so" subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS"" WITHOUT WARRANTY OF ANY KIND" EXPRESS OR
|
||||
IMPLIED" INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY"
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM" DAMAGES OR OTHER
|
||||
LIABILITY" WHETHER IN AN ACTION OF CONTRACT" TORT OR OTHERWISE" ARISING FROM"
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_FILE_ERROR_NUMBERS
|
||||
#define ETL_FILE_ERROR_NUMBERS
|
||||
|
||||
#define ETL_DEQUE_ID "1"
|
||||
#define ETL_FLAT_MAP_ID "2"
|
||||
#define ETL_FLAT_MULTIMAP_ID "3"
|
||||
#define ETL_FLAT_MULTISET_ID "4"
|
||||
#define ETL_FLAT_SET_ID "5"
|
||||
#define ETL_FORWARD_LIST_ID "6"
|
||||
#define ETL_LIST_ID "7"
|
||||
#define ETL_MAP_ID "8"
|
||||
#define ETL_MULTIMAP_ID "9"
|
||||
#define ETL_MULTISET_ID "10"
|
||||
#define ETL_POOL_ID "11"
|
||||
#define ETL_PRIORITY_QUEUE_ID "12"
|
||||
#define ETL_QUEUE_ID "13"
|
||||
#define ETL_SET_ID "14"
|
||||
#define ETL_STACK_ID "15"
|
||||
#define ETL_UNORDERED_MAP_ID "16"
|
||||
#define ETL_VECTOR_ID "17"
|
||||
#define ETL_OBSERVER_ID "18"
|
||||
#define ETL_IHASH_ID "19"
|
||||
#define ETL_INTRUSIVE_FORWARD_LIST_ID "20"
|
||||
#define ETL_INTRUSIVE_LIST_ID "21"
|
||||
#define ETL_INTRUSIVE_LINKS_ID "22"
|
||||
#define ETL_UNORDERED_SET_ID "23"
|
||||
#define ETL_VARIANT_ID "24"
|
||||
#define ETL_UNORDERED_MULTIMAP_ID "25"
|
||||
#define ETL_UNORDERED_MULTISET_ID "26"
|
||||
#define ETL_BASIC_STRING_ID "27"
|
||||
#define ETL_INTRUSIVE_STACK_ID "28"
|
||||
#define ETL_INTRUSIVE_QUEUE_ID "29"
|
||||
#define ETL_REFERENCE_FLAT_MAP_ID "30"
|
||||
#define ETL_REFERENCE_FLAT_MULTIMAP_ID "31"
|
||||
#define ETL_REFERENCE_FLAT_SET_ID "32"
|
||||
#define ETL_REFERENCE_FLAT_MULTISET_ID "33"
|
||||
#define ETL_FSM_ID "34"
|
||||
#define ETL_MESSAGE_ROUTER_ID "35"
|
||||
#define ETL_SCHEDULER_ID "36"
|
||||
#define ETL_TASK_ID "37"
|
||||
#define ETL_MESSAGE_ID "38"
|
||||
#define ETL_MESSAGE_BUS_ID "39"
|
||||
#define ETL_VARIANT_POOL_ID "40"
|
||||
#define ETL_ARRAY_VIEW_ID "41"
|
||||
#define ETL_STRING_VIEW_ID "42"
|
||||
#define ETL_CALLBACK_TIMER_ID "43"
|
||||
#define ETL_MESSAGE_TIMER_ID "44"
|
||||
#define ETL_TYPE_LOOKUP_ID "45"
|
||||
#define ETL_QUEUE_SPSC_ISR_ID "46"
|
||||
#define ETL_QUEUE_SPSC_ATOMIC_ID "47"
|
||||
#define ETL_QUEUE_MPMC_MUTEX_ID "48"
|
||||
#define ETL_TYPE_SELECT_ID "49"
|
||||
#define ETL_BINARY_ID "50"
|
||||
#define ETL_DELEGATE_ID "51"
|
||||
#define ETL_BITSET_ID "52"
|
||||
#define ETL_INDIRECT_VECTOR_ID "53"
|
||||
#define ETL_QUEUE_SPSC_LOCKED_ID "54"
|
||||
#define ETL_MESSAGE_PACKET_ID "55"
|
||||
#define ETL_CIRCULAR_BUFFER_ID "56"
|
||||
#define ETL_MULTI_LOOP_ID "57"
|
||||
#define ETL_REFERENCE_COUNTER_MESSAGE_POOL_ID "58"
|
||||
|
||||
#endif
|
||||
@ -1,57 +0,0 @@
|
||||
1 deque
|
||||
2 flat_map
|
||||
3 flat_multimap
|
||||
4 flat_multiset
|
||||
5 flat_set
|
||||
6 forward_list
|
||||
7 list
|
||||
8 map
|
||||
9 multimap
|
||||
10 multiset
|
||||
11 pool
|
||||
12 priority_queue
|
||||
13 queue
|
||||
14 set
|
||||
15 stack
|
||||
16 unordered_map
|
||||
17 vector
|
||||
18 observer
|
||||
19 ihash
|
||||
20 intrusive_forward_list
|
||||
21 intrusive_list
|
||||
22 intrusive_links
|
||||
23 unordered_set
|
||||
24 variant
|
||||
25 unordered_multimap
|
||||
26 unordered_multiset
|
||||
27 basic_string
|
||||
28 intrusive_stack
|
||||
29 intrusive_queue
|
||||
30 reference_flat_map
|
||||
31 reference_flat_multimap
|
||||
32 reference_flat_set
|
||||
33 reference_flat_multiset
|
||||
34 fsm
|
||||
35 message_router
|
||||
36 scheduler
|
||||
37 task
|
||||
38 message
|
||||
39 message_bus
|
||||
40 factory / variant_pool
|
||||
41 array_view
|
||||
42 string_view
|
||||
43 callback_timer
|
||||
44 message_timer
|
||||
45 type_lookup
|
||||
46 queue_spsc_isr
|
||||
47 queue_spsc_atomic
|
||||
48 queue_mpmc_mutex
|
||||
49 type_select
|
||||
50 binary
|
||||
51 delegate
|
||||
52 bitset
|
||||
53 indirect_vector
|
||||
54 queue_spsc_locked
|
||||
55 message_packet
|
||||
56 multi_range
|
||||
57 reference_counted_message_pool
|
||||
113
include/etl/fixed_sized_memory_block_allocator.h
Normal file
113
include/etl/fixed_sized_memory_block_allocator.h
Normal file
@ -0,0 +1,113 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_FIXED_MEMORY_BLOCK_POOL_INCLUDED
|
||||
#define ETL_FIXED_MEMORY_BLOCK_POOL_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "memory.h"
|
||||
#include "generic_pool.h"
|
||||
#include "alignment.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//*************************************************************************
|
||||
/// The fixed sized memory block pool.
|
||||
/// The allocated memory blocks are all the same size.
|
||||
//*************************************************************************
|
||||
template <size_t Block_Size, size_t Alignment, size_t Size>
|
||||
class fixed_sized_memory_block_allocator : public imemory_block_allocator
|
||||
{
|
||||
public:
|
||||
|
||||
//*************************************************************************
|
||||
/// Default contsrcutor
|
||||
//*************************************************************************
|
||||
fixed_sized_memory_block_allocator()
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Construct with a successor allocator.
|
||||
//*************************************************************************
|
||||
fixed_sized_memory_block_allocator(etl::imemory_block_allocator& successor)
|
||||
: imemory_block_allocator(successor)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// A structure that has the size Block_Size.
|
||||
struct block
|
||||
{
|
||||
char data[Block_Size];
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// The overridden virtual function to allocate a block.
|
||||
//*************************************************************************
|
||||
virtual void* allocate_block(size_t required_size) ETL_OVERRIDE
|
||||
{
|
||||
if (required_size <= Block_Size)
|
||||
{
|
||||
return pool.allocate<block>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return ETL_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// The overridden virtual function to release a block.
|
||||
//*************************************************************************
|
||||
virtual bool release_block(const void* const pblock) ETL_OVERRIDE
|
||||
{
|
||||
if (pool.is_in_pool(pblock))
|
||||
{
|
||||
pool.release(static_cast<const block* const>(pblock));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// The generic pool from which allocate memory blocks.
|
||||
etl::generic_pool<Block_Size, Alignment, Size> pool;
|
||||
|
||||
// No copying allowed.
|
||||
fixed_sized_memory_block_allocator(const etl::fixed_sized_memory_block_allocator<Block_Size, Alignment, Size>&) ETL_DELETE;
|
||||
fixed_sized_memory_block_allocator& operator =(const etl::fixed_sized_memory_block_allocator<Block_Size, Alignment, Size>&) ETL_DELETE;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,65 +0,0 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_FIXED_MEMORY_BLOCK_POOL_INCLUDED
|
||||
#define ETL_FIXED_MEMORY_BLOCK_POOL_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "memory.h"
|
||||
#include "pool.h"
|
||||
#include "alignment.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//*************************************************************************
|
||||
/// The fixed sized memory block pool.
|
||||
/// The allocated memory blocks are all the same size.
|
||||
//*************************************************************************
|
||||
template <size_t BLOCK_SIZE, size_t ALIGNMENT, size_t SIZE>
|
||||
struct fixed_sized_memory_block_pool : public etl::ipool
|
||||
{
|
||||
public:
|
||||
|
||||
fixed_sized_memory_block_pool()
|
||||
: ipool(buffer.get_address<char>(), BLOCK_SIZE, SIZE)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// No copying allowed.
|
||||
fixed_sized_memory_block_pool(const etl::fixed_sized_memory_block_pool<BLOCK_SIZE, ALIGNMENT, SIZE>&) ETL_DELETE;
|
||||
fixed_sized_memory_block_pool& operator =(const etl::fixed_sized_memory_block_pool<BLOCK_SIZE, ALIGNMENT, SIZE>&) ETL_DELETE;
|
||||
|
||||
typename etl::aligned_storage<SIZE * BLOCK_SIZE, ALIGNMENT>::type buffer;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -129,6 +129,7 @@ namespace etl
|
||||
virtual bool is_producer() const = 0;
|
||||
virtual bool is_consumer() const = 0;
|
||||
|
||||
//********************************************
|
||||
virtual void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message)
|
||||
{
|
||||
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
|
||||
|
||||
@ -51,20 +51,20 @@ namespace etl
|
||||
/// A templated abstract pool implementation that uses a fixed size pool.
|
||||
///\ingroup pool
|
||||
//*************************************************************************
|
||||
template <const size_t TYPE_SIZE_, const size_t ALIGNMENT_, const size_t SIZE_>
|
||||
template <const size_t VTypeSize, const size_t VAlignment, const size_t VSize>
|
||||
class generic_pool : public etl::ipool
|
||||
{
|
||||
public:
|
||||
|
||||
static const size_t SIZE = SIZE_;
|
||||
static const size_t ALIGNMENT = ALIGNMENT_;
|
||||
static const size_t TYPE_SIZE = TYPE_SIZE_;
|
||||
static ETL_CONSTANT size_t SIZE = VSize;
|
||||
static ETL_CONSTANT size_t ALIGNMENT = VAlignment;
|
||||
static ETL_CONSTANT size_t TYPE_SIZE = VTypeSize;
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
//*************************************************************************
|
||||
generic_pool()
|
||||
: etl::ipool(reinterpret_cast<char*>(&buffer[0]), ELEMENT_SIZE, SIZE)
|
||||
: etl::ipool(reinterpret_cast<char*>(&buffer[0]), Element_Size, VSize)
|
||||
{
|
||||
}
|
||||
|
||||
@ -77,12 +77,12 @@ namespace etl
|
||||
template <typename U>
|
||||
U* allocate()
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= VAlignment, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= VTypeSize, "Type too large for pool");
|
||||
return ipool::allocate<U>();
|
||||
}
|
||||
|
||||
#if !ETL_CPP11_SUPPORTED || ETL_POOL_CPP03_CODE || defined(ETL_STLPORT)
|
||||
#if ETL_CPP11_NOT_SUPPORTED || ETL_POOL_CPP03_CODE || ETL_USING_STLPORT
|
||||
//*************************************************************************
|
||||
/// Allocate storage for an object from the pool and create with default.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
@ -91,8 +91,8 @@ namespace etl
|
||||
template <typename U>
|
||||
U* create()
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= VAlignment, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= VTypeSize, "Type too large for pool");
|
||||
return ipool::create<U>();
|
||||
}
|
||||
|
||||
@ -104,8 +104,8 @@ namespace etl
|
||||
template <typename U, typename T1>
|
||||
U* create(const T1& value1)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= VAlignment, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= VTypeSize, "Type too large for pool");
|
||||
return ipool::create<U>(value1);
|
||||
}
|
||||
|
||||
@ -117,8 +117,8 @@ namespace etl
|
||||
template <typename U, typename T1, typename T2>
|
||||
U* create(const T1& value1, const T2& value2)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= VAlignment, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= VTypeSize, "Type too large for pool");
|
||||
return ipool::create<U>(value1, value2);
|
||||
}
|
||||
|
||||
@ -130,8 +130,8 @@ namespace etl
|
||||
template <typename U, typename T1, typename T2, typename T3>
|
||||
U* create(const T1& value1, const T2& value2, const T3& value3)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= VAlignment, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= VTypeSize, "Type too large for pool");
|
||||
return ipool::create<U>(value1, value2, value3);
|
||||
}
|
||||
|
||||
@ -143,8 +143,8 @@ namespace etl
|
||||
template <typename U, typename T1, typename T2, typename T3, typename T4>
|
||||
U* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= VAlignment, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= VTypeSize, "Type too large for pool");
|
||||
return ipool::create<U>(value1, value2, value3, value4);
|
||||
}
|
||||
#else
|
||||
@ -154,34 +154,24 @@ namespace etl
|
||||
template <typename U, typename... Args>
|
||||
U* create(Args&&... args)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= VAlignment, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= VTypeSize, "Type too large for pool");
|
||||
return ipool::create<U>(etl::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Releases the object.
|
||||
/// \param p_object A pointer to the object to be destroyed.
|
||||
//*************************************************************************
|
||||
template <typename U>
|
||||
void release(const U* const p_object)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
ipool::release(p_object);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Destroys the object.
|
||||
/// Undefined behaviour if the pool does not contain a 'U'.
|
||||
/// \param p_object A pointer to the object to be destroyed.
|
||||
//*************************************************************************
|
||||
template <typename U>
|
||||
void destroy(const U* const p_object)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
ipool::destroy(p_object);
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= VAlignment, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= VTypeSize, "Type too large for pool");
|
||||
p_object->~U();
|
||||
ipool::release(p_object);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -189,20 +179,22 @@ namespace etl
|
||||
// The pool element.
|
||||
union Element
|
||||
{
|
||||
char* next; ///< Pointer to the next free element.
|
||||
char value[TYPE_SIZE_]; ///< Storage for value type.
|
||||
typename etl::type_with_alignment<ALIGNMENT_>::type dummy; ///< Dummy item to get correct alignment.
|
||||
char* next; ///< Pointer to the next free element.
|
||||
char value[VTypeSize]; ///< Storage for value type.
|
||||
typename etl::type_with_alignment<VAlignment>::type dummy; ///< Dummy item to get correct alignment.
|
||||
};
|
||||
|
||||
///< The memory for the pool of objects.
|
||||
typename etl::aligned_storage<sizeof(Element), etl::alignment_of<Element>::value>::type buffer[SIZE];
|
||||
typename etl::aligned_storage<sizeof(Element), etl::alignment_of<Element>::value>::type buffer[VSize];
|
||||
|
||||
static ETL_CONSTANT uint32_t ELEMENT_SIZE = sizeof(Element);
|
||||
static const uint32_t Element_Size = sizeof(Element);
|
||||
|
||||
// Should not be copied.
|
||||
generic_pool(const generic_pool&) ETL_DELETE;
|
||||
generic_pool& operator =(const generic_pool&) ETL_DELETE;
|
||||
generic_pool(const generic_pool&);
|
||||
generic_pool& operator =(const generic_pool&);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -37,20 +37,13 @@ SOFTWARE.
|
||||
#include "static_assert.h"
|
||||
#include "utility.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include <new>
|
||||
#include "placement_new.h"
|
||||
|
||||
#undef ETL_FILE
|
||||
#define ETL_FILE "11"
|
||||
#define ETL_FILE ETL_POOL_ID
|
||||
|
||||
#define ETL_POOL_CPP03_CODE 0
|
||||
|
||||
//*****************************************************************************
|
||||
///\defgroup pool pool
|
||||
/// A fixed capacity pool.
|
||||
///\ingroup containers
|
||||
//*****************************************************************************
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
@ -106,39 +99,14 @@ namespace etl
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// The base implementation of a pool.
|
||||
/// Implements the imemory_block_pool interface.
|
||||
///\ingroup pool
|
||||
//***************************************************************************
|
||||
class ipool : public imemory_block_pool
|
||||
class ipool
|
||||
{
|
||||
public:
|
||||
|
||||
typedef size_t size_type;
|
||||
|
||||
//*************************************************************************
|
||||
/// Implementation of the low level imemory_block_pool interface.
|
||||
//*************************************************************************
|
||||
void* allocate_memory_block(size_t require_size) ETL_OVERRIDE
|
||||
{
|
||||
return allocate<void*>();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Implementation of the low level imemory_block_pool interface.
|
||||
//*************************************************************************
|
||||
void release_memory_block(const void* const ptr) ETL_OVERRIDE
|
||||
{
|
||||
release(ptr);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Implementation of the low level imemory_block_pool interface.
|
||||
//*************************************************************************
|
||||
size_t get_memory_block_size() ETL_OVERRIDE
|
||||
{
|
||||
return ITEM_SIZE;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate storage for an object from the pool.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
@ -147,7 +115,7 @@ namespace etl
|
||||
template <typename T>
|
||||
T* allocate()
|
||||
{
|
||||
if (sizeof(T) > ITEM_SIZE)
|
||||
if (sizeof(T) > Item_Size)
|
||||
{
|
||||
ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size));
|
||||
}
|
||||
@ -155,7 +123,7 @@ namespace etl
|
||||
return reinterpret_cast<T*>(allocate_item());
|
||||
}
|
||||
|
||||
#if !ETL_CPP11_SUPPORTED || ETL_POOL_CPP03_CODE || defined(ETL_STLPORT)
|
||||
#if ETL_CPP11_NOT_SUPPORTED || ETL_POOL_CPP03_CODE || ETL_USING_STLPORT
|
||||
//*************************************************************************
|
||||
/// Allocate storage for an object from the pool and create default.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
@ -250,24 +218,19 @@ namespace etl
|
||||
|
||||
//*************************************************************************
|
||||
/// Destroys the object.
|
||||
/// If asserts or exceptions are enabled and the object does not belong to this
|
||||
/// pool then an etl::pool_object_not_in_pool is thrown.
|
||||
/// Undefined behaviour if p_object is not a 'T' or derived from 'T'.
|
||||
/// Undefined behaviour if the pool does not contain a 'T'.
|
||||
/// \param p_object A pointer to the object to be destroyed.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
void destroy(const T* const p_object)
|
||||
{
|
||||
// Does it belong to us?
|
||||
if (is_in_pool(p_object))
|
||||
if (sizeof(T) > Item_Size)
|
||||
{
|
||||
p_object->~T();
|
||||
release_item((char*)p_object);
|
||||
}
|
||||
else
|
||||
{
|
||||
ETL_ALWAYS_ASSERT(ETL_ERROR(pool_object_not_in_pool));
|
||||
ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size));
|
||||
}
|
||||
|
||||
p_object->~T();
|
||||
release(p_object);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -278,15 +241,8 @@ namespace etl
|
||||
//*************************************************************************
|
||||
void release(const void* const p_object)
|
||||
{
|
||||
// Does it belong to us?
|
||||
if (is_in_pool(p_object))
|
||||
{
|
||||
release_item((char*)p_object);
|
||||
}
|
||||
else
|
||||
{
|
||||
ETL_ALWAYS_ASSERT(ETL_ERROR(pool_object_not_in_pool));
|
||||
}
|
||||
const uintptr_t p = uintptr_t(p_object);
|
||||
release_item((char*)p);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -294,9 +250,9 @@ namespace etl
|
||||
//*************************************************************************
|
||||
void release_all()
|
||||
{
|
||||
items_allocated = 0;
|
||||
items_allocated = 0;
|
||||
items_initialised = 0;
|
||||
p_next = p_buffer;
|
||||
p_next = p_buffer;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -304,9 +260,10 @@ namespace etl
|
||||
/// \param p_object A pointer to the object to be checked.
|
||||
/// \return <b>true<\b> if it does, otherwise <b>false</b>
|
||||
//*************************************************************************
|
||||
bool is_in_pool(const void* p_object) const
|
||||
bool is_in_pool(const void* const p_object) const
|
||||
{
|
||||
return is_item_in_pool((const char*)p_object);
|
||||
const uintptr_t p = uintptr_t(p_object);
|
||||
return is_item_in_pool((const char*)p);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -314,7 +271,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
size_t max_size() const
|
||||
{
|
||||
return MAX_SIZE;
|
||||
return Max_Size;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -322,7 +279,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
size_t capacity() const
|
||||
{
|
||||
return MAX_SIZE;
|
||||
return Max_Size;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -330,7 +287,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
size_t available() const
|
||||
{
|
||||
return MAX_SIZE - items_allocated;
|
||||
return Max_Size - items_allocated;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -356,7 +313,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
bool full() const
|
||||
{
|
||||
return items_allocated == MAX_SIZE;
|
||||
return items_allocated == Max_Size;
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -366,11 +323,11 @@ namespace etl
|
||||
//*************************************************************************
|
||||
ipool(char* p_buffer_, uint32_t item_size_, uint32_t max_size_)
|
||||
: p_buffer(p_buffer_),
|
||||
p_next(p_buffer_),
|
||||
items_allocated(0),
|
||||
items_initialised(0),
|
||||
ITEM_SIZE(item_size_),
|
||||
MAX_SIZE(max_size_)
|
||||
p_next(p_buffer_),
|
||||
items_allocated(0),
|
||||
items_initialised(0),
|
||||
Item_Size(item_size_),
|
||||
Max_Size(max_size_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -384,13 +341,13 @@ namespace etl
|
||||
char* p_value = ETL_NULLPTR;
|
||||
|
||||
// Any free space left?
|
||||
if (items_allocated < MAX_SIZE)
|
||||
if (items_allocated < Max_Size)
|
||||
{
|
||||
// Initialise another one if necessary.
|
||||
if (items_initialised < MAX_SIZE)
|
||||
if (items_initialised < Max_Size)
|
||||
{
|
||||
char* p = p_buffer + (items_initialised * ITEM_SIZE);
|
||||
char* np = p + ITEM_SIZE;
|
||||
char* p = p_buffer + (items_initialised * Item_Size);
|
||||
char* np = p + Item_Size;
|
||||
*reinterpret_cast<char**>(p) = np;
|
||||
++items_initialised;
|
||||
}
|
||||
@ -399,7 +356,7 @@ namespace etl
|
||||
p_value = p_next;
|
||||
|
||||
++items_allocated;
|
||||
if (items_allocated != MAX_SIZE)
|
||||
if (items_allocated != Max_Size)
|
||||
{
|
||||
// Set up the pointer to the next free item
|
||||
p_next = *reinterpret_cast<char**>(p_next);
|
||||
@ -423,6 +380,9 @@ namespace etl
|
||||
//*************************************************************************
|
||||
void release_item(char* p_value)
|
||||
{
|
||||
// Does it belong to us?
|
||||
ETL_ASSERT(is_item_in_pool(p_value), ETL_ERROR(pool_object_not_in_pool));
|
||||
|
||||
if (p_next != ETL_NULLPTR)
|
||||
{
|
||||
// Point it to the current free item.
|
||||
@ -446,12 +406,12 @@ namespace etl
|
||||
{
|
||||
// Within the range of the buffer?
|
||||
intptr_t distance = p - p_buffer;
|
||||
bool is_within_range = (distance >= 0) && (distance <= intptr_t((ITEM_SIZE * MAX_SIZE) - ITEM_SIZE));
|
||||
bool is_within_range = (distance >= 0) && (distance <= intptr_t((Item_Size * Max_Size) - Item_Size));
|
||||
|
||||
// Modulus and division can be slow on some architectures, so only do this in debug.
|
||||
#if defined(ETL_DEBUG)
|
||||
// Is the address on a valid object boundary?
|
||||
bool is_valid_address = ((distance % ITEM_SIZE) == 0);
|
||||
bool is_valid_address = ((distance % Item_Size) == 0);
|
||||
#else
|
||||
bool is_valid_address = true;
|
||||
#endif
|
||||
@ -469,8 +429,8 @@ namespace etl
|
||||
uint32_t items_allocated; ///< The number of items allocated.
|
||||
uint32_t items_initialised; ///< The number of items initialised.
|
||||
|
||||
const uint32_t ITEM_SIZE; ///< The size of allocated items.
|
||||
const uint32_t MAX_SIZE; ///< The maximum number of objects that can be allocated.
|
||||
const uint32_t Item_Size; ///< The size of allocated items.
|
||||
const uint32_t Max_Size; ///< The maximum number of objects that can be allocated.
|
||||
|
||||
//*************************************************************************
|
||||
/// Destructor.
|
||||
|
||||
@ -35,7 +35,7 @@ SOFTWARE.
|
||||
|
||||
namespace etl
|
||||
{
|
||||
class ireference_counted_message;
|
||||
class ipool_message;
|
||||
|
||||
//***************************************************************************
|
||||
/// Interface for a reference counted message pool.
|
||||
@ -44,8 +44,8 @@ namespace etl
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void release(const etl::ireference_counted_message* const pmsg) = 0;
|
||||
virtual void release(const etl::ireference_counted_message& msg) = 0;
|
||||
virtual ~ireference_counted_message_pool() {}
|
||||
virtual void release(const etl::ipool_message& msg) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -48,6 +48,7 @@ SOFTWARE.
|
||||
#include "memory.h"
|
||||
#include "iterator.h"
|
||||
#include "static_assert.h"
|
||||
#include "parameter_type.h"
|
||||
#include "placement_new.h"
|
||||
|
||||
#if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
|
||||
|
||||
@ -1900,34 +1900,124 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
//*****************************************************************************
|
||||
/// The interface for a memory block pool.
|
||||
//*************************************************************************
|
||||
struct imemory_block_pool
|
||||
//*****************************************************************************
|
||||
class imemory_block_allocator
|
||||
{
|
||||
virtual void* allocate_memory_block(size_t required_size) = 0;
|
||||
virtual void release_memory_block(const void* const) = 0;
|
||||
virtual size_t get_memory_block_size() const = 0;
|
||||
public:
|
||||
|
||||
//*****************************************************************************
|
||||
/// Default constructor.
|
||||
//*****************************************************************************
|
||||
imemory_block_allocator()
|
||||
: p_successor(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Construct with a successor.
|
||||
//*****************************************************************************
|
||||
explicit imemory_block_allocator(imemory_block_allocator& successor)
|
||||
: p_successor(&successor)
|
||||
{
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Try to allocate a memory block of the required size.
|
||||
/// If this allocator cannot, then pass the request on the the successor, if configured.
|
||||
//*****************************************************************************
|
||||
void* allocate(size_t required_size)
|
||||
{
|
||||
// Call the derived implementation.
|
||||
void* p = allocate_block(required_size);
|
||||
|
||||
// If that failed...
|
||||
if (p == ETL_NULLPTR)
|
||||
{
|
||||
/// ...and we have a successor...
|
||||
if (has_successor())
|
||||
{
|
||||
// Try to allocate from the next one in the chain.
|
||||
return get_successor().allocate(required_size);
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Try to release a memory block of the required size.
|
||||
/// If this allocator cannot, then pass the request on the the successor, if configured.
|
||||
//*****************************************************************************
|
||||
bool release(const void* const p)
|
||||
{
|
||||
// Call the derived implementation to try to release.
|
||||
if (!release_block(p))
|
||||
{
|
||||
// If it failed and we have a successor...
|
||||
if (has_successor())
|
||||
{
|
||||
// Try to release from the next one in the chain.
|
||||
return get_successor().release(p);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Set the sucessor allocator.
|
||||
//*****************************************************************************
|
||||
void set_successor(etl::imemory_block_allocator& successor)
|
||||
{
|
||||
p_successor = &successor;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Get the sucessor allocator.
|
||||
//*****************************************************************************
|
||||
etl::imemory_block_allocator& get_successor() const
|
||||
{
|
||||
return *p_successor;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Do we have a successor allocator.
|
||||
//*****************************************************************************
|
||||
bool has_successor() const
|
||||
{
|
||||
return (p_successor != ETL_NULLPTR);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void* allocate_block(size_t required_size) = 0;
|
||||
virtual bool release_block(const void* const) = 0;
|
||||
|
||||
private:
|
||||
|
||||
etl::imemory_block_allocator* p_successor;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Declares an aligned buffer of N_OBJECTS x of size OBJECT_SIZE at alignment ALIGNMENT.
|
||||
/// Declares an aligned buffer of N_Objects x of size Object_Size at alignment Alignment.
|
||||
///\ingroup alignment
|
||||
//***************************************************************************
|
||||
template <size_t OBJECT_SIZE_, size_t N_OBJECTS_, size_t ALIGNMENT_>
|
||||
template <size_t VObject_Size, size_t VN_Objects, size_t VAlignment>
|
||||
class uninitialized_buffer
|
||||
{
|
||||
public:
|
||||
|
||||
static ETL_CONSTANT size_t OBJECT_SIZE = OBJECT_SIZE_;
|
||||
static ETL_CONSTANT size_t N_OBJECTS = N_OBJECTS_;
|
||||
static ETL_CONSTANT size_t ALIGNMENT = ALIGNMENT_;
|
||||
static ETL_CONSTANT size_t Object_Size = VObject_Size;
|
||||
static ETL_CONSTANT size_t N_Objects = VN_Objects;
|
||||
static ETL_CONSTANT size_t Alignment = VAlignment;
|
||||
|
||||
/// Convert to T reference.
|
||||
template <typename T>
|
||||
operator T& ()
|
||||
{
|
||||
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
|
||||
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
|
||||
return *reinterpret_cast<T*>(raw);
|
||||
}
|
||||
|
||||
@ -1935,7 +2025,7 @@ namespace etl
|
||||
template <typename T>
|
||||
operator const T& () const
|
||||
{
|
||||
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
|
||||
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
|
||||
return *reinterpret_cast<const T*>(raw);
|
||||
}
|
||||
|
||||
@ -1943,7 +2033,7 @@ namespace etl
|
||||
template <typename T>
|
||||
operator T* ()
|
||||
{
|
||||
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
|
||||
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
|
||||
return reinterpret_cast<T*>(raw);
|
||||
}
|
||||
|
||||
@ -1951,26 +2041,26 @@ namespace etl
|
||||
template <typename T>
|
||||
operator const T* () const
|
||||
{
|
||||
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
|
||||
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
|
||||
return reinterpret_cast<const T*>(raw);
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED && !defined(ETL_COMPILER_ARM5) && !defined(ETL_UNINITIALIZED_BUFFER_FORCE_CPP03)
|
||||
alignas(ALIGNMENT) char raw[OBJECT_SIZE * N_OBJECTS];
|
||||
alignas(VAlignment) char raw[Object_Size * N_Objects];
|
||||
#else
|
||||
union
|
||||
{
|
||||
char raw[OBJECT_SIZE * N_OBJECTS];
|
||||
typename etl::type_with_alignment<ALIGNMENT>::type etl_alignment_type; // A POD type that has the same alignment as ALIGNMENT.
|
||||
char raw[VObject_Size * VN_Objects];
|
||||
typename etl::type_with_alignment<Alignment>::type etl_alignment_type; // A POD type that has the same alignment as VAlignment.
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Declares an aligned buffer of N_OBJECTS as if they were type T.
|
||||
/// Declares an aligned buffer of VN_Objects as if they were type T.
|
||||
///\ingroup alignment
|
||||
//***************************************************************************
|
||||
template <typename T, size_t N_OBJECTS_>
|
||||
template <typename T, size_t VN_Objects>
|
||||
class uninitialized_buffer_of
|
||||
{
|
||||
public:
|
||||
@ -1983,9 +2073,9 @@ namespace etl
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
|
||||
static ETL_CONSTANT size_t OBJECT_SIZE = sizeof(T);
|
||||
static ETL_CONSTANT size_t N_OBJECTS = N_OBJECTS_;
|
||||
static ETL_CONSTANT size_t ALIGNMENT = etl::alignment_of<T>::value;
|
||||
static ETL_CONSTANT size_t Object_Size = sizeof(T);
|
||||
static ETL_CONSTANT size_t N_Objects = VN_Objects;
|
||||
static ETL_CONSTANT size_t Alignment = etl::alignment_of<T>::value;
|
||||
|
||||
/// Index operator.
|
||||
T& operator [](int i)
|
||||
@ -2036,28 +2126,28 @@ namespace etl
|
||||
|
||||
T* end()
|
||||
{
|
||||
return reinterpret_cast<const T*>(raw + (sizeof(T) * N_OBJECTS));
|
||||
return reinterpret_cast<const T*>(raw + (sizeof(T) * N_Objects));
|
||||
}
|
||||
|
||||
const T* end() const
|
||||
{
|
||||
return reinterpret_cast<const T*>(raw + (sizeof(T) * N_OBJECTS));
|
||||
return reinterpret_cast<const T*>(raw + (sizeof(T) * N_Objects));
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED && !defined(ETL_COMPILER_ARM5) && !defined(ETL_UNINITIALIZED_BUFFER_FORCE_CPP03)
|
||||
alignas(ALIGNMENT) char raw[sizeof(T) * N_OBJECTS];
|
||||
alignas(Alignment) char raw[sizeof(T) * N_Objects];
|
||||
#else
|
||||
union
|
||||
{
|
||||
char raw[sizeof(T) * N_OBJECTS];
|
||||
typename etl::type_with_alignment<ALIGNMENT>::type etl_alignment_type; // A POD type that has the same alignment as ALIGNMENT.
|
||||
char raw[sizeof(T) * N_Objects];
|
||||
typename etl::type_with_alignment<Alignment>::type etl_alignment_type; // A POD type that has the same alignment as Alignment.
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
#if ETL_CPP14_SUPPORTED
|
||||
template <typename T, size_t N_OBJECTS>
|
||||
using uninitialized_buffer_of_v = typename uninitialized_buffer_of<T, N_OBJECTS>::buffer;
|
||||
template <typename T, size_t N_Objects>
|
||||
using uninitialized_buffer_of_v = typename uninitialized_buffer_of<T, N_Objects>::buffer;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -162,10 +162,82 @@ namespace etl
|
||||
receive(source, etl::imessage_router::ALL_MESSAGE_ROUTERS, message);
|
||||
}
|
||||
|
||||
//********************************************
|
||||
virtual void receive(etl::imessage_router& source,
|
||||
etl::message_router_id_t destination_router_id,
|
||||
etl::shared_message shared_msg) ETL_OVERRIDE
|
||||
{
|
||||
switch (destination_router_id)
|
||||
{
|
||||
//*****************************
|
||||
// Broadcast to all routers.
|
||||
case etl::imessage_router::ALL_MESSAGE_ROUTERS:
|
||||
{
|
||||
router_list_t::iterator irouter = router_list.begin();
|
||||
|
||||
// Broadcast to everyone.
|
||||
while (irouter != router_list.end())
|
||||
{
|
||||
etl::imessage_router& router = **irouter;
|
||||
|
||||
if (router.accepts(shared_msg.get_message().get_message_id()))
|
||||
{
|
||||
router.receive(source, shared_msg);
|
||||
}
|
||||
|
||||
++irouter;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//*****************************
|
||||
// Must be an addressed message.
|
||||
default:
|
||||
{
|
||||
router_list_t::iterator irouter = router_list.begin();
|
||||
|
||||
// Find routers with the id.
|
||||
ETL_OR_STD::pair<router_list_t::iterator, router_list_t::iterator> range = etl::equal_range(router_list.begin(),
|
||||
router_list.end(),
|
||||
destination_router_id,
|
||||
compare_router_id());
|
||||
|
||||
// Call all of them.
|
||||
while (range.first != range.second)
|
||||
{
|
||||
if ((*(range.first))->accepts(shared_msg.get_message().get_message_id()))
|
||||
{
|
||||
(*(range.first))->receive(source, shared_msg);
|
||||
}
|
||||
|
||||
++range.first;
|
||||
}
|
||||
|
||||
// Do any message buses.
|
||||
// These are always at the end of the list.
|
||||
irouter = etl::lower_bound(router_list.begin(),
|
||||
router_list.end(),
|
||||
etl::imessage_bus::MESSAGE_BUS,
|
||||
compare_router_id());
|
||||
|
||||
while (irouter != router_list.end())
|
||||
{
|
||||
// So pass it on.
|
||||
(*irouter)->receive(source, destination_router_id, shared_msg);
|
||||
|
||||
++irouter;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
void receive(etl::imessage_router& source,
|
||||
etl::message_router_id_t destination_router_id,
|
||||
const etl::imessage& message) ETL_OVERRIDE
|
||||
virtual void receive(etl::imessage_router& source,
|
||||
etl::message_router_id_t destination_router_id,
|
||||
const etl::imessage& message) ETL_OVERRIDE
|
||||
{
|
||||
switch (destination_router_id)
|
||||
{
|
||||
|
||||
@ -117,6 +117,7 @@ namespace etl
|
||||
virtual bool is_producer() const = 0;
|
||||
virtual bool is_consumer() const = 0;
|
||||
|
||||
//********************************************
|
||||
virtual void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message)
|
||||
{
|
||||
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
|
||||
@ -144,7 +145,7 @@ namespace etl
|
||||
}
|
||||
|
||||
//********************************************
|
||||
void receive(imessage_router& source, etl::message_router_id_t destination_router_id, etl::shared_message shared_msg)
|
||||
virtual void receive(imessage_router& source, etl::message_router_id_t destination_router_id, etl::shared_message shared_msg)
|
||||
{
|
||||
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
|
||||
{
|
||||
@ -152,6 +153,12 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************
|
||||
void receive(etl::message_router_id_t destination_router_id, etl::shared_message shared_msg)
|
||||
{
|
||||
receive(etl::get_null_message_router(), destination_router_id, shared_msg);
|
||||
}
|
||||
|
||||
//********************************************
|
||||
bool accepts(const etl::imessage& msg) const
|
||||
{
|
||||
|
||||
@ -34,6 +34,8 @@ SOFTWARE.
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "file_error_numbers.h"
|
||||
|
||||
// Define a debug macro
|
||||
#if (defined(_DEBUG) || defined(DEBUG)) && !defined(ETL_DEBUG)
|
||||
#define ETL_DEBUG
|
||||
|
||||
@ -32,22 +32,8 @@ SOFTWARE.
|
||||
#define ETL_POOL_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "algorithm.h"
|
||||
#include "iterator.h"
|
||||
#include "utility.h"
|
||||
#include "error_handler.h"
|
||||
#include "alignment.h"
|
||||
#include "array.h"
|
||||
#include "container.h"
|
||||
#include "integral_limits.h"
|
||||
#include "nullptr.h"
|
||||
#include "alignment.h"
|
||||
#include "static_assert.h"
|
||||
#include "algorithm.h"
|
||||
#include "placement_new.h"
|
||||
|
||||
#undef ETL_FILE
|
||||
#define ETL_FILE "11"
|
||||
#include "ipool.h"
|
||||
#include "generic_pool.h"
|
||||
|
||||
#define ETL_POOL_CPP03_CODE 0
|
||||
|
||||
@ -59,565 +45,16 @@ SOFTWARE.
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// The base class for pool exceptions.
|
||||
///\ingroup pool
|
||||
//***************************************************************************
|
||||
class pool_exception : public exception
|
||||
{
|
||||
public:
|
||||
|
||||
pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||||
: exception(reason_, file_name_, line_number_)
|
||||
{}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// The exception thrown when the pool has no more free items.
|
||||
///\ingroup pool
|
||||
//***************************************************************************
|
||||
class pool_no_allocation : public pool_exception
|
||||
{
|
||||
public:
|
||||
|
||||
explicit pool_no_allocation(string_type file_name_, numeric_type line_number_)
|
||||
: pool_exception(ETL_ERROR_TEXT("pool:allocation", ETL_FILE"A"), file_name_, line_number_)
|
||||
{}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// The exception thrown when an object is released which does not belong to the pool.
|
||||
///\ingroup pool
|
||||
//***************************************************************************
|
||||
class pool_object_not_in_pool : public pool_exception
|
||||
{
|
||||
public:
|
||||
|
||||
pool_object_not_in_pool(string_type file_name_, numeric_type line_number_)
|
||||
: pool_exception(ETL_ERROR_TEXT("pool:not in pool", ETL_FILE"B"), file_name_, line_number_)
|
||||
{}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// The exception thrown when an the type requested is larger than the element size.
|
||||
///\ingroup pool
|
||||
//***************************************************************************
|
||||
class pool_element_size : public pool_exception
|
||||
{
|
||||
public:
|
||||
|
||||
pool_element_size(string_type file_name_, numeric_type line_number_)
|
||||
: pool_exception(ETL_ERROR_TEXT("pool:element size", ETL_FILE"C"), file_name_, line_number_)
|
||||
{}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///\ingroup pool
|
||||
//***************************************************************************
|
||||
class ipool
|
||||
{
|
||||
public:
|
||||
|
||||
typedef size_t size_type;
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate storage for an object from the pool.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
/// etl::pool_no_allocation if thrown, otherwise a null pointer is returned.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
T* allocate()
|
||||
{
|
||||
if (sizeof(T) > ITEM_SIZE)
|
||||
{
|
||||
ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size));
|
||||
}
|
||||
|
||||
return reinterpret_cast<T*>(allocate_item());
|
||||
}
|
||||
|
||||
#if ETL_CPP11_NOT_SUPPORTED || ETL_POOL_CPP03_CODE || ETL_USING_STLPORT
|
||||
//*************************************************************************
|
||||
/// Allocate storage for an object from the pool and create default.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
/// etl::pool_no_allocation if thrown, otherwise a null pointer is returned.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
T* create()
|
||||
{
|
||||
T* p = allocate<T>();
|
||||
|
||||
if (p)
|
||||
{
|
||||
::new (p) T();
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate storage for an object from the pool and create with 1 parameter.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
/// etl::pool_no_allocation if thrown, otherwise a null pointer is returned.
|
||||
//*************************************************************************
|
||||
template <typename T, typename T1>
|
||||
T* create(const T1& value1)
|
||||
{
|
||||
T* p = allocate<T>();
|
||||
|
||||
if (p)
|
||||
{
|
||||
::new (p) T(value1);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename T, typename T1, typename T2>
|
||||
T* create(const T1& value1, const T2& value2)
|
||||
{
|
||||
T* p = allocate<T>();
|
||||
|
||||
if (p)
|
||||
{
|
||||
::new (p) T(value1, value2);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename T, typename T1, typename T2, typename T3>
|
||||
T* create(const T1& value1, const T2& value2, const T3& value3)
|
||||
{
|
||||
T* p = allocate<T>();
|
||||
|
||||
if (p)
|
||||
{
|
||||
::new (p) T(value1, value2, value3);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename T, typename T1, typename T2, typename T3, typename T4>
|
||||
T* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
|
||||
{
|
||||
T* p = allocate<T>();
|
||||
|
||||
if (p)
|
||||
{
|
||||
::new (p) T(value1, value2, value3, value4);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
#else
|
||||
//*************************************************************************
|
||||
/// Emplace with variadic constructor parameters.
|
||||
//*************************************************************************
|
||||
template <typename T, typename... Args>
|
||||
T* create(Args&&... args)
|
||||
{
|
||||
T* p = allocate<T>();
|
||||
|
||||
if (p)
|
||||
{
|
||||
::new (p) T(etl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Destroys the object.
|
||||
/// Undefined behaviour if the pool does not contain a 'T'.
|
||||
/// \param p_object A pointer to the object to be destroyed.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
void destroy(const T* const p_object)
|
||||
{
|
||||
if (sizeof(T) > ITEM_SIZE)
|
||||
{
|
||||
ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size));
|
||||
}
|
||||
|
||||
p_object->~T();
|
||||
release(p_object);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Release an object in the pool.
|
||||
/// If asserts or exceptions are enabled and the object does not belong to this
|
||||
/// pool then an etl::pool_object_not_in_pool is thrown.
|
||||
/// \param p_object A pointer to the object to be released.
|
||||
//*************************************************************************
|
||||
void release(const void* const p_object)
|
||||
{
|
||||
const uintptr_t p = uintptr_t(p_object);
|
||||
release_item((char*)p);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Release all objects in the pool.
|
||||
//*************************************************************************
|
||||
void release_all()
|
||||
{
|
||||
items_allocated = 0;
|
||||
items_initialised = 0;
|
||||
p_next = p_buffer;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Check to see if the object belongs to the pool.
|
||||
/// \param p_object A pointer to the object to be checked.
|
||||
/// \return <b>true<\b> if it does, otherwise <b>false</b>
|
||||
//*************************************************************************
|
||||
bool is_in_pool(const void* p_object) const
|
||||
{
|
||||
const uintptr_t p = uintptr_t(p_object);
|
||||
return is_item_in_pool((const char*)p);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns the maximum number of items in the pool.
|
||||
//*************************************************************************
|
||||
size_t max_size() const
|
||||
{
|
||||
return MAX_SIZE;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns the maximum number of items in the pool.
|
||||
//*************************************************************************
|
||||
size_t capacity() const
|
||||
{
|
||||
return MAX_SIZE;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns the number of free items in the pool.
|
||||
//*************************************************************************
|
||||
size_t available() const
|
||||
{
|
||||
return MAX_SIZE - items_allocated;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns the number of allocated items in the pool.
|
||||
//*************************************************************************
|
||||
size_t size() const
|
||||
{
|
||||
return items_allocated;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Checks to see if there are no allocated items in the pool.
|
||||
/// \return <b>true</b> if there are none allocated.
|
||||
//*************************************************************************
|
||||
bool empty() const
|
||||
{
|
||||
return items_allocated == 0;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Checks to see if there are no free items in the pool.
|
||||
/// \return <b>true</b> if there are none free.
|
||||
//*************************************************************************
|
||||
bool full() const
|
||||
{
|
||||
return items_allocated == MAX_SIZE;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
//*************************************************************************
|
||||
ipool(char* p_buffer_, uint32_t item_size_, uint32_t max_size_)
|
||||
: p_buffer(p_buffer_),
|
||||
p_next(p_buffer_),
|
||||
items_allocated(0),
|
||||
items_initialised(0),
|
||||
ITEM_SIZE(item_size_),
|
||||
MAX_SIZE(max_size_)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate an item from the pool.
|
||||
//*************************************************************************
|
||||
char* allocate_item()
|
||||
{
|
||||
char* p_value = ETL_NULLPTR;
|
||||
|
||||
// Any free space left?
|
||||
if (items_allocated < MAX_SIZE)
|
||||
{
|
||||
// Initialise another one if necessary.
|
||||
if (items_initialised < MAX_SIZE)
|
||||
{
|
||||
char* p = p_buffer + (items_initialised * ITEM_SIZE);
|
||||
char* np = p + ITEM_SIZE;
|
||||
*reinterpret_cast<char**>(p) = np;
|
||||
++items_initialised;
|
||||
}
|
||||
|
||||
// Get the address of new allocated item.
|
||||
p_value = p_next;
|
||||
|
||||
++items_allocated;
|
||||
if (items_allocated != MAX_SIZE)
|
||||
{
|
||||
// Set up the pointer to the next free item
|
||||
p_next = *reinterpret_cast<char**>(p_next);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No more left!
|
||||
p_next = ETL_NULLPTR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ETL_ASSERT(false, ETL_ERROR(pool_no_allocation));
|
||||
}
|
||||
|
||||
return p_value;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Release an item back to the pool.
|
||||
//*************************************************************************
|
||||
void release_item(char* p_value)
|
||||
{
|
||||
// Does it belong to us?
|
||||
ETL_ASSERT(is_item_in_pool(p_value), ETL_ERROR(pool_object_not_in_pool));
|
||||
|
||||
if (p_next != ETL_NULLPTR)
|
||||
{
|
||||
// Point it to the current free item.
|
||||
*(uintptr_t*)p_value = reinterpret_cast<uintptr_t>(p_next);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the only free item.
|
||||
*((uintptr_t*)p_value) = 0;
|
||||
}
|
||||
|
||||
p_next = p_value;
|
||||
|
||||
--items_allocated;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Check if the item belongs to this pool.
|
||||
//*************************************************************************
|
||||
bool is_item_in_pool(const char* p) const
|
||||
{
|
||||
// Within the range of the buffer?
|
||||
intptr_t distance = p - p_buffer;
|
||||
bool is_within_range = (distance >= 0) && (distance <= intptr_t((ITEM_SIZE * MAX_SIZE) - ITEM_SIZE));
|
||||
|
||||
// Modulus and division can be slow on some architectures, so only do this in debug.
|
||||
#if defined(ETL_DEBUG)
|
||||
// Is the address on a valid object boundary?
|
||||
bool is_valid_address = ((distance % ITEM_SIZE) == 0);
|
||||
#else
|
||||
bool is_valid_address = true;
|
||||
#endif
|
||||
|
||||
return is_within_range && is_valid_address;
|
||||
}
|
||||
|
||||
// Disable copy construction and assignment.
|
||||
ipool(const ipool&);
|
||||
ipool& operator =(const ipool&);
|
||||
|
||||
char* p_buffer;
|
||||
char* p_next;
|
||||
|
||||
uint32_t items_allocated; ///< The number of items allocated.
|
||||
uint32_t items_initialised; ///< The number of items initialised.
|
||||
|
||||
const uint32_t ITEM_SIZE; ///< The size of allocated items.
|
||||
const uint32_t MAX_SIZE; ///< The maximum number of objects that can be allocated.
|
||||
|
||||
//*************************************************************************
|
||||
/// Destructor.
|
||||
//*************************************************************************
|
||||
#if defined(ETL_POLYMORPHIC_POOL) || defined(ETL_POLYMORPHIC_CONTAINERS)
|
||||
public:
|
||||
virtual ~ipool()
|
||||
{
|
||||
}
|
||||
#else
|
||||
protected:
|
||||
~ipool()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// A templated abstract pool implementation that uses a fixed size pool.
|
||||
///\ingroup pool
|
||||
//*************************************************************************
|
||||
template <const size_t TYPE_SIZE_, const size_t ALIGNMENT_, const size_t SIZE_>
|
||||
class generic_pool : public etl::ipool
|
||||
{
|
||||
public:
|
||||
|
||||
static const size_t SIZE = SIZE_;
|
||||
static const size_t ALIGNMENT = ALIGNMENT_;
|
||||
static const size_t TYPE_SIZE = TYPE_SIZE_;
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
//*************************************************************************
|
||||
generic_pool()
|
||||
: etl::ipool(reinterpret_cast<char*>(&buffer[0]), ELEMENT_SIZE, SIZE)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate an object from the pool.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
/// etl::pool_no_allocation if thrown, otherwise a null pointer is returned.
|
||||
/// Static asserts if the specified type is too large for the pool.
|
||||
//*************************************************************************
|
||||
template <typename U>
|
||||
U* allocate()
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
return ipool::allocate<U>();
|
||||
}
|
||||
|
||||
#if ETL_CPP11_NOT_SUPPORTED || ETL_POOL_CPP03_CODE || ETL_USING_STLPORT
|
||||
//*************************************************************************
|
||||
/// Allocate storage for an object from the pool and create with default.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
/// etl::pool_no_allocation if thrown, otherwise a null pointer is returned.
|
||||
//*************************************************************************
|
||||
template <typename U>
|
||||
U* create()
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
return ipool::create<U>();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate storage for an object from the pool and create with 1 parameter.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
/// etl::pool_no_allocation if thrown, otherwise a null pointer is returned.
|
||||
//*************************************************************************
|
||||
template <typename U, typename T1>
|
||||
U* create(const T1& value1)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
return ipool::create<U>(value1);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate storage for an object from the pool and create with 2 parameters.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
/// etl::pool_no_allocation if thrown, otherwise a null pointer is returned.
|
||||
//*************************************************************************
|
||||
template <typename U, typename T1, typename T2>
|
||||
U* create(const T1& value1, const T2& value2)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
return ipool::create<U>(value1, value2);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate storage for an object from the pool and create with 3 parameters.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
/// etl::pool_no_allocation if thrown, otherwise a null pointer is returned.
|
||||
//*************************************************************************
|
||||
template <typename U, typename T1, typename T2, typename T3>
|
||||
U* create(const T1& value1, const T2& value2, const T3& value3)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
return ipool::create<U>(value1, value2, value3);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate storage for an object from the pool and create with 4 parameters.
|
||||
/// If asserts or exceptions are enabled and there are no more free items an
|
||||
/// etl::pool_no_allocation if thrown, otherwise a null pointer is returned.
|
||||
//*************************************************************************
|
||||
template <typename U, typename T1, typename T2, typename T3, typename T4>
|
||||
U* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
return ipool::create<U>(value1, value2, value3, value4);
|
||||
}
|
||||
#else
|
||||
//*************************************************************************
|
||||
/// Emplace with variadic constructor parameters.
|
||||
//*************************************************************************
|
||||
template <typename U, typename... Args>
|
||||
U* create(Args&&... args)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
return ipool::create<U>(etl::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Destroys the object.
|
||||
/// Undefined behaviour if the pool does not contain a 'U'.
|
||||
/// \param p_object A pointer to the object to be destroyed.
|
||||
//*************************************************************************
|
||||
template <typename U>
|
||||
void destroy(const U* const p_object)
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment");
|
||||
ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool");
|
||||
p_object->~U();
|
||||
ipool::release(p_object);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// The pool element.
|
||||
union Element
|
||||
{
|
||||
char* next; ///< Pointer to the next free element.
|
||||
char value[TYPE_SIZE_]; ///< Storage for value type.
|
||||
typename etl::type_with_alignment<ALIGNMENT_>::type dummy; ///< Dummy item to get correct alignment.
|
||||
};
|
||||
|
||||
///< The memory for the pool of objects.
|
||||
typename etl::aligned_storage<sizeof(Element), etl::alignment_of<Element>::value>::type buffer[SIZE];
|
||||
|
||||
static const uint32_t ELEMENT_SIZE = sizeof(Element);
|
||||
|
||||
// Should not be copied.
|
||||
generic_pool(const generic_pool&);
|
||||
generic_pool& operator =(const generic_pool&);
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// A templated pool implementation that uses a fixed size pool.
|
||||
///\ingroup pool
|
||||
//*************************************************************************
|
||||
template <typename T, const size_t SIZE_>
|
||||
class pool : public etl::generic_pool<sizeof(T), etl::alignment_of<T>::value, SIZE_>
|
||||
template <typename T, const size_t VSize>
|
||||
class pool : public etl::generic_pool<sizeof(T), etl::alignment_of<T>::value, VSize>
|
||||
{
|
||||
private:
|
||||
|
||||
typedef etl::generic_pool<sizeof(T), etl::alignment_of<T>::value, SIZE_> base_t;
|
||||
typedef etl::generic_pool<sizeof(T), etl::alignment_of<T>::value, VSize> base_t;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@ -46,6 +46,7 @@ namespace etl
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ireference_counted_message() {}
|
||||
virtual ETL_NODISCARD const etl::imessage& get_message() const = 0; ///< Get a const reference to the message.
|
||||
virtual ETL_NODISCARD etl::ireference_counter& get_reference_counter() = 0; ///< Get a reference to the reference counter.
|
||||
virtual ETL_NODISCARD const etl::ireference_counter& get_reference_counter() const = 0; ///< Get a const reference to the reference counter.
|
||||
@ -55,8 +56,12 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// Reference counted message type.
|
||||
//***************************************************************************
|
||||
class ipool_message : public etl::ireference_counted_message
|
||||
{
|
||||
};
|
||||
|
||||
template <typename TMessage, typename TCounter>
|
||||
class reference_counted_message : public etl::ireference_counted_message
|
||||
class pool_message : public etl::ipool_message
|
||||
{
|
||||
public:
|
||||
|
||||
@ -67,7 +72,7 @@ namespace etl
|
||||
/// Constructor
|
||||
/// \param msg The message to count.
|
||||
//***************************************************************************
|
||||
reference_counted_message(const TMessage& msg_, etl::ireference_counted_message_pool& owner_)
|
||||
pool_message(const TMessage& msg_, etl::ireference_counted_message_pool& owner_)
|
||||
: rc_object(msg_)
|
||||
, owner(owner_)
|
||||
{
|
||||
@ -112,7 +117,7 @@ namespace etl
|
||||
private:
|
||||
|
||||
etl::reference_counted_object<TMessage, TCounter> rc_object; ///< The reference counted object.
|
||||
etl::ireference_counted_message_pool& owner; ///< The pool that owns this object.
|
||||
etl::ireference_counted_message_pool& owner; ///< The pool that owns this object.
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
@ -120,8 +125,12 @@ namespace etl
|
||||
/// The message type will always have a reference count of 1.
|
||||
/// \tparam TMessage The message type stored.
|
||||
//***************************************************************************
|
||||
class inon_pool_message : public etl::ireference_counted_message
|
||||
{
|
||||
};
|
||||
|
||||
template <typename TMessage>
|
||||
class persistent_message : virtual public etl::ireference_counted_message
|
||||
class non_pool_message : public etl::inon_pool_message
|
||||
{
|
||||
public:
|
||||
|
||||
@ -131,7 +140,7 @@ namespace etl
|
||||
/// Constructor
|
||||
/// \param msg The message to count.
|
||||
//***************************************************************************
|
||||
persistent_message(const TMessage& msg_)
|
||||
explicit non_pool_message(const TMessage& msg_)
|
||||
: rc_object(msg_)
|
||||
{
|
||||
}
|
||||
@ -175,9 +184,9 @@ namespace etl
|
||||
private:
|
||||
|
||||
// This class must not be default contructed, copy constructed or assigned.
|
||||
persistent_message() ETL_DELETE;
|
||||
persistent_message(const persistent_message&) ETL_DELETE;
|
||||
persistent_message& operator =(const persistent_message&) ETL_DELETE;
|
||||
non_pool_message() ETL_DELETE;
|
||||
non_pool_message(const non_pool_message&) ETL_DELETE;
|
||||
non_pool_message& operator =(const non_pool_message&) ETL_DELETE;
|
||||
|
||||
etl::persistent_object<TMessage> rc_object; ///< The reference counted object.
|
||||
};
|
||||
@ -188,7 +197,7 @@ namespace etl
|
||||
/// \tparam TObject The type to be reference counted.
|
||||
//***************************************************************************
|
||||
template <typename TMessage>
|
||||
using atomic_counted_message = etl::reference_counted_message<TMessage, etl::atomic_int32_t>;
|
||||
using atomic_counted_message = etl::pool_message<TMessage, etl::atomic_int32_t>;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -38,34 +38,49 @@ SOFTWARE.
|
||||
#include "static_assert.h"
|
||||
#include "error_handler.h"
|
||||
#include "utility.h"
|
||||
#include "atomic.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define ETL_FILE "57"
|
||||
#undef ETL_FILE
|
||||
#define ETL_FILE ETL_REFERENCE_COUNTER_MESSAGE_POOL_ID
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
///
|
||||
/// Exception type for etl::reference_counted_message_pool
|
||||
//***************************************************************************
|
||||
class reference_counted_message_pool_allocation_exception : public etl::exception
|
||||
class reference_counted_message_pool_exception : public etl::exception
|
||||
{
|
||||
public:
|
||||
|
||||
reference_counted_message_pool_allocation_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||||
reference_counted_message_pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||||
: exception(reason_, file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
///
|
||||
/// Exception if the allocation failed.
|
||||
//***************************************************************************
|
||||
class reference_counted_message_pool_allocation_failure : etl::reference_counted_message_pool_allocation_exception
|
||||
class reference_counted_message_pool_allocation_failure : etl::reference_counted_message_pool_exception
|
||||
{
|
||||
public:
|
||||
|
||||
reference_counted_message_pool_allocation_failure(string_type file_name_, numeric_type line_number_)
|
||||
: reference_counted_message_pool_allocation_exception(ETL_ERROR_TEXT("reference_counted_message_pool:allocation failure", ETL_FILE"A"), file_name_, line_number_)
|
||||
: reference_counted_message_pool_exception(ETL_ERROR_TEXT("reference_counted_message_pool:allocation failure", ETL_FILE"A"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception if the release failed.
|
||||
//***************************************************************************
|
||||
class reference_counted_message_pool_release_failure : etl::reference_counted_message_pool_exception
|
||||
{
|
||||
public:
|
||||
|
||||
reference_counted_message_pool_release_failure(string_type file_name_, numeric_type line_number_)
|
||||
: reference_counted_message_pool_exception(ETL_ERROR_TEXT("reference_counted_message_pool:release failure", ETL_FILE"B"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -81,8 +96,8 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
//*************************************************************************
|
||||
reference_counted_message_pool(imemory_block_pool& memory_block_pool_)
|
||||
: memory_block_pool(memory_block_pool_)
|
||||
reference_counted_message_pool(imemory_block_allocator& memory_block_allocator_)
|
||||
: memory_block_allocator(memory_block_allocator_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -90,26 +105,23 @@ namespace etl
|
||||
/// Allocate a reference counted message from the pool.
|
||||
//*************************************************************************
|
||||
template <typename TMessage>
|
||||
etl::ireference_counted_message* allocate(const TMessage& message)
|
||||
etl::ipool_message* allocate(const TMessage& message)
|
||||
{
|
||||
ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage>::value), "Not a message type");
|
||||
|
||||
typedef etl::reference_counted_message<TMessage, TCounter> rcm_t;
|
||||
typedef etl::pool_message<TMessage, TCounter> rcm_t;
|
||||
typedef rcm_t* prcm_t;
|
||||
|
||||
prcm_t p = ETL_NULLPTR;
|
||||
|
||||
if (sizeof(rcm_t) <= memory_block_pool.get_memory_block_size())
|
||||
{
|
||||
p = static_cast<prcm_t>(memory_block_pool.allocate_memory_block(sizeof(rcm_t)));
|
||||
p = static_cast<prcm_t>(memory_block_allocator.allocate(sizeof(rcm_t)));
|
||||
|
||||
if (p != ETL_NULLPTR)
|
||||
{
|
||||
::new(p) rcm_t(message, *this);
|
||||
}
|
||||
if (p != ETL_NULLPTR)
|
||||
{
|
||||
::new(p) rcm_t(message, *this);
|
||||
}
|
||||
|
||||
ETL_ASSERT((p != ETL_NULLPTR), ETL_ERROR(etl::message_pool_allocation_failure));
|
||||
ETL_ASSERT((p != ETL_NULLPTR), ETL_ERROR(etl::reference_counted_message_pool_allocation_failure));
|
||||
|
||||
return p;
|
||||
}
|
||||
@ -117,32 +129,78 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Destruct a message and send it back to the pool.
|
||||
//*************************************************************************
|
||||
void release(const etl::ireference_counted_message* const p_rcmessage)
|
||||
void release(const etl::ipool_message& rcmessage)
|
||||
{
|
||||
if (p_rcmessage != ETL_NULLPTR)
|
||||
{
|
||||
p_rcmessage->~ireference_counted_message();
|
||||
memory_block_pool.release_memory_block(p_rcmessage);
|
||||
}
|
||||
rcmessage.~ipool_message();
|
||||
bool released = memory_block_allocator.release(&rcmessage);
|
||||
|
||||
ETL_ASSERT(released, ETL_ERROR(etl::reference_counted_message_pool_release_failure));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Destruct a message and send it back to the pool.
|
||||
//*************************************************************************
|
||||
void release(const etl::ireference_counted_message& msg)
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*****************************************************
|
||||
template <typename TMessage1, typename... TMessages>
|
||||
struct pool_message_size
|
||||
{
|
||||
release(&msg);
|
||||
}
|
||||
private:
|
||||
|
||||
// Size of the first pool message type.
|
||||
static constexpr size_t size1 = sizeof(etl::pool_message<TMessage1, TCounter>);
|
||||
|
||||
// Maximum size of the the rest of the pool message types.
|
||||
static constexpr size_t size2 = pool_message_size<TMessages...>::size;
|
||||
|
||||
// Size of the first pool message type.
|
||||
static constexpr size_t alignment1 = etl::alignment_of<etl::pool_message<TMessage1, TCounter>>::value;
|
||||
|
||||
// Maximum size of the the rest of the pool message types.
|
||||
static constexpr size_t alignment2 = pool_message_size<TMessages...>::alignment;
|
||||
|
||||
public:
|
||||
|
||||
// The maximum size.
|
||||
static constexpr size_t size = (size1 < size2) ? size2 : size1;
|
||||
|
||||
// The maximum alignment.
|
||||
static constexpr size_t alignment = (alignment1 < alignment2) ? alignment2 : alignment1;
|
||||
};
|
||||
|
||||
//*****************************************************
|
||||
template <typename TMessage1>
|
||||
struct pool_message_size<TMessage1>
|
||||
{
|
||||
public:
|
||||
|
||||
ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage1>::value), "TMessage not derived from etl::imessage");
|
||||
|
||||
// The size of this pool message type.
|
||||
static constexpr size_t size = sizeof(etl::pool_message<TMessage1, TCounter>);
|
||||
|
||||
// The maximum alignment.
|
||||
static constexpr size_t alignment = etl::alignment_of<etl::pool_message<TMessage1, TCounter>>::value;
|
||||
};
|
||||
#else
|
||||
template <typename TMessage>
|
||||
struct pool_message_size
|
||||
{
|
||||
static const size_t size = sizeof(etl::pool_message<TMessage, TCounter>);
|
||||
static const size_t alignment = etl::alignment_of<etl::pool_message<TMessage, TCounter> >::value;
|
||||
};
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
/// The raw memory block pool.
|
||||
imemory_block_pool& memory_block_pool;
|
||||
imemory_block_allocator& memory_block_allocator;
|
||||
|
||||
// Should not be copied.
|
||||
reference_counted_message_pool(const reference_counted_message_pool&) ETL_DELETE;
|
||||
reference_counted_message_pool& operator =(const reference_counted_message_pool&) ETL_DELETE;
|
||||
};
|
||||
|
||||
#if ETL_CPP11_SUPPORTED && ETL_HAS_ATOMIC
|
||||
using atomic_counted_message_pool = reference_counted_message_pool<etl::atomic_int>;
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef ETL_FILE
|
||||
|
||||
@ -151,6 +151,7 @@ namespace etl
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ireference_counted_object() {}
|
||||
ETL_NODISCARD virtual ireference_counter& get_reference_counter() = 0;
|
||||
ETL_NODISCARD virtual const ireference_counter& get_reference_counter() const = 0;
|
||||
};
|
||||
|
||||
@ -34,6 +34,10 @@ SOFTWARE.
|
||||
#include "platform.h"
|
||||
#include "utility.h"
|
||||
#include "reference_counted_message.h"
|
||||
#include "ireference_counted_message_pool.h"
|
||||
#include "message.h"
|
||||
#include "type_traits.h"
|
||||
#include "static_assert.h"
|
||||
|
||||
//*****************************************************************************
|
||||
/// A wrapper for reference counted messages.
|
||||
@ -45,11 +49,37 @@ namespace etl
|
||||
{
|
||||
public:
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
//*************************************************************************
|
||||
template <typename TPool, typename TMessage>
|
||||
shared_message(TPool& owner, const TMessage& message)
|
||||
{
|
||||
ETL_STATIC_ASSERT((etl::is_base_of<etl::ireference_counted_message_pool, TPool>::value), "TPool not derived from etl::ireference_counted_message_pool");
|
||||
ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage>::value), "TMessage not derived from etl::imessage");
|
||||
|
||||
p_rcmessage = owner.allocate(message);
|
||||
|
||||
if (p_rcmessage != ETL_NULLPTR)
|
||||
{
|
||||
p_rcmessage->get_reference_counter().set_reference_count(1U);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
/// \param np_message A reference to a message not controlled by a pool.
|
||||
//*************************************************************************
|
||||
explicit shared_message(etl::inon_pool_message& np_message)
|
||||
: p_rcmessage(&np_message)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
/// \param message A reference to the message allocated from the pool.
|
||||
//*************************************************************************
|
||||
shared_message(etl::ireference_counted_message& rcmessage_)
|
||||
explicit shared_message(etl::ipool_message& rcmessage_)
|
||||
: p_rcmessage(&rcmessage_)
|
||||
{
|
||||
p_rcmessage->get_reference_counter().set_reference_count(1U);
|
||||
@ -100,7 +130,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Get a const reference to the contained message.
|
||||
//*************************************************************************
|
||||
const etl::imessage& get_message() const
|
||||
ETL_NODISCARD const etl::imessage& get_message() const
|
||||
{
|
||||
return p_rcmessage->get_message();
|
||||
}
|
||||
@ -108,7 +138,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Get the current reference count for this shared message.
|
||||
//*************************************************************************
|
||||
uint32_t get_reference_count() const
|
||||
ETL_NODISCARD uint32_t get_reference_count() const
|
||||
{
|
||||
return p_rcmessage->get_reference_counter().get_reference_count();
|
||||
}
|
||||
@ -117,34 +147,8 @@ namespace etl
|
||||
|
||||
shared_message() ETL_DELETE;
|
||||
|
||||
etl::ireference_counted_message* p_rcmessage;
|
||||
etl::ireference_counted_message* p_rcmessage; ///< A pointer to the reference counted message.
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
/// Make a shared_message from a pool.
|
||||
/// \param owner The pool to allocate the reference counted message from.
|
||||
/// \param message The message to reference count.
|
||||
//*****************************************************************************
|
||||
template <typename TPool, typename TMessage>
|
||||
etl::shared_message make_shared_message(TPool& owner, const TMessage& message)
|
||||
{
|
||||
etl::ireference_counted_message* p_rcmessage = owner.allocate(message);
|
||||
return etl::shared_message(*p_rcmessage);
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*****************************************************************************
|
||||
/// Make a shared_message from a pool.
|
||||
/// \param owner The pool to allocate the reference counted message from.
|
||||
/// \param args The arguments to pass to the message constructor.
|
||||
//*****************************************************************************
|
||||
template <typename TMessage, typename TPool, typename... TArgs>
|
||||
etl::shared_message make_shared_message(TPool& owner, TArgs&&... args)
|
||||
{
|
||||
etl::ireference_counted_message* p_rcmessage = owner.allocate(TMessage(etl::forward<TArgs>(args)...));
|
||||
return etl::shared_message(*p_rcmessage);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -54,7 +54,7 @@ SOFTWARE.
|
||||
#include <stdint.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "generic_pool.h"
|
||||
#include "pool.h"
|
||||
#include "type_traits.h"
|
||||
#include "static_assert.h"
|
||||
#include "largest.h"
|
||||
|
||||
@ -1,221 +0,0 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2020 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "UnitTest++/UnitTest++.h"
|
||||
|
||||
#include "etl/pool.h"
|
||||
#include "etl/shared_message.h"
|
||||
#include "etl/message.h"
|
||||
#include "etl/message_router.h"
|
||||
#include "etl/atomic.h"
|
||||
#include "etl/queue.h"
|
||||
#include "etl/reference_counted_message_pool.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr etl::message_id_t MESSAGE1 = 1U;
|
||||
constexpr etl::message_id_t MESSAGE2 = 2U;
|
||||
|
||||
constexpr etl::message_router_id_t ROUTER1 = 1U;
|
||||
constexpr etl::message_router_id_t ROUTER2 = 2U;
|
||||
|
||||
//*************************************************************************
|
||||
struct Message1 : public etl::message<MESSAGE1>
|
||||
{
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
struct Message2 : public etl::message<MESSAGE2>
|
||||
{
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
struct Router1 : public etl::message_router<Router1, Message1, Message2>
|
||||
{
|
||||
Router1()
|
||||
: message_router(1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& source, const Message1& message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void on_receive_unknown(etl::imessage_router& source, const etl::imessage& message)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
struct Router2 : public etl::message_router<Router2, Message1, Message2>
|
||||
{
|
||||
Router2()
|
||||
: message_router(2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& source, const Message1& message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void on_receive_unknown(etl::imessage_router& source, const etl::imessage& message)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
struct Processor : public etl::shared_message_processor
|
||||
{
|
||||
Processor(Router& router_)
|
||||
: shared_message_processor(router_)
|
||||
{
|
||||
}
|
||||
|
||||
void receive(etl::shared_message message)
|
||||
{
|
||||
uint32_t count1 = message.get_reference_count();
|
||||
|
||||
smqueue.push(message);
|
||||
|
||||
uint32_t count2 = message.get_reference_count();
|
||||
}
|
||||
|
||||
void receive(etl::imessage_router& source, etl::shared_message message)
|
||||
{
|
||||
}
|
||||
|
||||
void Process()
|
||||
{
|
||||
get_router().receive(smqueue.front().get_message());
|
||||
smqueue.pop();
|
||||
}
|
||||
|
||||
etl::queue<etl::shared_message, 10> smqueue;
|
||||
};
|
||||
|
||||
Router router;
|
||||
Processor processor(router);
|
||||
|
||||
SUITE(test_shared_message)
|
||||
{
|
||||
constexpr size_t POOL_SIZE = 2;
|
||||
|
||||
etl::variant_pool<POOL_SIZE, Message1> vpool;
|
||||
|
||||
etl::message_pool mp(vpool);
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_buffered)
|
||||
{
|
||||
etl::message_pool& mpool = mp;
|
||||
|
||||
{
|
||||
etl::shared_message* pbuffered_sm = nullptr;
|
||||
|
||||
{
|
||||
etl::shared_message sm(mpool, *mpool.create<Message1>());
|
||||
uint32_t count1 = sm.get_reference_count();
|
||||
|
||||
processor.receive(sm);
|
||||
|
||||
uint32_t count1b = sm.get_reference_count();
|
||||
|
||||
processor.Process();
|
||||
|
||||
uint32_t count1c = sm.get_reference_count();
|
||||
|
||||
pbuffered_sm = new etl::shared_message(sm);
|
||||
//uint32_t count2 = sm.get_reference_count();
|
||||
//uint32_t count3 = pbuffered_sm->get_reference_count();
|
||||
|
||||
etl::shared_message sm2 = etl::shared_message(mpool, *mpool.create<Message1>());
|
||||
uint32_t count4 = sm2.get_reference_count();
|
||||
|
||||
pbuffered_sm = pbuffered_sm;
|
||||
}
|
||||
|
||||
size_t ps1 = vpool.size();
|
||||
|
||||
//{
|
||||
// uint32_t count = pbuffered_sm->get_reference_count();
|
||||
// etl::message_id_t id = pbuffered_sm->get_message().get_message_id();
|
||||
//}
|
||||
|
||||
size_t ps2 = vpool.size();
|
||||
|
||||
delete pbuffered_sm;
|
||||
}
|
||||
|
||||
size_t ps3 = vpool.size();
|
||||
|
||||
vpool.size();
|
||||
}
|
||||
}
|
||||
|
||||
////*************************************************************************
|
||||
//TEST(test_construct_and_destruct)
|
||||
//{
|
||||
// etl::pool<Message1, 2> pool;
|
||||
// etl::pool_chain<1> pool_chain;
|
||||
|
||||
// pool_chain.add(pool);
|
||||
|
||||
// etl::shared_message buffered_sm(pool_chain);
|
||||
|
||||
// {
|
||||
// etl::shared_message sm1(pool_chain, pool.create());
|
||||
// CHECK_EQUAL(1, sm1.get_reference_count());
|
||||
// CHECK_EQUAL(1, pool.size());
|
||||
// {
|
||||
// etl::shared_message sm2(sm1);
|
||||
// CHECK_EQUAL(1, sm1.get_reference_count());
|
||||
// CHECK_EQUAL(2, sm2.get_reference_count());
|
||||
// CHECK_EQUAL(1, pool.size());
|
||||
// {
|
||||
// etl::shared_message sm3(pool_chain);
|
||||
// sm3 = sm2;
|
||||
// CHECK_EQUAL(1, sm1.get_reference_count());
|
||||
// CHECK_EQUAL(2, sm2.get_reference_count());
|
||||
// CHECK_EQUAL(3, sm3.get_reference_count());
|
||||
// CHECK_EQUAL(1, pool.size());
|
||||
|
||||
// }
|
||||
// CHECK_EQUAL(1, pool.size());
|
||||
// }
|
||||
// CHECK_EQUAL(1, pool.size());
|
||||
// }
|
||||
// CHECK_EQUAL(0, pool.size());
|
||||
//}
|
||||
|
||||
}
|
||||
197
test/test_shared_message.cpp
Normal file
197
test/test_shared_message.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2020 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "UnitTest++/UnitTest++.h"
|
||||
|
||||
#include "etl/shared_message.h"
|
||||
#include "etl/message.h"
|
||||
#include "etl/message_router.h"
|
||||
#include "etl/message_bus.h"
|
||||
#include "etl/queue.h"
|
||||
#include "etl/fixed_sized_memory_block_allocator.h"
|
||||
#include "etl/reference_counted_message_pool.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr etl::message_id_t MessageId1 = 1U;
|
||||
constexpr etl::message_id_t MessageId2 = 2U;
|
||||
|
||||
constexpr etl::message_router_id_t RouterId1 = 1U;
|
||||
constexpr etl::message_router_id_t RouterId2 = 2U;
|
||||
|
||||
//*************************************************************************
|
||||
struct Message1 : public etl::message<MessageId1>
|
||||
{
|
||||
Message1(int i_)
|
||||
: i(i_)
|
||||
{
|
||||
}
|
||||
|
||||
~Message1()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int i;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
struct Message2 : public etl::message<MessageId2>
|
||||
{
|
||||
~Message2()
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
struct Router1 : public etl::message_router<Router1, Message1, Message2>
|
||||
{
|
||||
Router1()
|
||||
: message_router(RouterId1)
|
||||
, count_message1(0)
|
||||
, count_message2(0)
|
||||
, count_unknown_message(0)
|
||||
{
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& source, const Message1& message)
|
||||
{
|
||||
++count_message1;
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& source, const Message2& message)
|
||||
{
|
||||
++count_message2;
|
||||
}
|
||||
|
||||
void on_receive_unknown(etl::imessage_router& source, const etl::imessage& message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
count_message1 = 0;
|
||||
count_message2 = 0;
|
||||
count_unknown_message = 0;
|
||||
}
|
||||
|
||||
int count_message1;
|
||||
int count_message2;
|
||||
int count_unknown_message;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
struct Router2 : public etl::message_router<Router2, Message1>
|
||||
{
|
||||
Router2()
|
||||
: message_router(RouterId2)
|
||||
, count_message1(0)
|
||||
, count_message2(0)
|
||||
, count_unknown_message(0)
|
||||
{
|
||||
}
|
||||
|
||||
void on_receive(etl::imessage_router& source, const Message1& message)
|
||||
{
|
||||
++count_message1;
|
||||
}
|
||||
|
||||
void on_receive_unknown(etl::imessage_router& source, const etl::imessage& message)
|
||||
{
|
||||
++count_unknown_message;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
count_message1 = 0;
|
||||
count_message2 = 0;
|
||||
count_unknown_message = 0;
|
||||
}
|
||||
|
||||
int count_message1;
|
||||
int count_message2;
|
||||
int count_unknown_message;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
struct Bus : public etl::message_bus<2U>
|
||||
{
|
||||
};
|
||||
|
||||
SUITE(test_shared_message)
|
||||
{
|
||||
Router1 router1;
|
||||
Router2 router2;
|
||||
Bus bus;
|
||||
|
||||
using pool_message_parameters = etl::atomic_counted_message_pool::pool_message_size<Message1, Message2>;
|
||||
|
||||
etl::fixed_sized_memory_block_allocator<pool_message_parameters::size,
|
||||
pool_message_parameters::alignment,
|
||||
4U> memory_allocator;
|
||||
|
||||
etl::atomic_counted_message_pool message_pool(memory_allocator);
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_send_to_routers)
|
||||
{
|
||||
bus.clear();
|
||||
bus.subscribe(router1);
|
||||
bus.subscribe(router2);
|
||||
router1.clear();
|
||||
router2.clear();
|
||||
|
||||
etl::non_pool_message<Message2> npm((Message2())); // npm is not owned by any pool. Extra parentheses to fix 'vexing parse'.
|
||||
|
||||
etl::shared_message sm1(message_pool, Message1(1)); // sm1 holds a Message1 that is owned by message_pool.
|
||||
etl::shared_message sm2(message_pool, Message2()); // sm2 holds a Message2 that is owned by message_pool.
|
||||
etl::shared_message sm3(npm); // sm3 holds a Message2 that is not owned by a message pool.
|
||||
etl::shared_message sm4(sm1); // sm4 is a copy of sm1.
|
||||
|
||||
bus.receive(sm1);
|
||||
bus.receive(sm2);
|
||||
bus.receive(sm1);
|
||||
bus.receive(sm3);
|
||||
bus.receive(sm4); // sm4 is a copy of sm1
|
||||
bus.receive(RouterId2, sm1); // Only send sm1 to Router2
|
||||
|
||||
CHECK_EQUAL(2, sm1.get_reference_count());
|
||||
CHECK_EQUAL(1, sm2.get_reference_count());
|
||||
CHECK_EQUAL(1, sm3.get_reference_count());
|
||||
CHECK_EQUAL(2, sm4.get_reference_count());
|
||||
CHECK_EQUAL(3, router1.count_message1);
|
||||
CHECK_EQUAL(2, router1.count_message2);
|
||||
CHECK_EQUAL(0, router1.count_unknown_message);
|
||||
CHECK_EQUAL(4, router2.count_message1);
|
||||
CHECK_EQUAL(0, router2.count_message2);
|
||||
CHECK_EQUAL(0, router2.count_unknown_message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1272,6 +1272,7 @@
|
||||
<ClInclude Include="..\..\include\etl\cumulative_moving_average.h" />
|
||||
<ClInclude Include="..\..\include\etl\delegate.h" />
|
||||
<ClInclude Include="..\..\include\etl\delegate_service.h" />
|
||||
<ClInclude Include="..\..\include\etl\file_error_numbers.h" />
|
||||
<ClInclude Include="..\..\include\etl\flags.h" />
|
||||
<ClInclude Include="..\..\include\etl\format_spec.h" />
|
||||
<ClInclude Include="..\..\include\etl\frame_check_sequence.h" />
|
||||
@ -1293,7 +1294,7 @@
|
||||
<ClInclude Include="..\..\include\etl\ireference_counted_message_pool.h" />
|
||||
<ClInclude Include="..\..\include\etl\limits.h" />
|
||||
<ClInclude Include="..\..\include\etl\macros.h" />
|
||||
<ClInclude Include="..\..\include\etl\fixed_sized_memory_block_pool.h" />
|
||||
<ClInclude Include="..\..\include\etl\fixed_sized_memory_block_allocator.h" />
|
||||
<ClInclude Include="..\..\include\etl\message_packet.h" />
|
||||
<ClInclude Include="..\..\include\etl\message_pool.h" />
|
||||
<ClInclude Include="..\..\include\etl\multi_array.h" />
|
||||
@ -1333,7 +1334,6 @@
|
||||
<ClInclude Include="..\..\include\etl\reference_counted_object.h" />
|
||||
<ClInclude Include="..\..\include\etl\scaled_rounding.h" />
|
||||
<ClInclude Include="..\..\include\etl\shared_message.h" />
|
||||
<ClInclude Include="..\..\include\etl\shared_message_processor.h" />
|
||||
<ClInclude Include="..\..\include\etl\span.h" />
|
||||
<ClInclude Include="..\..\include\etl\state_chart.h" />
|
||||
<ClInclude Include="..\..\include\etl\math_constants.h" />
|
||||
@ -1915,7 +1915,7 @@
|
||||
<ClCompile Include="..\test_parity_checksum.cpp" />
|
||||
<ClCompile Include="..\test_pearson.cpp" />
|
||||
<ClCompile Include="..\test_pool.cpp" />
|
||||
<ClCompile Include="..\test_pool_message.cpp" />
|
||||
<ClCompile Include="..\test_shared_message.cpp" />
|
||||
<ClCompile Include="..\test_priority_queue.cpp" />
|
||||
<ClCompile Include="..\test_queue.cpp" />
|
||||
<ClCompile Include="..\test_queue_memory_model_small.cpp" />
|
||||
@ -2021,7 +2021,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\CMakeLists.txt" />
|
||||
<Text Include="..\..\include\etl\file_error_numbers.txt" />
|
||||
<Text Include="..\..\support\Release notes.txt" />
|
||||
<Text Include="..\..\todo.txt" />
|
||||
<Text Include="..\CMakeLists.txt" />
|
||||
|
||||
@ -909,18 +909,9 @@
|
||||
<ClInclude Include="..\..\include\etl\multi_range.h">
|
||||
<Filter>ETL\Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\ipool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\message_pool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\shared_message.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\shared_message_processor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\ireference_counted_message_pool.h">
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
@ -930,13 +921,22 @@
|
||||
<ClInclude Include="..\..\include\etl\reference_counted_message_pool.h">
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\reference_counted_object.h">
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\fixed_sized_memory_block_pool.h">
|
||||
<ClInclude Include="..\..\include\etl\generic_pool.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\generic_pool.h">
|
||||
<ClInclude Include="..\..\include\etl\ipool.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\file_error_numbers.h">
|
||||
<Filter>ETL\Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\shared_message.h">
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\reference_counted_object.h">
|
||||
<Filter>ETL\Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\fixed_sized_memory_block_allocator.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
@ -1475,7 +1475,7 @@
|
||||
<ClCompile Include="..\test_multi_range.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_pool_message.cpp">
|
||||
<ClCompile Include="..\test_shared_message.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
@ -1560,9 +1560,6 @@
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\include\etl\file_error_numbers.txt">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Text>
|
||||
<Text Include="..\..\support\Release notes.txt">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Text>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user