Interim commit

This commit is contained in:
John Wellbelove 2021-01-01 17:07:53 +00:00
parent eeb057a99d
commit 5abae28f16
6 changed files with 795 additions and 108 deletions

View File

@ -64,6 +64,8 @@ namespace etl
}
};
//***************************************************************************
// Message interface.
//***************************************************************************
class imessage
{
@ -77,87 +79,83 @@ namespace etl
};
//***************************************************************************
class ireference_counted_message : public etl::imessage, public etl::ireference_counted_object
{
};
// Message type.
//***************************************************************************
template <typename TCounter>
class reference_counted_message : public etl::ireference_counted_message
template <etl::message_id_t ID_>
class message : public imessage
{
public:
reference_counted_message()
: reference_count(TCounter())
enum
{
ID = ID_
};
ETL_NODISCARD etl::message_id_t get_message_id() const ETL_NOEXCEPT ETL_OVERRIDE
{
return ID;
}
};
class ireference_counted_message
{
public:
virtual etl::imessage* get_message() = 0;
virtual const etl::imessage* get_message() const = 0;
virtual ~ireference_counted_message() {};
virtual void set_reference_count(uint32_t value) = 0;
virtual void increment_reference_count() = 0;
ETL_NODISCARD virtual uint32_t decrement_reference_count() = 0;
ETL_NODISCARD virtual uint32_t get_reference_count() const = 0;
};
//*******************************************************
template <typename TMessage, typename TCounter>
class reference_counted_message : virtual public ireference_counted_message
{
public:
reference_counted_message(const TMessage& msg_)
: msg(msg_)
{
reference_count = 0;
}
private:
virtual TMessage* get_message() ETL_OVERRIDE
{
return &msg;
}
//***************************************************************************
void set_reference_count(uint32_t value) ETL_OVERRIDE
virtual const TMessage* get_message() const ETL_OVERRIDE
{
return &msg;
}
virtual void set_reference_count(uint32_t value) ETL_OVERRIDE
{
reference_count = value;
}
//***************************************************************************
void increment_reference_count() ETL_OVERRIDE
virtual void increment_reference_count() ETL_OVERRIDE
{
++reference_count;
}
//***************************************************************************
ETL_NODISCARD uint32_t decrement_reference_count() ETL_OVERRIDE
ETL_NODISCARD virtual uint32_t decrement_reference_count() ETL_OVERRIDE
{
return uint32_t(--reference_count);
}
//***************************************************************************
ETL_NODISCARD uint32_t get_reference_count() const ETL_OVERRIDE
ETL_NODISCARD virtual uint32_t get_reference_count() const ETL_OVERRIDE
{
return uint32_t(reference_count);
}
/// The reference counter.
private:
TCounter reference_count;
};
//***************************************************************************
// Reference counted message.
//***************************************************************************
template <etl::message_id_t ID_, typename TCounter = void>
class message : public reference_counted_message<TCounter>
{
public:
enum
{
ID = ID_
};
ETL_NODISCARD etl::message_id_t get_message_id() const ETL_NOEXCEPT
{
return ID;
}
};
//***************************************************************************
// Non-reference counted message.
//***************************************************************************
template <etl::message_id_t ID_>
class message<ID_, void> : public imessage
{
public:
enum
{
ID = ID_
};
ETL_NODISCARD etl::message_id_t get_message_id() const ETL_NOEXCEPT
{
return ID;
}
TMessage msg;
};
}

View File

