Merge branch 'feature/shared-objects-in-pools' into development

# Conflicts:
#	.gitignore
#	include/etl/deque.h
#	include/etl/file_error_numbers.txt
#	include/etl/generators/fsm_generator.h
#	include/etl/list.h
#	include/etl/memory.h
#	include/etl/pool.h
#	test/vs2019/etl.vcxproj.filters
This commit is contained in:
John Wellbelove 2021-01-04 17:15:25 +00:00
commit f980ce2cd3
31 changed files with 2278 additions and 794 deletions

2
.gitignore vendored
View File

@ -282,3 +282,5 @@ test/vs2019/multi_loop.csv
temp/create_arduino_library.py
examples/FunctionInterruptSimulation-Delegates/vs2019/.vs
*.db-shm
test/vs2019/.vs/etl/v16/Browse.VC.db-wal

View File

@ -48,6 +48,7 @@ SOFTWARE.
#define ETL_HAS_ATOMIC 1
#else
#define ETL_HAS_ATOMIC 0
#pragma message ("ETL atomics not supported")
#endif
#endif

View File

@ -206,8 +206,8 @@ namespace etl
//*************************************************************************
deque_base(size_t max_size_, size_t buffer_size_)
: current_size(0),
CAPACITY(max_size_),
BUFFER_SIZE(buffer_size_)
CAPACITY(max_size_),
BUFFER_SIZE(buffer_size_)
{
}
@ -236,12 +236,12 @@ namespace etl
typedef T value_type;
typedef size_t size_type;
typedef T& reference;
typedef T& reference;
typedef const T& const_reference;
#if ETL_CPP11_SUPPORTED
typedef T&& rvalue_reference;
typedef T&& rvalue_reference;
#endif
typedef T* pointer;
typedef T* pointer;
typedef const T* const_pointer;
typedef typename etl::iterator_traits<pointer>::difference_type difference_type;
@ -284,8 +284,8 @@ namespace etl
//***************************************************
iterator& operator =(const iterator& other)
{
index = other.index;
p_deque = other.p_deque;
index = other.index;
p_deque = other.p_deque;
p_buffer = other.p_buffer;
return *this;
@ -491,7 +491,7 @@ namespace etl
}
difference_type index;
ideque* p_deque;
ideque* p_deque;
pointer p_buffer;
};
@ -529,8 +529,8 @@ namespace etl
//***************************************************
const_iterator& operator =(const const_iterator& other)
{
index = other.index;
p_deque = other.p_deque;
index = other.index;
p_deque = other.p_deque;
p_buffer = other.p_buffer;
return *this;
@ -538,8 +538,8 @@ namespace etl
const_iterator& operator =(const typename ideque::iterator& other)
{
index = other.index;
p_deque = other.p_deque;
index = other.index;
p_deque = other.p_deque;
p_buffer = other.p_buffer;
return *this;
@ -733,7 +733,7 @@ namespace etl
}
difference_type index;
ideque* p_deque;
ideque* p_deque;
pointer p_buffer;
};
@ -1095,7 +1095,7 @@ namespace etl
p = etl::addressof(*_begin);
++current_size;
ETL_INCREMENT_DEBUG_COUNT
position = _begin;
position = _begin;
}
else if (insert_position == end())
{
@ -1103,7 +1103,7 @@ namespace etl
++_end;
++current_size;
ETL_INCREMENT_DEBUG_COUNT
position = _end - 1;
position = _end - 1;
}
else
{
@ -1162,7 +1162,7 @@ namespace etl
p = etl::addressof(*_begin);
++current_size;
ETL_INCREMENT_DEBUG_COUNT
position = _begin;
position = _begin;
}
else if (insert_position == end())
{
@ -1170,7 +1170,7 @@ namespace etl
++_end;
++current_size;
ETL_INCREMENT_DEBUG_COUNT
position = _end - 1;
position = _end - 1;
}
else
{
@ -1227,7 +1227,7 @@ namespace etl
p = etl::addressof(*_begin);
++current_size;
ETL_INCREMENT_DEBUG_COUNT
position = _begin;
position = _begin;
}
else if (insert_position == end())
{
@ -1235,7 +1235,7 @@ namespace etl
++_end;
++current_size;
ETL_INCREMENT_DEBUG_COUNT
position = _end - 1;
position = _end - 1;
}
else
{
@ -1292,7 +1292,7 @@ namespace etl
p = etl::addressof(*_begin);
++current_size;
ETL_INCREMENT_DEBUG_COUNT
position = _begin;
position = _begin;
}
else if (insert_position == end())
{
@ -1300,7 +1300,7 @@ namespace etl
++_end;
++current_size;
ETL_INCREMENT_DEBUG_COUNT
position = _end - 1;
position = _end - 1;
}
else
{
@ -1357,7 +1357,7 @@ namespace etl
p = etl::addressof(*_begin);
++current_size;
ETL_INCREMENT_DEBUG_COUNT
position = _begin;
position = _begin;
}
else if (insert_position == end())
{
@ -1365,7 +1365,7 @@ namespace etl
++_end;
++current_size;
ETL_INCREMENT_DEBUG_COUNT
position = _end - 1;
position = _end - 1;
}
else
{
@ -2090,7 +2090,7 @@ namespace etl
//*************************************************************************
ideque(pointer p_buffer_, size_t max_size_, size_t buffer_size_)
: deque_base(max_size_, buffer_size_),
p_buffer(p_buffer_)
p_buffer(p_buffer_)
{
}
@ -2101,7 +2101,7 @@ namespace etl
{
if ETL_IF_CONSTEXPR(etl::is_trivially_destructible<T>::value)
{
current_size = 0;
current_size = 0;
ETL_RESET_DEBUG_COUNT
}
else
@ -2113,7 +2113,7 @@ namespace etl
}
_begin = iterator(0, *this, p_buffer);
_end = iterator(0, *this, p_buffer);
_end = iterator(0, *this, p_buffer);
}
//*************************************************************************
@ -2124,7 +2124,7 @@ namespace etl
p_buffer = p_buffer_;
_begin = iterator(_begin.index, *this, p_buffer);
_end = iterator(_end.index, *this, p_buffer);
_end = iterator(_end.index, *this, p_buffer);
}
iterator _begin; ///Iterator to the _begin item in the deque.
@ -2233,7 +2233,7 @@ namespace etl
(*_begin).~T();
--current_size;
ETL_DECREMENT_DEBUG_COUNT
++_begin;
++_begin;
}
//*********************************************************************
@ -2319,9 +2319,9 @@ namespace etl
public:
typedef T value_type;
typedef T* pointer;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef typename etl::iterator_traits<pointer>::difference_type difference_type;
@ -2507,9 +2507,9 @@ namespace etl
bool operator <(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
{
return etl::lexicographical_compare(lhs.begin(),
lhs.end(),
rhs.begin(),
rhs.end());
lhs.end(),
rhs.begin(),
rhs.end());
}
//***************************************************************************

View File

@ -53,5 +53,5 @@
53 indirect_vector
54 queue_spsc_locked
55 message_packet
56 circular_buffer
57 multi_loop
56 multi_range
57 reference_counted_message_pool

View File

@ -0,0 +1,65 @@
///\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

View File