@ -36,6 +36,9 @@ SOFTWARE.
#include "static_assert.h"
#include "error_handler.h"
#include "utility.h"
#include "memory.h"
#define ETL_FILE "99"
namespace etl
{
@ -97,7 +100,7 @@ namespace etl
if (p != ETL_NULLPTR)
{
::new(p) TMessage(etl::forward<Args>(args)...);
::new(p) TMessage(etl::forward<TArgs>(args)...);
}
else
{

View File

@ -0,0 +1,322 @@
///\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 "static_assert.h"
#include "error_handler.h"
#include "utility.h"
#include "memory.h"
#include <iostream>
#define ETL_FILE "99"
namespace etl
{
////***************************************************************************
/////
////***************************************************************************
//class message_pool_allocation_exception : public etl::exception
//{
//public:
// message_pool_allocation_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
// : exception(reason_, file_name_, line_number_)
// {
// }
//};
////***************************************************************************
/////
////***************************************************************************
//class message_pool_allocation_failure : etl::message_pool_allocation_exception
//{
//public:
// message_pool_allocation_failure(string_type file_name_, numeric_type line_number_)
// : message_pool_allocation_exception(ETL_ERROR_TEXT("message_pool:allocation failure", ETL_FILE"A"), file_name_, line_number_)
// {
// }
//};
//***************************************************************************
///
//***************************************************************************
class ireference_counted_message_pool
{
public:
virtual void destroy(const etl::ireference_counted_message* const pmsg) = 0;
virtual void destroy(const etl::ireference_counted_message& msg) = 0;
};
//***************************************************************************
///
//***************************************************************************
class null_reference_counted_message_pool : public ireference_counted_message_pool
{
public:
void destroy(const etl::ireference_counted_message* const pmsg) ETL_OVERRIDE
{
std::cout << "null_reference_counted_message_pool : destroy\n";
}
void destroy(const etl::ireference_counted_message& msg) ETL_OVERRIDE
{
std::cout << "null_reference_counted_message_pool : destroy\n";
}
};
//***************************************************************************
///
//***************************************************************************
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_)
//{
//}
#if ETL_CPP11_SUPPORTED && !defined(ETL_MESSAGE_POOL_FORCE_CPP03)
//*************************************************************************
/// Create a message from the pool.
//*************************************************************************
template <typename TMessage, typename... TArgs>
etl::ireference_counted_message* create(TArgs&&... args)
{
//ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage>::value), "Not a message type");
using ref_message_t = etl::reference_counted_message<TMessage, TCounter>;
etl::ireference_counted_message* p = ETL_NULLPTR;
//if (sizeof(ref_message_t) <= memory_block_pool.get_memory_block_size(ref_message_t))
//{
// p = memory_block_pool.allocate_memory_block(sizeof(ref_message_t));
// if (p != ETL_NULLPTR)
// {
// ::new(p) ref_message_t(TMessage(etl::forward<TArgs>(args)...));
p = ::new ref_message_t(TMessage(etl::forward<TArgs>(args)...));
// }
// else
// {
// ETL_ALWAYS_ASSERT(ETL_ERROR(etl::message_pool_allocation_failure));
// }
//}
return p;
}
#else
//*************************************************************************
/// Create a message from the pool. No parameters.
//*************************************************************************
template <typename TMessage>
TMessage* create()
{
ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TMessage>::value), "Not a message type");
void* p = ETL_NULLPTR;
if (sizeof(TMessage) <= memory_block_pool.get_memory_block_size())
{
p = memory_block_pool.allocate_memory_block(sizeof(TMessage));
if (p != ETL_NULLPTR)
{
::new(p) TMessage();
}
else
{
ETL_ALWAYS_ASSERT(ETL_ERROR(etl::message_pool_allocation_failure));
}
}
return reinterpret_cast<TMessage*>(p);
}
//*************************************************************************
/// Create a message from the pool. One parameter.
//*************************************************************************
template <typename TMessage, typename T1>
TMessage* create(const T1& t1)
{
ETL_STATIC_ASSERT(etl::is_base_of<etl::imessage, TMessage>::value, "Not a message type");
void* p = ETL_NULLPTR;
if (sizeof(TMessage) <= memory_block_pool.get_memory_block_size())
{
p = memory_block_pool.allocate_memory_block(sizeof(TMessage));
if (p != ETL_NULLPTR)
{
::new(p) TMessage(t1);
}
else
{
ETL_ALWAYS_ASSERT(ETL_ERROR(etl::message_pool_allocation_failure));
}
}
return reinterpret_cast<TMessage*>(p);
}
//*************************************************************************
/// Create a message from the pool. Two parameters.
//*************************************************************************
template <typename TMessage, typename T1, typename T2>
TMessage* create(const T1& t1, const T2& t2)
{
ETL_STATIC_ASSERT(etl::is_base_of<etl::imessage, TMessage>::value, "Not a message type");
void* p = ETL_NULLPTR;
if (sizeof(TMessage) <= memory_block_pool.get_memory_block_size())
{
p = memory_block_pool.allocate_memory_block(sizeof(TMessage));
if (p != ETL_NULLPTR)
{
::new(p) TMessage(t1, t2);
}
else
{
ETL_ALWAYS_ASSERT(ETL_ERROR(etl::message_pool_allocation_failure));
}
}
return reinterpret_cast<TMessage*>(p);
}
//*************************************************************************
/// Create a message from the pool. Three parameters.
//*************************************************************************
template <typename TMessage, typename T1, typename T2, typename T3>
TMessage* create(const T1& t1, const T2& t2, const T3& t3)
{
ETL_STATIC_ASSERT(etl::is_base_of<etl::imessage, TMessage>::value, "Not a message type");
void* p = ETL_NULLPTR;
if (sizeof(TMessage) <= memory_block_pool.get_memory_block_size())
{
p = memory_block_pool.allocate_memory_block(sizeof(TMessage));
if (p != ETL_NULLPTR)
{
::new(p) TMessage(t1, t2, t3);
}
else
{
ETL_ALWAYS_ASSERT(ETL_ERROR(etl::message_pool_allocation_failure));
}
}
return reinterpret_cast<TMessage*>(p);
}
//*************************************************************************
/// Create a message from the pool. Four parameters.
//*************************************************************************
template <typename TMessage, typename T1, typename T2, typename T3, typename T4>
TMessage* create(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
{
ETL_STATIC_ASSERT(etl::is_base_of<etl::imessage, TMessage>::value, "Not a message type");
void* p = ETL_NULLPTR;
if (sizeof(TMessage) <= memory_block_pool.get_memory_block_size())
{
p = memory_block_pool.allocate_memory_block(sizeof(TMessage));
if (p != ETL_NULLPTR)
{
::new(p) TMessage(t1, t2, t3, t4);
}
else
{
ETL_ALWAYS_ASSERT(ETL_ERROR(etl::message_pool_allocation_failure));
}
}
return reinterpret_cast<TMessage*>(p)
}
#endif
//*************************************************************************
/// Destruct a message and send it back to the pool.
//*************************************************************************
void destroy(const etl::ireference_counted_message* const pmsg)
{
std::cout << "reference_counted_message_pool : destroy\n";
if (pmsg != ETL_NULLPTR)
{
// pmsg->~ireference_counted_message();
delete pmsg;
//memory_block_pool.release_memory_block(pmsg);
}
}
//*************************************************************************
/// Destruct a message and send it back to the pool.
//*************************************************************************
void destroy(const etl::ireference_counted_message& msg)
{
destroy(&msg);
}
private:
/// The raw memory block pool.
//imemory_block_pool& memory_block_pool;
//// Should not be copied.
//message_pool(const message_pool&) ETL_DELETE;
//message_pool& operator =(const message_pool&) ETL_DELETE;
};
}
#undef ETL_FILE
#endif