@ -224,8 +224,10 @@ namespace etl
/// Constructor.
//*******************************************
fsm(etl::message_router_id_t id)
: imessage_router(id),
p_state(ETL_NULLPTR)
: imessage_router(id)
, p_state(ETL_NULLPTR)
, state_list(ETL_NULLPTR)
, number_of_states(0U)
{
}
@ -278,26 +280,6 @@ namespace etl
}
}
//*******************************************
/// Top level message handler for the FSM.
//*******************************************
void receive(const etl::imessage& message) ETL_OVERRIDE
{
static etl::null_message_router nmr;
receive(nmr, message);
}
//*******************************************
/// Top level message handler for the FSM.
//*******************************************
void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, message);
}
}
//*******************************************
/// Top level message handler for the FSM.
//*******************************************
@ -448,7 +430,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -513,7 +495,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -577,7 +559,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -640,7 +622,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -701,7 +683,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -761,7 +743,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -820,7 +802,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -878,7 +860,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -934,7 +916,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -989,7 +971,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -1043,7 +1025,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -1096,7 +1078,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -1147,7 +1129,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -1197,7 +1179,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -1246,7 +1228,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{
@ -1294,7 +1276,7 @@ namespace etl
etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t new_state_id;
etl::message_id_t event_id = message.message_id;
etl::message_id_t event_id = message.get_message_id();
switch (event_id)
{

View File

@ -236,8 +236,10 @@ namespace etl
/// Constructor.
//*******************************************
fsm(etl::message_router_id_t id)
: imessage_router(id),
p_state(ETL_NULLPTR)
: imessage_router(id)
, p_state(ETL_NULLPTR)
, state_list(ETL_NULLPTR)
, number_of_states(0U)
{
}
@ -290,26 +292,6 @@ namespace etl
}
}
//*******************************************
/// Top level message handler for the FSM.
//*******************************************
void receive(const etl::imessage& message) ETL_OVERRIDE
{
static etl::null_message_router nmr;
receive(nmr, message);
}
//*******************************************
/// Top level message handler for the FSM.
//*******************************************
void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, message);
}
}
//*******************************************
/// Top level message handler for the FSM.
//*******************************************
@ -468,7 +450,7 @@ namespace etl
cog.outl(" etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)")
cog.outl(" {")
cog.outl(" etl::fsm_state_id_t new_state_id;")
cog.outl(" etl::message_id_t event_id = message.message_id;")
cog.outl(" etl::message_id_t event_id = message.get_message_id();")
cog.outl("")
cog.outl(" switch (event_id)")
cog.outl(" {")
@ -545,7 +527,7 @@ namespace etl
cog.outl(" etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)")
cog.outl(" {")
cog.outl(" etl::fsm_state_id_t new_state_id;")
cog.outl(" etl::message_id_t event_id = message.message_id;")
cog.outl(" etl::message_id_t event_id = message.get_message_id();")
cog.outl("")
cog.outl(" switch (event_id)")
cog.outl(" {")

View File

@ -217,7 +217,7 @@ namespace etl
cog.outl("#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)")
cog.outl(" pmsg->~imessage();")
cog.outl("#else")
cog.outl(" size_t id = pmsg->message_id;")
cog.outl(" size_t id = pmsg->get_message_id();")
cog.outl("")
cog.outl(" switch (id)")
cog.outl(" {")
@ -232,7 +232,7 @@ namespace etl
cog.outl(" //********************************************")
cog.outl(" void add_new_message(const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" const size_t id = msg.message_id;")
cog.outl(" const size_t id = msg.get_message_id();")
cog.outl(" void* p = data;")
cog.outl("")
cog.outl(" switch (id)")
@ -247,7 +247,7 @@ namespace etl
cog.outl(" //********************************************")
cog.outl(" void add_new_message(etl::imessage&& msg)")
cog.outl(" {")
cog.outl(" const size_t id = msg.message_id;")
cog.outl(" const size_t id = msg.get_message_id();")
cog.outl(" void* p = data;")
cog.outl("")
cog.outl(" switch (id)")
@ -416,7 +416,7 @@ namespace etl
cog.outl("#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)")
cog.outl(" pmsg->~imessage();")
cog.outl("#else")
cog.outl(" size_t id = pmsg->message_id;")
cog.outl(" size_t id = pmsg->get_message_id();")
cog.outl("")
cog.outl(" switch (id)")
cog.outl(" {")
@ -431,7 +431,7 @@ namespace etl
cog.outl(" //********************************************")
cog.outl(" void add_new_message(const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" const size_t id = msg.message_id;")
cog.outl(" const size_t id = msg.get_message_id();")
cog.outl(" void* p = data;")
cog.outl("")
cog.outl(" switch (id)")
@ -446,7 +446,7 @@ namespace etl
cog.outl(" //********************************************")
cog.outl(" void add_new_message(etl::imessage&& msg)")
cog.outl(" {")
cog.outl(" const size_t id = msg.message_id;")
cog.outl(" const size_t id = msg.get_message_id();")
cog.outl(" void* p = data;")
cog.outl("")
cog.outl(" switch (id)")

View File

@ -67,6 +67,7 @@ cog.outl("//********************************************************************
#include "platform.h"
#include "message.h"
#include "shared_message.h"
#include "message_packet.h"
#include "message_types.h"
#include "alignment.h"
@ -107,6 +108,13 @@ namespace etl
}
};
//***************************************************************************
/// Forward declare null message router functionality.
//***************************************************************************
class imessage_router;
etl::imessage_router& get_null_message_router();
//***************************************************************************
/// This is the base of all message routers.
//***************************************************************************
@ -115,18 +123,51 @@ namespace etl
public:
virtual ~imessage_router() {}
virtual void receive(const etl::imessage& message) = 0;
virtual void receive(imessage_router& source, const etl::imessage& message) = 0;
virtual void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message) = 0;
virtual bool accepts(etl::message_id_t id) const = 0;
virtual bool is_null_router() const = 0;
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))
{
receive(source, message);
}
}
//********************************************
void receive(const etl::imessage& message)
{
receive(etl::get_null_message_router(), message);
}
//********************************************
virtual void receive(imessage_router& source, etl::shared_message shared_msg)
{
receive(source, shared_msg.get_message());
}
//********************************************
void receive(etl::shared_message shared_msg)
{
receive(etl::get_null_message_router(), shared_msg);
}
//********************************************
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))
{
receive(source, shared_msg);
}
}
//********************************************
bool accepts(const etl::imessage& msg) const
{
return accepts(msg.message_id);
return accepts(msg.get_message_id());
}
//********************************************
@ -164,15 +205,15 @@ namespace etl
protected:
imessage_router(etl::message_router_id_t id_)
: successor(ETL_NULLPTR),
message_router_id(id_)
: successor(ETL_NULLPTR)
, message_router_id(id_)
{
}
imessage_router(etl::message_router_id_t id_,
imessage_router& successor_)
: successor(&successor_),
message_router_id(id_)
imessage_router& successor_)
: successor(&successor_)
, message_router_id(id_)
{
}
@ -200,21 +241,15 @@ namespace etl
}
//********************************************
void receive(const etl::imessage&) ETL_OVERRIDE
{
}
using etl::imessage_router::receive;
//********************************************
void receive(etl::imessage_router&, const etl::imessage&) ETL_OVERRIDE
{
}
//********************************************
void receive(imessage_router&, etl::message_router_id_t, const etl::imessage&) ETL_OVERRIDE
{
}
using etl::imessage_router::accepts;
//********************************************
bool accepts(etl::message_id_t) const ETL_OVERRIDE
{
return false;
@ -246,6 +281,13 @@ namespace etl
}
};
//***********************************************
/// null message router functionality.
inline etl::imessage_router& get_null_message_router()
{
return etl::null_message_router::instance();
}
//***************************************************************************
/// This router can be used as a producer-only of messages, such an interrupt routine.
//***************************************************************************
@ -259,21 +301,15 @@ namespace etl
}
//********************************************
void receive(const etl::imessage&) ETL_OVERRIDE
{
}
using etl::imessage_router::receive;
//********************************************
void receive(etl::imessage_router&, const etl::imessage&) ETL_OVERRIDE
{
}
//********************************************
void receive(imessage_router&, etl::message_router_id_t, const etl::imessage&) ETL_OVERRIDE
{
}
using etl::imessage_router::accepts;
//********************************************
bool accepts(etl::message_id_t) const ETL_OVERRIDE
{
return false;
@ -359,24 +395,11 @@ namespace etl
cog.outl(" }")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" void receive(const etl::imessage& msg) ETL_OVERRIDE")
cog.outl(" {")
cog.outl(" receive(etl::null_message_router::instance(), msg);")
cog.outl(" }")
cog.outl(" using etl::imessage_router::receive;")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE")
cog.outl(" {")
cog.outl(" if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))")
cog.outl(" {")
cog.outl(" receive(source, msg);")
cog.outl(" }")
cog.outl(" }")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE")
cog.outl(" {")
cog.outl(" const etl::message_id_t id = msg.message_id;")
cog.outl(" const etl::message_id_t id = msg.get_message_id();")
cog.outl("")
cog.outl(" switch (id)")
cog.outl(" {")
@ -399,9 +422,9 @@ namespace etl
cog.outl(" }")
cog.outl(" }")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" using imessage_router::accepts;")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" bool accepts(etl::message_id_t id) const ETL_OVERRIDE")
cog.outl(" {")
cog.outl(" switch (id)")
@ -492,24 +515,11 @@ namespace etl
cog.outl(" }")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" void receive(const etl::imessage& msg) ETL_OVERRIDE")
cog.outl(" {")
cog.outl(" receive(etl::null_message_router::instance(), msg);")
cog.outl(" }")
cog.outl(" using etl::imessage_router::receive;")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE")
cog.outl(" {")
cog.outl(" if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))")
cog.outl(" {")
cog.outl(" receive(source, msg);")
cog.outl(" }")
cog.outl(" }")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE")
cog.outl(" {")
cog.outl(" const size_t id = msg.message_id;")
cog.outl(" const size_t id = msg.get_message_id();")
cog.outl("")
cog.outl(" switch (id)")
cog.outl(" {")
@ -532,9 +542,9 @@ namespace etl
cog.outl(" }")
cog.outl(" }")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" using imessage_router::accepts;")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" bool accepts(etl::message_id_t id) const ETL_OVERRIDE")
cog.outl(" {")
cog.outl(" switch (id)")