View File

@ -1,30 +1,30 @@
/******************************************************************************
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.
******************************************************************************/
///******************************************************************************
//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
@ -46,6 +46,54 @@ namespace etl
ETL_NODISCARD virtual uint32_t decrement_reference_count() = 0;
ETL_NODISCARD virtual uint32_t get_reference_count() const = 0;
};
//***************************************************************************
template <typename TObject, typename TCounter>
class reference_counted_object : public ireference_counted_object
{
public:
reference_counted_object(const TObject& object_)
: object(object_)
{
reference_count = 0;
}
TObject* get_object()
{
return &object;
}
const TObject* get_object() const
{
return &object;
}
virtual void set_reference_count(uint32_t value) ETL_OVERRIDE
{
reference_count = value;
}
virtual void increment_reference_count() ETL_OVERRIDE
{
++reference_count;
}
ETL_NODISCARD virtual uint32_t decrement_reference_count() ETL_OVERRIDE
{
return uint32_t(--reference_count);
}
ETL_NODISCARD virtual uint32_t get_reference_count() const ETL_OVERRIDE
{
return uint32_t(reference_count);
}
private:
TCounter reference_count;
TObject object;
};
}
#endif

View File

@ -31,14 +31,15 @@ SOFTWARE.
#ifndef ETL_SHARED_MESSAGE_INCLUDED
#define ETL_SHARED_MESSAGE_INCLUDED
#include <iostream>
#include "platform.h"
#include "message_pool.h"
#include "reference_counted_message_pool.h"
#include "message.h"
//*****************************************************************************
/// A wrapper for reference countable messages.
/// A wrapper for reference counted messages.
/// Contains pointers to a pool owner and a message defined with a ref count type.
/// See etl::message template.
//*****************************************************************************
namespace etl
{
@ -51,11 +52,12 @@ namespace etl
/// \param owner_ A reference to the owner pool.
/// \param pmessage A reference to the message allocated from the pool.
//*************************************************************************
shared_message(etl::message_pool& owner_, etl::ireference_counted_message& message_)
shared_message(etl::ireference_counted_message& message_, etl::ireference_counted_message_pool& owner_)
: p_message_owner(&owner_)
, p_message(&message_)
{
p_message->set_reference_count(1U);
std::cout << "shared_message C : Reference " << int(p_message->get_message()->get_message_id()) << " " << p_message->get_reference_count() << "\n";
}
//*************************************************************************
@ -66,6 +68,7 @@ namespace etl
, p_message(other.p_message)
{
p_message->increment_reference_count();
std::cout << "shared_message CC : Reference " << int(p_message->get_message()->get_message_id()) << " " << p_message->get_reference_count() << "\n";
}
//*************************************************************************
@ -75,9 +78,10 @@ namespace etl
{
if (&other != this)
{
// Deal with the current message.
// Deal with the current message.
if (p_message->decrement_reference_count() == 0U)
{
std::cout << "shared_message =: Destroy reference counted message\n";
p_message_owner->destroy(p_message);
}
@ -85,7 +89,8 @@ namespace etl
p_message_owner = other.p_message_owner;
p_message = other.p_message;
p_message->increment_reference_count();
}
std::cout << "shared_message =: Reference " << int(p_message->get_message()->get_message_id()) << " " << p_message->get_reference_count() << "\n";
}
return *this;
}
@ -98,24 +103,44 @@ namespace etl
{
if (p_message->decrement_reference_count() == 0U)
{
std::cout << "shared_message ~: Destroy reference counted message\n";
p_message_owner->destroy(p_message);
}
else
{
std::cout << "shared_message ~: Reference " << int(p_message->get_message()->get_message_id()) << " " << p_message->get_reference_count() << "\n";
}
}
//*************************************************************************
/// Get a reference to the contained message.
/// Get a pointer to the contained message.
//*************************************************************************
etl::imessage& get_message()
etl::imessage* get_message()
{
return *p_message;
return p_message->get_message();
}
//*************************************************************************
/// Get a const reference to the contained message.
/// Get a const pointer to the contained message.
//*************************************************************************
const etl::imessage& get_message() const
const etl::imessage* get_message() const
{
return *p_message;
if (p_message != ETL_NULLPTR)
{
return p_message->get_message();
}
else
{
return ETL_NULLPTR;
}
}
//*************************************************************************
/// Returns <b>true</b> if the shared message is owned by a pool.
//*************************************************************************
bool is_owned() const
{
return (p_message_owner != ETL_NULLPTR);
}
//*************************************************************************
@ -128,8 +153,10 @@ namespace etl
private:
etl::message_pool* p_message_owner;
etl::ireference_counted_message* p_message;
shared_message() ETL_DELETE;
etl::ireference_counted_message_pool* p_message_owner;
etl::ireference_counted_message* p_message;
};
}

View File

@ -31,34 +31,323 @@ SOFTWARE.
#include "platform.h"
#include "shared_message.h"
#include "message_router.h"
#include "vector.h"
#include <stdint.h>
namespace etl
{
typedef uint_least8_t shared_message_processor_id_t;
//***************************************************************************
/// This is the base of all shared message processors.
//***************************************************************************
class shared_message_processor
class ishared_message_processor
{
public:
shared_message_processor(imessage_router& router_)
: router(router_)
//***************************************************************************
///
//***************************************************************************
ishared_message_processor(etl::shared_message_processor_id_t id_ = etl::shared_message_processor_id_t())
: id(id_)
{
}
imessage_router& get_router() const
virtual void receive(etl::shared_message shared_msg) = 0;
virtual void receive(shared_message_processor_id_t destination_processor_id, etl::shared_message shared_msg) = 0;
virtual bool accepts(etl::message_id_t id) const = 0;
//***************************************************************************
///
//***************************************************************************
bool accepts(etl::shared_message shared_msg) const
{
return router;
return accepts(shared_msg.get_message()->get_message_id());
}
virtual ~shared_message_processor() {}
virtual void receive(etl::shared_message message) = 0;
virtual void receive(imessage_router& source, etl::shared_message message) = 0;
//***************************************************************************
///
//***************************************************************************
shared_message_processor_id_t get_shared_message_processor_id() const
{
return id;
}
enum
{
NULL_SHARED_MESSAGE_PROCESSOR = 255,
SHARED_MESSAGE_BUS = 254,
ALL_SHARED_MESSAGE_PROCESSORS = 253,
MAX_SHARED_MESSAGE_PROCESSOR = 249
};
protected:
etl::shared_message_processor_id_t id;
};
//***************************************************************************
/// Derive user defined shared message processors from this.
//***************************************************************************
class shared_message_processor : public ishared_message_processor
{
public:
//***************************************************************************
///
//***************************************************************************
shared_message_processor(etl::shared_message_processor_id_t id_ = etl::shared_message_processor_id_t())
: ishared_message_processor(id_)
{
}
etl::ishared_message_processor::receive;
//***************************************************************************
///
//***************************************************************************
void receive(etl::shared_message shared_msg)
{
on_receive(shared_msg);
}
//***************************************************************************
///
//***************************************************************************
void receive(shared_message_processor_id_t destination_processor_id, etl::shared_message shared_msg)
{
if (destination_processor_id == id)
{
on_receive(shared_msg);
}
}
// User overridden.
virtual void on_receive(etl::shared_message shared_msg) = 0;
};
//***************************************************************************
/// Interface for shared message bus
//***************************************************************************
class ishared_message_bus : public etl::ishared_message_processor
{
private:
typedef etl::ivector<etl::ishared_message_processor*> processor_list_t;
public:
using etl::ishared_message_processor::receive;
//*******************************************
/// Subscribe to the bus.
//*******************************************
bool subscribe(etl::ishared_message_processor& processor)
{
bool ok = true;
ok = !processor_list.full();
ETL_ASSERT(ok, ETL_ERROR(etl::shared_message_bus_too_many_subscribers));
if (ok)
{
processor_list_t::iterator iprocessor = etl::upper_bound(processor_list.begin(),
processor_list.end(),
processor.get_shared_message_processor_id(),
compare_processor_id());
processor_list.insert(iprocessor, &processor);
}
return ok;
}
//*******************************************
/// Unsubscribe from the bus.
//*******************************************
void unsubscribe(etl::shared_message_processor_id_t id)
{
if (id == etl::ishared_message_bus::ALL_SHARED_MESSAGE_PROCESSORS)
{
clear();
}
else
{
ETL_OR_STD::pair<processor_list_t::iterator, processor_list_t::iterator> range = etl::equal_range(processor_list.begin(),
processor_list.end(),
id,
compare_processor_id());
processor_list.erase(range.first, range.second);
}
}
//*******************************************
void unsubscribe(etl::shared_message_processor& processor)
{
processor_list_t::iterator iprocessor = etl::find(processor_list.begin(),
processor_list.end(),
&processor);
if (iprocessor != processor_list.end())
{
processor_list.erase(iprocessor);
}
}
//*******************************************
void receive(shared_message shared_msg) ETL_OVERRIDE
{
receive(etl::shared_message_processor::ALL_SHARED_MESSAGE_PROCESSORS, shared_msg);
}
//*******************************************
void receive(etl::shared_message_processor_id_t destination_processor_id,
etl::shared_message shared_msg) ETL_OVERRIDE
{
switch (destination_processor_id)
{
//*****************************
// Broadcast to all processors.
case etl::shared_message_processor::ALL_SHARED_MESSAGE_PROCESSORS:
{
processor_list_t::iterator iprocessor = processor_list.begin();
// Broadcast to everyone.
while (iprocessor != processor_list.end())
{
etl::ishared_message_processor& processor = **iprocessor;
if (processor.accepts(shared_msg.get_message()->get_message_id()))
{
processor.receive(shared_msg);
}
++iprocessor;
}
break;
}
//*****************************
// Must be an addressed shared_msg.
default:
{
processor_list_t::iterator iprocessor = processor_list.begin();
// Find processors with the id.
ETL_OR_STD::pair<processor_list_t::iterator, processor_list_t::iterator> range = etl::equal_range(processor_list.begin(),
processor_list.end(),
destination_processor_id,
compare_processor_id());
// Call all of them.
while (range.first != range.second)
{
if ((*(range.first))->accepts(shared_msg.get_message()->get_message_id()))
{
(*(range.first))->receive(shared_msg);
}
++range.first;
}
// Do any message buses.
// These are always at the end of the list.
iprocessor = etl::lower_bound(processor_list.begin(),
processor_list.end(),
etl::ishared_message_bus::SHARED_MESSAGE_BUS,
compare_processor_id());
while (iprocessor != processor_list.end())
{
// So pass it on.
(*iprocessor)->receive(destination_processor_id, shared_msg);
++iprocessor;
}
break;
}
}
}
using ishared_message_processor::accepts;
//*******************************************
/// Does this message bus accept the message id?
/// Yes!, it accepts everything!
//*******************************************
bool accepts(etl::message_id_t) const ETL_OVERRIDE
{
return true;
}
//*******************************************
size_t size() const
{
return processor_list.size();
}
//*******************************************
void clear()
{
return processor_list.clear();
}
protected:
//*******************************************
/// Constructor.
//*******************************************
ishared_message_bus(processor_list_t& list)
: ishared_message_processor(etl::ishared_message_processor::SHARED_MESSAGE_BUS)
, processor_list(list)
{
}
private:
imessage_router& router;
//*******************************************
// How to compare processors to processor ids.
//*******************************************
struct compare_processor_id
{
bool operator()(const etl::ishared_message_processor* prouter, etl::shared_message_processor_id_t id) const
{
return prouter->get_shared_message_processor_id() < id;
}
bool operator()(etl::shared_message_processor_id_t id, const etl::ishared_message_processor* prouter) const
{
return id < prouter->get_shared_message_processor_id();
}
};
processor_list_t& processor_list;
};
//***************************************************************************
/// The message bus
//***************************************************************************
template <uint_least8_t MAX_PROCESSORS_>
class shared_message_bus : public etl::ishared_message_bus
{
public:
//*******************************************
/// Constructor.
//*******************************************
shared_message_bus()
: ishared_message_bus(processor_list)
{
}
private:
etl::vector<etl::shared_message_processor*, MAX_PROCESSORS_> processor_list;
};
}