View File

@ -369,7 +369,7 @@ namespace etl
/// Destroys the object.
//*************************************************************************
template <typename T>
bool destroy(const T* const p)
void destroy(const T* const p)
{
/*[[[cog
import cog
@ -395,12 +395,10 @@ namespace etl
if (pool.is_in_pool(vp))
{
pool.release(vp);
return true;
}
else
{
ETL_ASSERT(false, ETL_ERROR(variant_pool_did_not_create));
return false;
}
}

209
include/etl/generic_pool.h Normal file
View File

@ -0,0 +1,209 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2014 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_GENERIC_POOL_INCLUDED
#define ETL_GENERIC_POOL_INCLUDED
#include "platform.h"
#include "ipool.h"
#include "type_traits.h"
#include "static_assert.h"
#include "alignment.h"
#define ETL_POOL_CPP03_CODE 0
//*****************************************************************************
///\defgroup pool pool
/// A fixed capacity pool.
///\ingroup containers
//*****************************************************************************
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_>
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_SUPPORTED || ETL_POOL_CPP03_CODE || defined(ETL_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
//*************************************************************************
/// 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.
/// \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);
}
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 ETL_CONSTANT 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;
};
}
#endif

495
include/etl/ipool.h Normal file
View File

@ -0,0 +1,495 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2014 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_IPOOL_INCLUDED
#define ETL_IPOOL_INCLUDED
#include "platform.h"
#include "error_handler.h"
#include "exception.h"
#include "static_assert.h"
#include "utility.h"
#include "memory.h"
#include <new>
#undef ETL_FILE
#define ETL_FILE "11"
#define ETL_POOL_CPP03_CODE 0
//*****************************************************************************
///\defgroup pool pool
/// A fixed capacity pool.
///\ingroup containers
//*****************************************************************************
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_)
{}
};
//***************************************************************************
/// The base implementation of a pool.
/// Implements the imemory_block_pool interface.
//***************************************************************************
class ipool : public imemory_block_pool
{
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
/// 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_SUPPORTED || ETL_POOL_CPP03_CODE || defined(ETL_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.
/// 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'.
/// \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))
{
p_object->~T();
release_item((char*)p_object);
}
else
{
ETL_ALWAYS_ASSERT(ETL_ERROR(pool_object_not_in_pool));
}
}
//*************************************************************************
/// 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)
{
// 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));
}
}
//*************************************************************************
/// 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
{
return is_item_in_pool((const char*)p_object);
}
//*************************************************************************
/// 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)
{
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
};
}
#undef ETL_FILE
#endif

View File

@ -0,0 +1,53 @@
///\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_IREFERENCE_COUNTED_MESSAGE_POOL_INCLUDED
#define ETL_IREFERENCE_COUNTED_MESSAGE_POOL_INCLUDED
#include "platform.h"
namespace etl
{
class ireference_counted_message;
//***************************************************************************
/// Interface for a reference counted message pool.
//***************************************************************************
class ireference_counted_message_pool
{
public:
virtual void release(const etl::ireference_counted_message* const pmsg) = 0;
virtual void release(const etl::ireference_counted_message& msg) = 0;
};
}
#endif

View File

@ -1508,36 +1508,36 @@ namespace etl
//*****************************************************************************
// Global functions for unique_ptr
//*****************************************************************************
template<typename T1, typename D1, typename T2, typename D2>
bool operator ==(const etl::unique_ptr<T1, D1>&lhs, const etl::unique_ptr<T2, D2>& rhs)
template<typename T1, typename TD1, typename T2, typename TD2>
bool operator ==(const etl::unique_ptr<T1, TD1>&lhs, const etl::unique_ptr<T2, TD2>& rhs)
{
return lhs.get() == rhs.get();
}
//*********************************
template<typename T1, typename D1, typename T2, typename D2>
bool operator <(const etl::unique_ptr<T1, D1>&lhs, const etl::unique_ptr<T2, D2>& rhs)
template<typename T1, typename TD1, typename T2, typename TD2>
bool operator <(const etl::unique_ptr<T1, TD1>&lhs, const etl::unique_ptr<T2, TD2>& rhs)
{
return reinterpret_cast<char*>(lhs.get()) < reinterpret_cast<char*>(rhs.get());
}
//*********************************
template<typename T1, typename D1, typename T2, typename D2>
bool operator <=(const etl::unique_ptr<T1, D1>&lhs, const etl::unique_ptr<T2, D2>& rhs)
template<typename T1, typename TD1, typename T2, typename TD2>
bool operator <=(const etl::unique_ptr<T1, TD1>&lhs, const etl::unique_ptr<T2, TD2>& rhs)
{
return !(rhs < lhs);
}
//*********************************
template<typename T1, typename D1, typename T2, typename D2>
bool operator >(const etl::unique_ptr<T1, D1>&lhs, const etl::unique_ptr<T2, D2>& rhs)
template<typename T1, typename TD1, typename T2, typename TD2>
bool operator >(const etl::unique_ptr<T1, TD1>&lhs, const etl::unique_ptr<T2, TD2>& rhs)
{
return (rhs < lhs);
}
//*********************************
template<typename T1, typename D1, typename T2, typename D2>
bool operator >=(const etl::unique_ptr<T1, D1>&lhs, const etl::unique_ptr<T2, D2>& rhs)
template<typename T1, typename TD1, typename T2, typename TD2>
bool operator >=(const etl::unique_ptr<T1, TD1>&lhs, const etl::unique_ptr<T2, TD2>& rhs)
{
return !(lhs < rhs);
}
@ -1593,7 +1593,7 @@ namespace etl
///\ingroup memory
//*****************************************************************************
template <typename T>
void create_value_at(T* p)
void create_value_at(T* p)
{
::new (p) T();
}
@ -1603,7 +1603,7 @@ namespace etl
///\ingroup memory
//*****************************************************************************
template <typename T, typename TCounter>
void create_value_at(T* p, TCounter& count)
void create_value_at(T* p, TCounter& count)
{
::new (p) T();
++count;
@ -1614,7 +1614,7 @@ namespace etl
///\ingroup memory
//*****************************************************************************
template <typename T>
void create_copy_at(T* p, const T& value)
void create_copy_at(T* p, const T& value)
{
::new (p) T(value);
}
@ -1900,6 +1900,16 @@ namespace etl
}
};
//*************************************************************************
/// The interface for a memory block pool.
//*************************************************************************
struct imemory_block_pool
{
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() = 0;
};
//***************************************************************************
/// Declares an aligned buffer of N_OBJECTS x of size OBJECT_SIZE at alignment ALIGNMENT.
///\ingroup alignment

View File

@ -63,44 +63,37 @@ namespace etl
}
};
//***************************************************************************
// Message interface.
//***************************************************************************
class imessage
{
public:
imessage(etl::message_id_t id)
: message_id(id)
{
}
const etl::message_id_t message_id;
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
virtual ~imessage()
{
}
#else
~imessage()
{
}
#endif
ETL_NODISCARD virtual etl::message_id_t get_message_id() const ETL_NOEXCEPT = 0;
};
//***************************************************************************
template <const etl::message_id_t ID_>
// Message type.
//***************************************************************************
template <etl::message_id_t ID_>
class message : public imessage
{
public:
message()
: imessage(ID_)
{
}
enum
{
ID = ID_
};
ETL_NODISCARD etl::message_id_t get_message_id() const ETL_NOEXCEPT ETL_OVERRIDE
{
return ID;
}
};
}

View File

@ -147,13 +147,6 @@ namespace etl
}
}
//*******************************************
void receive(const etl::imessage& message) ETL_OVERRIDE
{
etl::null_message_router nmr;
receive(nmr, etl::imessage_router::ALL_MESSAGE_ROUTERS, message);
}
//*******************************************
void receive(etl::message_router_id_t destination_router_id,
const etl::imessage& message)
@ -187,7 +180,7 @@ namespace etl
{
etl::imessage_router& router = **irouter;
if (router.accepts(message.message_id))
if (router.accepts(message.get_message_id()))
{
router.receive(source, message);
}
@ -213,7 +206,7 @@ namespace etl
// Call all of them.
while (range.first != range.second)
{
if ((*(range.first))->accepts(message.message_id))
if ((*(range.first))->accepts(message.get_message_id()))
{
(*(range.first))->receive(source, message);
}

View File

@ -190,7 +190,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -219,7 +219,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -248,7 +248,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -403,7 +403,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -431,7 +431,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -459,7 +459,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -613,7 +613,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -640,7 +640,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -667,7 +667,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -820,7 +820,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -846,7 +846,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -872,7 +872,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -1023,7 +1023,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -1048,7 +1048,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -1073,7 +1073,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -1223,7 +1223,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -1247,7 +1247,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -1271,7 +1271,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -1420,7 +1420,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -1443,7 +1443,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -1466,7 +1466,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -1614,7 +1614,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -1636,7 +1636,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -1658,7 +1658,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -1804,7 +1804,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -1825,7 +1825,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -1846,7 +1846,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -1991,7 +1991,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -2011,7 +2011,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -2031,7 +2031,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -2175,7 +2175,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -2194,7 +2194,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -2213,7 +2213,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -2356,7 +2356,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -2374,7 +2374,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -2392,7 +2392,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -2533,7 +2533,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -2550,7 +2550,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -2567,7 +2567,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -2707,7 +2707,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -2723,7 +2723,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -2739,7 +2739,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -2878,7 +2878,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -2893,7 +2893,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -2908,7 +2908,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -3046,7 +3046,7 @@ namespace etl
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
pmsg->~imessage();
#else
size_t id = pmsg->message_id;
size_t id = pmsg->get_message_id();
switch (id)
{
@ -3060,7 +3060,7 @@ namespace etl
//********************************************
void add_new_message(const etl::imessage& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)
@ -3074,7 +3074,7 @@ namespace etl
//********************************************
void add_new_message(etl::imessage&& msg)
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
void* p = data;
switch (id)

View File

@ -55,6 +55,7 @@ SOFTWARE.
#include "platform.h"
#include "message.h"
#include "shared_message.h"
#include "message_packet.h"
#include "message_types.h"
#include "alignment.h"
@ -95,6 +96,13 @@ namespace etl
}
};
//***************************************************************************
/// Forward declare null message router functionality.
//***************************************************************************
class imessage_router;
etl::imessage_router& get_null_message_router();
//***************************************************************************
/// This is the base of all message routers.
//***************************************************************************
@ -103,18 +111,51 @@ namespace etl
public:
virtual ~imessage_router() {}
virtual void receive(const etl::imessage& message) = 0;
virtual void receive(imessage_router& source, const etl::imessage& message) = 0;
virtual void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message) = 0;
virtual bool accepts(etl::message_id_t id) const = 0;
virtual bool is_null_router() const = 0;
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))
{
receive(source, message);
}
}
//********************************************
void receive(const etl::imessage& message)
{
receive(etl::get_null_message_router(), message);
}
//********************************************
virtual void receive(imessage_router& source, etl::shared_message shared_msg)
{
receive(source, shared_msg.get_message());
}
//********************************************
void receive(etl::shared_message shared_msg)
{
receive(etl::get_null_message_router(), shared_msg);
}
//********************************************
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))
{
receive(source, shared_msg);
}
}
//********************************************
bool accepts(const etl::imessage& msg) const
{
return accepts(msg.message_id);
return accepts(msg.get_message_id());
}
//********************************************
@ -152,15 +193,15 @@ namespace etl
protected:
imessage_router(etl::message_router_id_t id_)
: successor(ETL_NULLPTR),
message_router_id(id_)
: successor(ETL_NULLPTR)
, message_router_id(id_)
{
}
imessage_router(etl::message_router_id_t id_,
imessage_router& successor_)
: successor(&successor_),
message_router_id(id_)
imessage_router& successor_)
: successor(&successor_)
, message_router_id(id_)
{
}
@ -188,21 +229,15 @@ namespace etl
}
//********************************************
void receive(const etl::imessage&) ETL_OVERRIDE
{
}
using etl::imessage_router::receive;
//********************************************
void receive(etl::imessage_router&, const etl::imessage&) ETL_OVERRIDE
{
}
//********************************************
void receive(imessage_router&, etl::message_router_id_t, const etl::imessage&) ETL_OVERRIDE
{
}
using etl::imessage_router::accepts;
//********************************************
bool accepts(etl::message_id_t) const ETL_OVERRIDE
{
return false;
@ -234,6 +269,13 @@ namespace etl
}
};
//***********************************************
/// null message router functionality.
inline etl::imessage_router& get_null_message_router()
{
return etl::null_message_router::instance();
}
//***************************************************************************
/// This router can be used as a producer-only of messages, such an interrupt routine.
//***************************************************************************
@ -247,21 +289,15 @@ namespace etl
}
//********************************************
void receive(const etl::imessage&) ETL_OVERRIDE
{
}
using etl::imessage_router::receive;
//********************************************
void receive(etl::imessage_router&, const etl::imessage&) ETL_OVERRIDE
{
}
//********************************************
void receive(imessage_router&, etl::message_router_id_t, const etl::imessage&) ETL_OVERRIDE
{
}
using etl::imessage_router::accepts;
//********************************************
bool accepts(etl::message_id_t) const ETL_OVERRIDE
{
return false;
@ -334,24 +370,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const etl::message_id_t id = msg.message_id;
const etl::message_id_t id = msg.get_message_id();
switch (id)
{
@ -386,9 +409,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -450,24 +473,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -501,9 +511,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -565,24 +575,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -615,9 +612,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -679,24 +676,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -728,9 +712,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -791,24 +775,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -839,9 +810,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -902,24 +873,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -949,9 +907,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -1012,24 +970,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -1058,9 +1003,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -1121,24 +1066,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -1166,9 +1098,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -1228,24 +1160,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -1272,9 +1191,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -1334,24 +1253,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -1377,9 +1283,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -1438,24 +1344,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -1480,9 +1373,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -1541,24 +1434,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -1582,9 +1462,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -1642,24 +1522,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -1682,9 +1549,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -1742,24 +1609,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -1781,9 +1635,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -1841,24 +1695,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -1879,9 +1720,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)
@ -1939,24 +1780,11 @@ namespace etl
}
//**********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::null_message_router::instance(), msg);
}
using etl::imessage_router::receive;
//**********************************************
void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(source, msg);
}
}
//**********************************************
void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE
{
const size_t id = msg.message_id;
const size_t id = msg.get_message_id();
switch (id)
{
@ -1976,9 +1804,9 @@ namespace etl
}
}
//**********************************************
using imessage_router::accepts;
//**********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
switch (id)

View File

@ -44,23 +44,23 @@ namespace etl
namespace private_multi_array
{
template <class T, size_t D1, size_t... Dx>
template <class T, size_t TD1, size_t... TDx>
struct multi_array_t
{
using type = etl::array<typename multi_array_t<T, Dx...>::type, D1>;
static constexpr size_t SIZE = D1;
using type = etl::array<typename multi_array_t<T, TDx...>::type, TD1>;
static constexpr size_t SIZE = TD1;
};
template <class T, size_t D1>
struct multi_array_t<T, D1>
template <class T, size_t TD1>
struct multi_array_t<T, TD1>
{
using type = etl::array<T, D1>;
static constexpr size_t SIZE = D1;
using type = etl::array<T, TD1>;
static constexpr size_t SIZE = TD1;
};
}
template <typename T, const size_t... Dx>
using multi_array = typename private_multi_array::multi_array_t<T, Dx...>::type;
template <typename T, const size_t... TDx>
using multi_array = typename private_multi_array::multi_array_t<T, TDx...>::type;
#endif
}

View File

@ -711,28 +711,37 @@ namespace etl
}
#endif
//*************************************************************************
/// Releases the object.
/// Undefined behaviour if the pool does not contain a 'U' object derived from 'U'.
/// \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::is_base_of<U, T>::value), "Pool does not contain this type");
base_t::template release(p_object);
}
//*************************************************************************
/// Destroys the object.
/// Undefined behaviour if the pool does not contain a 'U'.
/// Undefined behaviour if the pool does not contain a 'U' object derived from '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::is_base_of<U, T>::value), "Pool does not contain this type");
p_object->~U();
base_t::release(p_object);
base_t::template destroy(p_object);
}
private:
// Should not be copied.
pool(const pool&);
pool& operator =(const pool&);
pool(const pool&) ETL_DELETE;
pool& operator =(const pool&) ETL_DELETE;
};
}
#undef ETL_FILE
#endif

View File

@ -0,0 +1,195 @@
/******************************************************************************
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_REFERENCE_COUNTED_MESSAGE_INCLUDED
#define ETL_REFERENCE_COUNTED_MESSAGE_INCLUDED
#include <stdint.h>
#include "platform.h"
#include "message.h"
#include "atomic.h"
#include "reference_counted_object.h"
#include "ireference_counted_message_pool.h"
namespace etl
{
//***************************************************************************
// Base class for all reference counted messages.
//***************************************************************************
class ireference_counted_message
{
public:
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.
virtual void release() = 0; ///< Release back to the owner.
};
//***************************************************************************
// Reference counted message type.
//***************************************************************************
template <typename TMessage, typename TCounter>
class reference_counted_message : public etl::ireference_counted_message
{
public:
typedef TMessage message_type;
typedef TCounter counter_type;
//***************************************************************************
/// Constructor
/// \param msg The message to count.
//***************************************************************************
reference_counted_message(const TMessage& msg_, etl::ireference_counted_message_pool& owner_)
: rc_object(msg_)
, owner(owner_)
{
}
//***************************************************************************
/// Get a const reference to the message.
/// \return A const reference to the message.
//***************************************************************************
virtual ETL_NODISCARD const TMessage& get_message() const ETL_OVERRIDE
{
return rc_object.get_object();
}
//***************************************************************************
/// Get a reference to the reference counter.
/// \return A reference to the reference counter.
//***************************************************************************
virtual ETL_NODISCARD etl::ireference_counter& get_reference_counter() ETL_OVERRIDE
{
return rc_object.get_reference_counter();
}
//***************************************************************************
/// Get a const reference to the reference counter.
/// \return A const reference to the reference counter.
//***************************************************************************
virtual ETL_NODISCARD const etl::ireference_counter& get_reference_counter() const ETL_OVERRIDE
{
return rc_object.get_reference_counter();
}
//***************************************************************************
/// Release back to the owner pool.
/// \return A reference to the owner pool.
//***************************************************************************
virtual void release() ETL_OVERRIDE
{
owner.release(*this);
}
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.
};
//***************************************************************************
/// Persistent message type.
/// The message type will always have a reference count of 1.
/// \tparam TMessage The message type stored.
//***************************************************************************
template <typename TMessage>
class persistent_message : virtual public etl::ireference_counted_message
{
public:
typedef TMessage message_type;
//***************************************************************************
/// Constructor
/// \param msg The message to count.
//***************************************************************************
persistent_message(const TMessage& msg_)
: rc_object(msg_)
{
}
//***************************************************************************
/// Get a const reference to the message.
/// \return A const reference to the message.
//***************************************************************************
virtual ETL_NODISCARD const TMessage& get_message() const ETL_OVERRIDE
{
return rc_object.get_object();
}
//***************************************************************************
/// Get a reference to the reference counter.
/// \return A reference to the reference counter.
//***************************************************************************
virtual ETL_NODISCARD etl::ireference_counter& get_reference_counter() ETL_OVERRIDE
{
return rc_object.get_reference_counter();
}
//***************************************************************************
/// Get a const reference to the reference counter.
/// \return A const reference to the reference counter.
//***************************************************************************
virtual ETL_NODISCARD const etl::ireference_counter& get_reference_counter() const ETL_OVERRIDE
{
return rc_object.get_reference_counter();
}
//***************************************************************************
/// Release back to the owner pool.
/// \return A reference to the owner pool.
//***************************************************************************
virtual void release() ETL_OVERRIDE
{
// Do nothing.
}
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;
etl::persistent_object<TMessage> rc_object; ///< The reference counted object.
};
#if ETL_CPP11_SUPPORTED && ETL_HAS_ATOMIC
//***************************************************************************
/// Class for creating reference counted objects using an atomic counter.
/// \tparam TObject The type to be reference counted.
//***************************************************************************
template <typename TMessage>
using atomic_counted_message = etl::reference_counted_message<TMessage, etl::atomic_int32_t>;
#endif
}
#endif

View File

@ -0,0 +1,150 @@
///\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_REFERENCE_COUNTED_MESSAGE_POOL_INCLUDED
#define ETL_REFERENCE_COUNTED_MESSAGE_POOL_INCLUDED
#include "platform.h"
#include "message.h"
#include "ireference_counted_message_pool.h"
#include "reference_counted_message.h"
#include "static_assert.h"
#include "error_handler.h"
#include "utility.h"
#include "memory.h"
#define ETL_FILE "57"
namespace etl
{
//***************************************************************************
///
//***************************************************************************
class reference_counted_message_pool_allocation_exception : public etl::exception
{
public:
reference_counted_message_pool_allocation_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};
//***************************************************************************
///
//***************************************************************************
class reference_counted_message_pool_allocation_failure : etl::reference_counted_message_pool_allocation_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_)
{
}
};
//***************************************************************************
/// A pool for allocating reference counted messages.
//***************************************************************************
template <typename TCounter>
class reference_counted_message_pool : public ireference_counted_message_pool
{
public:
//*************************************************************************
/// Constructor
//*************************************************************************
reference_counted_message_pool(imemory_block_pool& memory_block_pool_)
: memory_block_pool(memory_block_pool_)
{
}
//*************************************************************************
/// Allocate a reference counted message from the pool.
//*************************************************************************
template <typename TMessage>
etl::ireference_counted_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 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)));
if (p != ETL_NULLPTR)
{
::new(p) rcm_t(message, *this);
}
}
ETL_ASSERT((p != ETL_NULLPTR), ETL_ERROR(etl::message_pool_allocation_failure));
return p;
}
//*************************************************************************
/// Destruct a message and send it back to the pool.
//*************************************************************************
void release(const etl::ireference_counted_message* const p_rcmessage)
{
if (p_rcmessage != ETL_NULLPTR)
{
p_rcmessage->~ireference_counted_message();
memory_block_pool.release_memory_block(p_rcmessage);
}
}
//*************************************************************************
/// Destruct a message and send it back to the pool.
//*************************************************************************
void release(const etl::ireference_counted_message& msg)
{
release(&msg);
}
private:
/// The raw memory block pool.
imemory_block_pool& memory_block_pool;
// 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;
};
}
#undef ETL_FILE
#endif

View File

@ -0,0 +1,279 @@
///******************************************************************************
//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_REFERENCE_COUNTED_OBJECT_INCLUDED
#define ETL_REFERENCE_COUNTED_OBJECT_INCLUDED
#include <stdint.h>
#include "platform.h"
#include "atomic.h"
namespace etl
{
//***************************************************************************
/// The base of all reference counters.
//***************************************************************************
class ireference_counter
{
public:
virtual ~ireference_counter() {};
virtual void set_reference_count(int32_t value) = 0;
virtual void increment_reference_count() = 0;
ETL_NODISCARD virtual int32_t decrement_reference_count() = 0;
ETL_NODISCARD virtual int32_t get_reference_count() const = 0;
};
//***************************************************************************
/// A specific type of reference counter.
//***************************************************************************
template <typename TCounter>
class reference_counter : public ireference_counter
{
public:
//***************************************************************************
/// Constructor.
//***************************************************************************
reference_counter()
: reference_count(0)
{
}
//***************************************************************************
/// Set the reference count.
//***************************************************************************
virtual void set_reference_count(int32_t value) ETL_OVERRIDE
{
reference_count = value;
}
//***************************************************************************
/// Increment the reference count.
//***************************************************************************
virtual void increment_reference_count() ETL_OVERRIDE
{
++reference_count;
}
//***************************************************************************
/// Decrement the reference count.
//***************************************************************************
ETL_NODISCARD virtual int32_t decrement_reference_count() ETL_OVERRIDE
{
assert(reference_count > 0);
return int32_t(--reference_count);
}
//***************************************************************************
/// Get the current reference count.
//***************************************************************************
ETL_NODISCARD virtual int32_t get_reference_count() const ETL_OVERRIDE
{
return int32_t(reference_count);
}
private:
TCounter reference_count; // The reference count object.
};
//***************************************************************************
/// A null reference counter.
/// Always returns the reference count as 1, for persistent objects.
//***************************************************************************
class null_reference_counter : public ireference_counter
{
public:
//***************************************************************************
/// Set the reference count.
//***************************************************************************
virtual void set_reference_count(int32_t value) ETL_OVERRIDE
{
}
//***************************************************************************
/// Increment the reference count.
//***************************************************************************
virtual void increment_reference_count() ETL_OVERRIDE
{
}
//***************************************************************************
/// Decrement the reference count.
//***************************************************************************
ETL_NODISCARD virtual int32_t decrement_reference_count() ETL_OVERRIDE
{
return int32_t(1);
}
//***************************************************************************
/// Get the current reference count.
//***************************************************************************
ETL_NODISCARD virtual int32_t get_reference_count() const ETL_OVERRIDE
{
return int32_t(1);
}
};
//***************************************************************************
/// Base for all reference counted objects.
//***************************************************************************
class ireference_counted_object
{
public:
ETL_NODISCARD virtual ireference_counter& get_reference_counter() = 0;
ETL_NODISCARD virtual const ireference_counter& get_reference_counter() const = 0;
};
//***************************************************************************
/// Class for creating reference counted objects.
/// \tparam TObject The type to be reference counted.
/// \tparam TCounter The type to use as the counter.
//***************************************************************************
template <typename TObject, typename TCounter>
class reference_counted_object : public etl::ireference_counted_object
{
public:
typedef TObject value_type;
typedef TCounter counter_type;
//***************************************************************************
/// Constructor.
//***************************************************************************
reference_counted_object(const TObject& object_)
: object(object_)
{
}
//***************************************************************************
/// Get a const reference to the counted object.
//***************************************************************************
ETL_NODISCARD const value_type& get_object() const
{
return object;
}
//***************************************************************************
/// Get a reference to the reference counter.
//***************************************************************************
virtual ETL_NODISCARD ireference_counter& get_reference_counter() ETL_OVERRIDE
{
return reference_counter;
}
//***************************************************************************
/// Get a const reference to the reference counter.
//***************************************************************************
virtual ETL_NODISCARD const ireference_counter& get_reference_counter() const ETL_OVERRIDE
{
return reference_counter;
}
private:
// This class must not be default contructed, copy constructed or assigned.
reference_counted_object() ETL_DELETE;
reference_counted_object(const reference_counted_object&) ETL_DELETE;
reference_counted_object& operator =(const reference_counted_object&) ETL_DELETE;
const TObject object; ///< The object being reference counted.
etl::reference_counter<TCounter> reference_counter; ///< The reference counter.
};
//***************************************************************************
/// Persistent message type.
/// The message type will always have a reference count of 1.
/// \tparam TObject The type stored in the object.
//***************************************************************************
template <typename TObject>
class persistent_object : public etl::ireference_counted_object
{
public:
typedef TObject value_type;
//***************************************************************************
/// Constructor.
//***************************************************************************
persistent_object(const TObject& object_)
: object(object_)
{
}
//***************************************************************************
/// Get a const reference to the counted object.
//***************************************************************************
ETL_NODISCARD const value_type& get_object() const
{
return object;
}
//***************************************************************************
/// Get a reference to the reference counter.
//***************************************************************************
virtual ETL_NODISCARD ireference_counter& get_reference_counter() ETL_OVERRIDE
{
return reference_counter;
}
//***************************************************************************
/// Get a const reference to the reference counter.
//***************************************************************************
virtual ETL_NODISCARD const ireference_counter& get_reference_counter() const ETL_OVERRIDE
{
return reference_counter;
}
private:
// This class must not be default contructed, copy constructed or assigned.
persistent_object() ETL_DELETE;
persistent_object(const persistent_object&) ETL_DELETE;
persistent_object& operator =(const persistent_object&) ETL_DELETE;
TObject object; ///< The object being reference counted.
etl::null_reference_counter reference_counter; ///< The reference counter.
};
#if ETL_CPP11_SUPPORTED && ETL_HAS_ATOMIC
//***************************************************************************
/// Class for creating reference counted objects using an atomic counter.
/// \tparam TObject The type to be reference counted.
//***************************************************************************
template <typename TObject>
using atomic_counted_object = etl::reference_counted_object<TObject, etl::atomic_int32_t>;
#endif
}
#endif

View File

@ -0,0 +1,151 @@
///\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_SHARED_MESSAGE_INCLUDED
#define ETL_SHARED_MESSAGE_INCLUDED
#include "platform.h"
#include "utility.h"
#include "reference_counted_message.h"
//*****************************************************************************
/// A wrapper for reference counted messages.
/// Contains pointers to a pool owner and a message defined with a ref count type.
//*****************************************************************************
namespace etl
{
class shared_message
{
public:
//*************************************************************************
/// Constructor
/// \param message A reference to the message allocated from the pool.
//*************************************************************************
shared_message(etl::ireference_counted_message& rcmessage_)
: p_rcmessage(&rcmessage_)
{
p_rcmessage->get_reference_counter().set_reference_count(1U);
}
//*************************************************************************
/// Copy constructor
//*************************************************************************
shared_message(const shared_message& other)
: p_rcmessage(other.p_rcmessage)
{
p_rcmessage->get_reference_counter().increment_reference_count();
}
//*************************************************************************
/// Copy assignment operator
//*************************************************************************
shared_message& operator =(const shared_message& other)
{
if (&other != this)
{
// Deal with the current message.
if (p_rcmessage->get_reference_counter().decrement_reference_count() == 0U)
{
p_rcmessage->release();
}
// Copy over the new one.
p_rcmessage = other.p_rcmessage;
p_rcmessage->get_reference_counter().increment_reference_count();
}
return *this;
}
//*************************************************************************
/// Destructor
/// Returns the message back to the pool it it is the last copy.
//*************************************************************************
~shared_message()
{
if (p_rcmessage->get_reference_counter().decrement_reference_count() == 0U)
{
p_rcmessage->release();
}
}
//*************************************************************************
/// Get a const reference to the contained message.
//*************************************************************************
const etl::imessage& get_message() const
{
return p_rcmessage->get_message();
}
//*************************************************************************
/// Get the current reference count for this shared message.
//*************************************************************************
uint32_t get_reference_count() const
{
return p_rcmessage->get_reference_counter().get_reference_count();
}
private:
shared_message() ETL_DELETE;
etl::ireference_counted_message* p_rcmessage;
};
//*****************************************************************************
/// 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

View File

@ -54,55 +54,13 @@ SOFTWARE.
#include <stdint.h>
#include "platform.h"
#include "error_handler.h"
#include "exception.h"
#include "largest.h"
#include "generic_pool.h"
#include "type_traits.h"
#include "alignment.h"
#include "static_assert.h"
#include "type_lookup.h"
#include "pool.h"
#include "utility.h"
#undef ETL_FILE
#define ETL_FILE "40"
#include "largest.h"
namespace etl
{
//***************************************************************************
class variant_pool_exception : public etl::exception
{
public:
variant_pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};
//***************************************************************************
class variant_pool_cannot_create : public etl::variant_pool_exception
{
public:
variant_pool_cannot_create(string_type file_name_, numeric_type line_number_)
: variant_pool_exception(ETL_ERROR_TEXT("variant_pool:cannot create", ETL_FILE"A"), file_name_, line_number_)
{
}
};
//***************************************************************************
class variant_pool_did_not_create : public etl::variant_pool_exception
{
public:
variant_pool_did_not_create(string_type file_name_, numeric_type line_number_)
: variant_pool_exception(ETL_ERROR_TEXT("variant_pool:did not create", ETL_FILE"B"), file_name_, line_number_)
{
}
};
//***************************************************************************
template <const size_t MAX_SIZE_,
typename T1,
@ -121,10 +79,16 @@ namespace etl
typename T14 = void,
typename T15 = void,
typename T16 = void>
class variant_pool
class variant_pool : public etl::generic_pool<etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::size,
etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::alignment,
MAX_SIZE_>
{
public:
typedef etl::generic_pool<etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::size,
etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::alignment,
MAX_SIZE_> base_t;
static const size_t MAX_SIZE = MAX_SIZE_;
//*************************************************************************
@ -143,23 +107,7 @@ namespace etl
{
ETL_STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
T* p = ETL_NULLPTR;
if (pool.full())
{
ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
}
else
{
p = pool.template allocate<T>();
if (p != ETL_NULLPTR)
{
new (p) T();
}
}
return p;
return base_t::template create<T>();
}
//*************************************************************************
@ -170,23 +118,7 @@ namespace etl
{
ETL_STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
T* p = ETL_NULLPTR;
if (pool.full())
{
ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
}
else
{
p = pool.template allocate<T>();
if (p != ETL_NULLPTR)
{
new (p) T(p1);
}
}
return p;
return base_t::template create<T>(p1);
}
//*************************************************************************
@ -197,23 +129,7 @@ namespace etl
{
ETL_STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
T* p = ETL_NULLPTR;
if (pool.full())
{
ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
}
else
{
p = pool.template allocate<T>();
if (p != ETL_NULLPTR)
{
new (p) T(p1, p2);
}
}
return p;
return base_t::template create<T>(p1, p2);
}
//*************************************************************************
@ -224,23 +140,7 @@ namespace etl
{
ETL_STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
T* p = ETL_NULLPTR;
if (pool.full())
{
ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
}
else
{
p = pool.template allocate<T>();
if (p != ETL_NULLPTR)
{
new (p) T(p1, p2, p3);
}
}
return p;
return base_t::template create<T>(p1, p2, p3);
}
//*************************************************************************
@ -251,23 +151,7 @@ namespace etl
{
ETL_STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
T* p = ETL_NULLPTR;
if (pool.full())
{
ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
}
else
{
p = pool.template allocate<T>();
if (p != ETL_NULLPTR)
{
new (p) T(p1, p2, p3, p4);
}
}
return p;
return base_t::template create<T>(p1, p2, p3, p4);
}
#else
//*************************************************************************
@ -278,23 +162,7 @@ namespace etl
{
ETL_STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
T* p = ETL_NULLPTR;
if (pool.full())
{
ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
}
else
{
p = pool.template allocate<T>();
if (p != ETL_NULLPTR)
{
new (p) T(etl::forward<Args>(args)...);
}
}
return p;
return base_t::template create<T>(args...);
}
#endif
@ -302,40 +170,27 @@ namespace etl
/// Destroys the object.
//*************************************************************************
template <typename T>
bool destroy(const T* const p)
void destroy(const T* const p)
{
ETL_STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value ||
etl::is_base_of<T, T1>::value ||
etl::is_base_of<T, T2>::value ||
etl::is_base_of<T, T3>::value ||
etl::is_base_of<T, T4>::value ||
etl::is_base_of<T, T5>::value ||
etl::is_base_of<T, T6>::value ||
etl::is_base_of<T, T7>::value ||
etl::is_base_of<T, T8>::value ||
etl::is_base_of<T, T9>::value ||
etl::is_base_of<T, T10>::value ||
etl::is_base_of<T, T11>::value ||
etl::is_base_of<T, T12>::value ||
etl::is_base_of<T, T13>::value ||
etl::is_base_of<T, T14>::value ||
etl::is_base_of<T, T15>::value ||
etl::is_base_of<T, T16>::value), "Invalid type");
etl::is_base_of<T, T1>::value ||
etl::is_base_of<T, T2>::value ||
etl::is_base_of<T, T3>::value ||
etl::is_base_of<T, T4>::value ||
etl::is_base_of<T, T5>::value ||
etl::is_base_of<T, T6>::value ||
etl::is_base_of<T, T7>::value ||
etl::is_base_of<T, T8>::value ||
etl::is_base_of<T, T9>::value ||
etl::is_base_of<T, T10>::value ||
etl::is_base_of<T, T11>::value ||
etl::is_base_of<T, T12>::value ||
etl::is_base_of<T, T13>::value ||
etl::is_base_of<T, T14>::value ||
etl::is_base_of<T, T15>::value ||
etl::is_base_of<T, T16>::value), "Invalid type");
p->~T();
void* vp = reinterpret_cast<char*>(const_cast<T*>(p));
if (pool.is_in_pool(vp))
{
pool.release(vp);
return true;
}
else
{
ETL_ASSERT(false, ETL_ERROR(variant_pool_did_not_create));
return false;
}
base_t::destroy(p);
}
//*************************************************************************
@ -346,52 +201,11 @@ namespace etl
return MAX_SIZE;
}
//*************************************************************************
/// Returns the number of free items in the variant_pool.
//*************************************************************************
size_t available() const
{
return pool.available();
}
//*************************************************************************
/// Returns the number of allocated items in the variant_pool.
//*************************************************************************
size_t size() const
{
return pool.size();
}
//*************************************************************************
/// Checks to see if there are no allocated items in the variant_pool.
/// \return <b>true</b> if there are none allocated.
//*************************************************************************
bool empty() const
{
return pool.empty();
}
//*************************************************************************
/// Checks to see if there are no free items in the variant_pool.
/// \return <b>true</b> if there are none free.
//*************************************************************************
bool full() const
{
return pool.full();
}
private:
variant_pool(const variant_pool&);
variant_pool& operator =(const variant_pool&);
// The pool.
etl::generic_pool<etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::size,
etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::alignment,
MAX_SIZE> pool;
variant_pool(const variant_pool&) ETL_DELETE;
variant_pool& operator =(const variant_pool&) ETL_DELETE;
};
}
#undef ETL_FILE
#endif

View File

@ -201,9 +201,9 @@ namespace
// The next line should result in a compile error.
//Packet packet4(message4);
CHECK_EQUAL(MESSAGE1, packet1.get().message_id);
CHECK_EQUAL(MESSAGE2, packet2.get().message_id);
CHECK_EQUAL(MESSAGE3, packet3.get().message_id);
CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id());
CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id());
CHECK_EQUAL(MESSAGE3, packet3.get().get_message_id());
CHECK(!static_cast<Message1&>(packet1.get()).moved);
CHECK(!static_cast<Message2&>(packet2.get()).moved);
@ -227,8 +227,8 @@ namespace
Packet packet1(message1);
Packet packet2(std::move(message2));
CHECK_EQUAL(MESSAGE1, packet1.get().message_id);
CHECK_EQUAL(MESSAGE2, packet2.get().message_id);
CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id());
CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id());
CHECK(!static_cast<Message1&>(packet1.get()).moved);
CHECK(static_cast<Message2&>(packet2.get()).moved);
@ -255,9 +255,9 @@ namespace
// The next line should result in a compile error.
//Packet packet4(message4);
CHECK_EQUAL(MESSAGE1, packet1.get().message_id);
CHECK_EQUAL(MESSAGE2, packet2.get().message_id);
CHECK_EQUAL(MESSAGE3, packet3.get().message_id);
CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id());
CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id());
CHECK_EQUAL(MESSAGE3, packet3.get().get_message_id());
CHECK_EQUAL(1, static_cast<const Message1&>(packet1.get()).x);
CHECK_EQUAL(2.2, static_cast<const Message2&>(packet2.get()).x);
@ -278,9 +278,9 @@ namespace
CHECK_THROW(Packet packet4(static_cast<etl::imessage&>(message4)), etl::unhandled_message_exception);
CHECK_EQUAL(MESSAGE1, packet1.get().message_id);
CHECK_EQUAL(MESSAGE2, packet2.get().message_id);
CHECK_EQUAL(MESSAGE3, packet3.get().message_id);
CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id());
CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id());
CHECK_EQUAL(MESSAGE3, packet3.get().get_message_id());
CHECK_EQUAL(1, static_cast<Message1&>(packet1.get()).x);
CHECK_EQUAL(2.2, static_cast<Message2&>(packet2.get()).x);
@ -296,8 +296,8 @@ namespace
Packet packet1(message1);
Packet packet2(packet1);
CHECK_EQUAL(MESSAGE1, packet1.get().message_id);
CHECK_EQUAL(MESSAGE1, packet2.get().message_id);
CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id());
CHECK_EQUAL(MESSAGE1, packet2.get().get_message_id());
CHECK(!static_cast<Message1&>(packet1.get()).moved);
CHECK(!static_cast<Message1&>(packet2.get()).moved);
@ -318,8 +318,8 @@ namespace
Packet packet1(message1);
Packet packet2(std::move(Packet(message1)));
CHECK_EQUAL(MESSAGE1, packet1.get().message_id);
CHECK_EQUAL(MESSAGE1, packet2.get().message_id);
CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id());
CHECK_EQUAL(MESSAGE1, packet2.get().get_message_id());
CHECK(!static_cast<Message1&>(packet1.get()).moved);
CHECK(static_cast<Message1&>(packet2.get()).moved);
@ -342,8 +342,8 @@ namespace
packet2 = packet1;
CHECK_EQUAL(MESSAGE1, packet1.get().message_id);
CHECK_EQUAL(MESSAGE1, packet2.get().message_id);
CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id());
CHECK_EQUAL(MESSAGE1, packet2.get().get_message_id());
CHECK(!static_cast<Message1&>(packet1.get()).moved);
CHECK(!static_cast<Message1&>(packet2.get()).moved);
@ -366,8 +366,8 @@ namespace
packet2 = std::move(packet1);
CHECK_EQUAL(MESSAGE1, packet1.get().message_id);
CHECK_EQUAL(MESSAGE1, packet2.get().message_id);
CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id());
CHECK_EQUAL(MESSAGE1, packet2.get().get_message_id());
CHECK(!static_cast<Message1&>(packet1.get()).moved);
CHECK(static_cast<Message1&>(packet2.get()).moved);

View File

@ -416,19 +416,19 @@ namespace
Router2 r2;
CHECK(r2.accepts(message1));
CHECK(r2.accepts(message1.message_id));
CHECK(r2.accepts(message1.get_message_id()));
CHECK(r2.accepts(message2));
CHECK(r2.accepts(message2.message_id));
CHECK(r2.accepts(message2.get_message_id()));
CHECK(!r2.accepts(message3));
CHECK(!r2.accepts(message3.message_id));
CHECK(!r2.accepts(message3.get_message_id()));
CHECK(r2.accepts(message4));
CHECK(r2.accepts(message4.message_id));
CHECK(r2.accepts(message4.get_message_id()));
CHECK(r2.accepts(message5));
CHECK(r2.accepts(message5.message_id));
CHECK(r2.accepts(message5.get_message_id()));
}
//*************************************************************************

221
test/test_pool_message.cpp Normal file
View File

@ -0,0 +1,221 @@
/******************************************************************************
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());
//}
}

View File

@ -202,7 +202,7 @@ namespace
CHECK(!variant_pool.empty());
CHECK(variant_pool.full());
CHECK_THROW(variant_pool.create<Derived1>(), etl::variant_pool_cannot_create);
CHECK_THROW(variant_pool.create<Derived1>(), etl::pool_no_allocation);
}
//*************************************************************************
@ -309,7 +309,7 @@ namespace
CHECK_NO_THROW(variant_pool1.destroy(p));
p = variant_pool2.create<Derived1>();
CHECK_THROW(variant_pool1.destroy(p), etl::variant_pool_did_not_create);
CHECK_THROW(variant_pool1.destroy(p), etl::pool_object_not_in_pool);
}
};
}

View File

@ -1286,11 +1286,16 @@
<ClInclude Include="..\..\include\etl\generators\type_select_generator.h" />
<ClInclude Include="..\..\include\etl\generators\type_traits_generator.h" />
<ClInclude Include="..\..\include\etl\generators\variant_pool_generator.h" />
<ClInclude Include="..\..\include\etl\generic_pool.h" />
<ClInclude Include="..\..\include\etl\indirect_vector.h" />
<ClInclude Include="..\..\include\etl\absolute.h" />
<ClInclude Include="..\..\include\etl\ipool.h" />
<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\message_packet.h" />
<ClInclude Include="..\..\include\etl\message_pool.h" />
<ClInclude Include="..\..\include\etl\multi_array.h" />
<ClInclude Include="..\..\include\etl\multi_range.h" />
<ClInclude Include="..\..\include\etl\mutex\mutex_clang_sync.h" />
@ -1323,7 +1328,12 @@
<ClInclude Include="..\..\include\etl\profiles\msvc_x86_no_stl.h" />
<ClInclude Include="..\..\include\etl\profiles\ticc_no_stl.h" />
<ClInclude Include="..\..\include\etl\queue_spsc_locked.h" />
<ClInclude Include="..\..\include\etl\reference_counted_message.h" />
<ClInclude Include="..\..\include\etl\reference_counted_message_pool.h" />
<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" />
@ -1905,6 +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_priority_queue.cpp" />
<ClCompile Include="..\test_queue.cpp" />
<ClCompile Include="..\test_queue_memory_model_small.cpp" />

View File

@ -909,6 +909,36 @@
<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>
<ClInclude Include="..\..\include\etl\reference_counted_message.h">
<Filter>ETL\Frameworks</Filter>
</ClInclude>
<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">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\generic_pool.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\main.cpp">
@ -1445,6 +1475,9 @@
<ClCompile Include="..\test_multi_range.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\test_pool_message.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\library.properties">