Merge remote-tracking branch 'origin/development'

# Conflicts:
#	test/codeblocks/ETL.depend
#	test/codeblocks/ETL.layout
This commit is contained in:
John Wellbelove 2017-08-07 15:54:21 +01:00
parent 20609e1caf
commit 099b3f8cfd
46 changed files with 11019 additions and 533 deletions

View File

@ -418,6 +418,52 @@ namespace etl
return o_begin;
}
//***************************************************************************
/// binary_find
///\ingroup algorithm
/// Does a binary search and returns an iterator to the value or end if not found.
//***************************************************************************
template <typename TIterator,
typename TValue>
TIterator binary_find(TIterator begin,
TIterator end,
const TValue& value)
{
TIterator it = std::lower_bound(begin, end, value);
if ((it == end) || (*it != value))
{
it = end;
}
return it;
}
//***************************************************************************
/// binary_find
///\ingroup algorithm
/// Does a binary search and returns an iterator to the value or end if not found.
//***************************************************************************
template <typename TIterator,
typename TValue,
typename TBinaryPredicate,
typename TBinaryEquality>
TIterator binary_find(TIterator begin,
TIterator end,
const TValue& value,
TBinaryPredicate predicate,
TBinaryEquality equality)
{
TIterator it = std::lower_bound(begin, end, value, predicate);
if ((it == end) || !equality(*it, value))
{
it = end;
}
return it;
}
//***************************************************************************
/// find_if_not
///\ingroup algorithm

View File

@ -113,7 +113,7 @@ namespace etl
template <typename T>
operator T& ()
{
STATIC_ASSERT(ALIGNMENT % etl::alignment_of<T>::value == 0, "Incompatible alignment");
STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<T&>(*data);
}
@ -121,7 +121,7 @@ namespace etl
template <typename T>
operator const T& () const
{
STATIC_ASSERT(ALIGNMENT % etl::alignment_of<T>::value == 0, "Incompatible alignment");
STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<const T&>(*data);
}
@ -129,7 +129,7 @@ namespace etl
template <typename T>
operator T* ()
{
STATIC_ASSERT(ALIGNMENT % etl::alignment_of<T>::value == 0, "Incompatible alignment");
STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<T*>(data);
}
@ -137,7 +137,7 @@ namespace etl
template <typename T>
operator const T* () const
{
STATIC_ASSERT(ALIGNMENT % etl::alignment_of<T>::value == 0, "Incompatible alignment");
STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<const T*>(data);
}
@ -145,7 +145,7 @@ namespace etl
template <typename T>
T& get_reference()
{
STATIC_ASSERT(ALIGNMENT % etl::alignment_of<T>::value == 0, "Incompatible alignment");
STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<T&>(*data);
}
@ -153,7 +153,7 @@ namespace etl
template <typename T>
const T& get_reference() const
{
STATIC_ASSERT(ALIGNMENT % etl::alignment_of<T>::value == 0, "Incompatible alignment");
STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<const T&>(*data);
}
@ -161,7 +161,7 @@ namespace etl
template <typename T>
T* get_address()
{
STATIC_ASSERT(ALIGNMENT % etl::alignment_of<T>::value == 0, "Incompatible alignment");
STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<T*>(data);
}
@ -169,7 +169,7 @@ namespace etl
template <typename T>
const T* get_address() const
{
STATIC_ASSERT(ALIGNMENT % etl::alignment_of<T>::value == 0, "Incompatible alignment");
STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<const T*>(data);
}

View File

@ -34,4 +34,6 @@
34 fsm
35 message_router
36 scheduler
37 task
37 task
38 message
39 message_bus

1204
src/fsm.h Normal file

File diff suppressed because it is too large Load Diff

569
src/fsm_generator.h Normal file
View File

@ -0,0 +1,569 @@
/******************************************************************************
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.
******************************************************************************/
/*[[[cog
import cog
cog.outl("#if 0")
]]]*/
/*[[[end]]]*/
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
/*[[[cog
import cog
cog.outl("#endif")
]]]*/
/*[[[end]]]*/
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("// This file has been auto generated. Do not edit this file.")
cog.outl("//***************************************************************************")
]]]*/
/*[[[end]]]*/
//***************************************************************************
// To generate to header file, run this at the command line.
// Note: You will need Python and COG installed.
//
// python -m cogapp -d -e -ofsm.h -DHandlers=<n> fsm_generator.h
// Where <n> is the number of messages to support.
//
// e.g.
// To generate handlers for up to 16 events...
// python -m cogapp -d -e -ofsm.h -DHandlers=16 fsm_generator.h
//
// See generate.bat
//***************************************************************************
#ifndef __ETL_FSM__
#define __ETL_FSM__
#include <stdint.h>
#include "array.h"
#include "nullptr.h"
#include "error_handler.h"
#include "exception.h"
#include "user_type.h"
#include "message_router.h"
#include "integral_limits.h"
#include "largest.h"
#undef ETL_FILE
#define ETL_FILE "34"
#ifdef ETL_COMPILER_MICROSOFT
#undef max
#endif
namespace etl
{
class fsm;
/// Allow alternative type for state id.
#if !defined(ETL_FSM_STATE_ID_TYPE)
typedef uint_least8_t fsm_state_id_t;
#else
typedef ETL_FSM_STATE_ID_TYPE fsm_state_id_t;
#endif
// For internal FSM use.
typedef typename etl::larger_type<etl::message_id_t>::type fsm_internal_id_t;
//***************************************************************************
/// Base exception class for FSM.
//***************************************************************************
class fsm_exception : public etl::exception
{
public:
fsm_exception(string_type what, string_type file_name, numeric_type line_number)
: etl::exception(what, file_name, line_number)
{
}
};
//***************************************************************************
/// Exception for null state pointer.
//***************************************************************************
class fsm_null_state_exception : public etl::fsm_exception
{
public:
fsm_null_state_exception(string_type file_name, numeric_type line_number)
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:null state", ETL_FILE"A"), file_name, line_number)
{
}
};
//***************************************************************************
/// Exception for invalid state id.
//***************************************************************************
class fsm_state_id_exception : public etl::fsm_exception
{
public:
fsm_state_id_exception(string_type file_name, numeric_type line_number)
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:state id", ETL_FILE"B"), file_name, line_number)
{
}
};
//***************************************************************************
/// Exception for incompatible state list.
//***************************************************************************
class fsm_state_list_exception : public etl::fsm_exception
{
public:
fsm_state_list_exception(string_type file_name, numeric_type line_number)
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:state list", ETL_FILE"C"), file_name, line_number)
{
}
};
//***************************************************************************
/// Interface class for FSM states.
//***************************************************************************
class ifsm_state
{
public:
/// Allows ifsm_state functions to be private.
friend class fsm_helper;
//*******************************************
/// Gets the id for this state.
//*******************************************
etl::fsm_state_id_t get_state_id() const
{
return state_id;
}
protected:
//*******************************************
/// Constructor.
//*******************************************
ifsm_state(etl::fsm_state_id_t state_id_)
: state_id(state_id_),
p_context(nullptr)
{
}
//*******************************************
inline etl::fsm& get_fsm_context() const
{
return *p_context;
}
private:
virtual fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) = 0;
virtual fsm_state_id_t on_enter_state() { return state_id; } // By default, do nothing.
virtual void on_exit_state() {} // By default, do nothing.
//*******************************************
void set_fsm_context(etl::fsm& context)
{
p_context = &context;
}
// The state id.
const etl::fsm_state_id_t state_id;
// A pointer to the FSM context.
etl::fsm* p_context;
// Disabled.
ifsm_state(const ifsm_state&);
ifsm_state& operator =(const ifsm_state&);
};
//***************************************************************************
/// Helper class for FSM.
/// Allows ifsm_state functions to be private.
//***************************************************************************
class fsm_helper
{
public:
//*******************************************
inline void set_fsm_context(etl::ifsm_state& state,
etl::fsm& context)
{
state.set_fsm_context(context);
}
//*******************************************
inline fsm_state_id_t process_event(etl::ifsm_state& state,
etl::imessage_router& source,
const etl::imessage& message)
{
return state.process_event(source, message);
}
//*******************************************
inline fsm_state_id_t on_enter_state(etl::ifsm_state& state)
{
return state.on_enter_state();
}
//*******************************************
inline void on_exit_state(etl::ifsm_state& state)
{
state.on_exit_state();
}
};
//***************************************************************************
/// The FSM class.
//***************************************************************************
class fsm : public etl::imessage_router, protected etl::fsm_helper
{
public:
//*******************************************
/// Constructor.
//*******************************************
fsm(etl::message_router_id_t id)
: imessage_router(id),
p_state(nullptr)
{
}
//*******************************************
/// Set the states for the FSM
//*******************************************
template <typename TSize>
void set_states(etl::ifsm_state** p_states, TSize size)
{
state_list = p_states;
number_of_states = etl::fsm_state_id_t(size);
ETL_ASSERT((number_of_states > 0), ETL_ERROR(etl::fsm_state_list_exception));
for (etl::fsm_state_id_t i = 0; i < size; ++i)
{
ETL_ASSERT((state_list[i] != nullptr), ETL_ERROR(etl::fsm_null_state_exception));
fsm_helper::set_fsm_context(*state_list[i], *this);
}
}
//*******************************************
/// Starts the FSM.
/// Can only be called once.
/// Subsequent calls will do nothing.
//*******************************************
void start()
{
// Can only be started once.
if (p_state == nullptr)
{
p_state = state_list[0];
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
fsm_helper::on_enter_state(*p_state);
}
}
//*******************************************
/// Top level message handler for the FSM.
//*******************************************
void receive(const etl::imessage& message)
{
etl::null_message_router nmr;
receive(nmr, message);
}
//*******************************************
/// Top level message handler for the FSM.
//*******************************************
void receive(etl::imessage_router& source, const etl::imessage& message)
{
etl::fsm_state_id_t next_state_id = fsm_helper::process_event(*p_state, source, message);
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
etl::ifsm_state* p_next_state = state_list[next_state_id];
// Have we changed state?
if (p_next_state != p_state)
{
do
{
p_state = p_next_state;
fsm_helper::on_exit_state(*p_state);
next_state_id = fsm_helper::on_enter_state(*p_state);
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
p_next_state = state_list[next_state_id];
} while (p_next_state != p_state); // Have we changed state again?
}
}
using imessage_router::accepts;
//*******************************************
/// Does this FSM accept the message id?
/// Yes, it accepts everything!
//*******************************************
bool accepts(etl::message_id_t id) const
{
return true;
}
//*******************************************
/// Gets the current state id.
//*******************************************
etl::fsm_state_id_t get_state_id() const
{
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
return p_state->get_state_id();
}
//*******************************************
/// Gets a reference to the current state interface.
//*******************************************
ifsm_state& get_state()
{
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
return *p_state;
}
//*******************************************
/// Gets a const reference to the current state interface.
//*******************************************
const ifsm_state& get_state() const
{
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
return *p_state;
}
//*******************************************
/// Checks if the FSM has been started.
//*******************************************
bool is_started() const
{
return p_state != nullptr;
}
//*******************************************
/// Reset the FSM to pre-started state.
//*******************************************
void reset()
{
p_state = nullptr;
}
private:
etl::ifsm_state* p_state; ///< A pointer to the current state.
etl::ifsm_state** state_list; ///< The list of added states.
etl::fsm_state_id_t number_of_states; ///< The number of states.
};
/*[[[cog
import cog
cog.outl("")
################################################
# The first definition for all of the events.
################################################
cog.outl("//***************************************************************************")
cog.outl("// The definition for all %s message types." % Handlers)
cog.outl("//***************************************************************************")
cog.outl("template <typename TContext, typename TDerived, const etl::fsm_state_id_t STATE_ID_, ")
cog.out(" ")
for n in range(1, int(Handlers)):
cog.out("typename T%s = void, " % n)
if n % 4 == 0:
cog.outl("")
cog.out(" ")
cog.outl("typename T%s = void>" % Handlers)
cog.outl("class fsm_state : public ifsm_state")
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.outl(" enum")
cog.outl(" {")
cog.outl(" STATE_ID = STATE_ID_")
cog.outl(" };")
cog.outl("")
cog.outl(" fsm_state()")
cog.outl(" : ifsm_state(STATE_ID)")
cog.outl(" {")
cog.outl(" }")
cog.outl("")
cog.outl(" inline TContext& get_fsm_context() const")
cog.outl(" {")
cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
cog.outl(" }")
cog.outl("")
cog.outl("private:")
cog.outl("")
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.get_message_id();")
cog.outl("")
cog.outl(" switch (event_id)")
cog.outl(" {")
for n in range(1, int(Handlers) + 1):
cog.out(" case T%d::ID:" % n)
cog.out(" new_state_id = static_cast<TDerived*>(this)->on_event(source, static_cast<const T%d&>(message));" % n)
cog.outl(" break;")
cog.out(" default:")
cog.out(" new_state_id = static_cast<TDerived*>(this)->on_event_unknown(source, message);")
cog.outl(" break;")
cog.outl(" }")
cog.outl("")
cog.outl(" return new_state_id;")
cog.outl(" }")
cog.outl("};")
####################################
# All of the other specialisations.
####################################
for n in range(int(Handlers) - 1, 0, -1):
cog.outl("")
cog.outl("//***************************************************************************")
if n == 1:
cog.outl("// Specialisation for %d message type." % n)
else:
cog.outl("// Specialisation for %d message types." % n)
cog.outl("//***************************************************************************")
cog.outl("template <typename TContext, typename TDerived, const etl::fsm_state_id_t STATE_ID_, ")
cog.out(" ")
for t in range(1, n):
cog.out("typename T%d, " % t)
if t % 4 == 0:
cog.outl("")
cog.out(" ")
cog.outl("typename T%d>" % n)
cog.out("class fsm_state<TContext, TDerived, STATE_ID_, ")
for t in range(1, n + 1):
cog.out("T%d, " % t)
if t % 16 == 0:
cog.outl("")
cog.out(" ")
for t in range(n + 1, int(Handlers)):
cog.out("void, ")
if t % 16 == 0:
cog.outl("")
cog.out(" ")
cog.outl("void> : public ifsm_state")
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.outl(" enum")
cog.outl(" {")
cog.outl(" STATE_ID = STATE_ID_")
cog.outl(" };")
cog.outl("")
cog.outl(" fsm_state()")
cog.outl(" : ifsm_state(STATE_ID)")
cog.outl(" {")
cog.outl(" }")
cog.outl("")
cog.outl(" inline TContext& get_fsm_context() const")
cog.outl(" {")
cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
cog.outl(" }")
cog.outl("private:")
cog.outl("")
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.get_message_id();")
cog.outl("")
cog.outl(" switch (event_id)")
cog.outl(" {")
for n in range(1, n + 1):
cog.out(" case T%d::ID:" % n)
cog.out(" new_state_id = static_cast<TDerived*>(this)->on_event(source, static_cast<const T%d&>(message));" % n)
cog.outl(" break;")
cog.out(" default:")
cog.out(" new_state_id = static_cast<TDerived*>(this)->on_event_unknown(source, message);")
cog.outl(" break;")
cog.outl(" }")
cog.outl("")
cog.outl(" return new_state_id;")
cog.outl(" }")
cog.outl("};")
####################################
# Specialisation for zero messages.
####################################
cog.outl("")
cog.outl("//***************************************************************************")
cog.outl("// Specialisation for 0 message types.")
cog.outl("//***************************************************************************")
cog.outl("template <typename TContext, typename TDerived, const etl::fsm_state_id_t STATE_ID_>")
cog.out("class fsm_state<TContext, TDerived, STATE_ID_, ")
for t in range(1, int(Handlers)):
cog.out("void, ")
if t % 16 == 0:
cog.outl("")
cog.out(" ")
cog.outl("void> : public ifsm_state")
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.outl(" enum")
cog.outl(" {")
cog.outl(" STATE_ID = STATE_ID_")
cog.outl(" };")
cog.outl("")
cog.outl(" fsm_state()")
cog.outl(" : ifsm_state(STATE_ID)")
cog.outl(" {")
cog.outl(" }")
cog.outl("")
cog.outl(" inline TContext& get_fsm_context() const")
cog.outl(" {")
cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
cog.outl(" }")
cog.outl("private:")
cog.outl("")
cog.outl(" etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)")
cog.outl(" {")
cog.outl(" return static_cast<TDerived*>(this)->on_event_unknown(source, message);")
cog.outl(" }")
cog.outl("};")
]]]*/
/*[[[end]]]*/
}
#undef ETL_FILE
#ifdef ETL_COMPILER_MICROSOFT
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#endif

5
src/generate.bat Normal file
View File

@ -0,0 +1,5 @@
python -m cogapp -d -e -ofsm.h -DHandlers=16 fsm_generator.h
python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h
python -m cogapp -d -e -olargest.h -DNTypes=16 largest_generator.h
python -m cogapp -d -e -osmallest.h -DNTypes=16 smallest_generator.h
python -m cogapp -d -e -otype_traits.h -DIsOneOf=16 type_traits_generator.h

1
src/generate_fsm.bat Normal file
View File

@ -0,0 +1 @@
python -m cogapp -d -e -ofsm.h -DHandlers=16 fsm_generator.h

View File

@ -0,0 +1 @@
python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h

View File

@ -5,7 +5,7 @@ The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
https://www.etlcpp.com
Copyright(c) 2014 jwellbelove
@ -28,6 +28,28 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#if 0
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
#endif
//***************************************************************************
// This file has been auto generated. Do not edit this file.
//***************************************************************************
//***************************************************************************
// To generate to header file, run this at the command line.
// Note: You will need Python and COG installed.
//
// python -m cogapp -d -e -olargest.h -DNTypes=<n> largest_generator.h
// Where <n> is the number of types to support.
//
// e.g.
// To generate handlers for up to 16 types...
// python -m cogapp -d -e -olargest.h -DNTypes=16 largest_generator.h
//
// See generate.bat
//***************************************************************************
#ifndef __ETL_LARGEST__
#define __ETL_LARGEST__
@ -47,9 +69,9 @@ namespace etl
/// Defines 'size' which is the size of the largest parameter.
///\ingroup largest
//***************************************************************************
template <typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
template <typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
struct largest_type
{
@ -78,14 +100,14 @@ namespace etl
public:
// Define 'largest_other' as 'largest_type' with all but the first parameter.
typedef typename largest_type<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::type largest_other;
typedef typename largest_type<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::type largest_other;
// Set 'type' to be the largest of the first parameter and any of the others.
// This is recursive.
typedef typename choose_type<(sizeof(T1) > sizeof(largest_other)), // Boolean
T1, // TrueType
largest_other> // FalseType
::type type; // The largest type of the two.
T1, // TrueType
largest_other> // FalseType
::type type; // The largest type of the two.
// The size of the largest type.
enum
@ -98,10 +120,8 @@ namespace etl
// Specialisation for one template parameter.
//***************************************************************************
template <typename T1>
struct largest_type<T1, void, void, void,
void, void, void, void,
void, void, void, void,
void, void, void, void>
struct largest_type<T1, void, void, void, void, void, void, void,
void, void, void, void, void, void, void, void>
{
typedef T1 type;
@ -117,12 +137,14 @@ namespace etl
/// Defines <b>value</b> which is the largest alignment of all the parameters.
///\ingroup largest
//***************************************************************************
template <typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
template <typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
struct largest_alignment
{
private:
// Determine the largest size.
template <const size_t size1, const size_t size2>
struct max_size
@ -136,22 +158,22 @@ namespace etl
// All of the alignments.
enum
{
t1 = alignment_of<T1>::value,
t2 = alignment_of<T2>::value,
t3 = alignment_of<T3>::value,
t4 = alignment_of<T4>::value,
t5 = alignment_of<T5>::value,
t6 = alignment_of<T6>::value,
t7 = alignment_of<T7>::value,
t8 = alignment_of<T8>::value,
t9 = alignment_of<T9>::value,
t10 = alignment_of<T10>::value,
t11 = alignment_of<T11>::value,
t12 = alignment_of<T12>::value,
t13 = alignment_of<T13>::value,
t14 = alignment_of<T14>::value,
t15 = alignment_of<T15>::value,
t16 = alignment_of<T16>::value
t1 = etl::alignment_of<T1>::value,
t2 = etl::alignment_of<T2>::value,
t3 = etl::alignment_of<T3>::value,
t4 = etl::alignment_of<T4>::value,
t5 = etl::alignment_of<T5>::value,
t6 = etl::alignment_of<T6>::value,
t7 = etl::alignment_of<T7>::value,
t8 = etl::alignment_of<T8>::value,
t9 = etl::alignment_of<T9>::value,
t10 = etl::alignment_of<T10>::value,
t11 = etl::alignment_of<T11>::value,
t12 = etl::alignment_of<T12>::value,
t13 = etl::alignment_of<T13>::value,
t14 = etl::alignment_of<T14>::value,
t15 = etl::alignment_of<T15>::value,
t16 = etl::alignment_of<T16>::value
};
public:
@ -216,6 +238,27 @@ namespace etl
typedef typename etl::smallest_int_for_bits<etl::integral_limits<T>::bits + 1>::type type;
};
//***************************************************************************
/// Template to determine the largest type, size and alignment.
/// Supports up to 16 types.
/// Defines <b>value</b> which is the largest type, size and alignment of all the parameters.
///\ingroup largest
//***************************************************************************
template <typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
struct largest
{
typedef typename etl::largest_type<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::type type;
enum
{
size = etl::largest_type<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::size,
alignment = etl::largest_alignment<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value
};
};
}
#endif

323
src/largest_generator.h Normal file
View File

@ -0,0 +1,323 @@
///\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.
******************************************************************************/
/*[[[cog
import cog
cog.outl("#if 0")
]]]*/
/*[[[end]]]*/
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
/*[[[cog
import cog
cog.outl("#endif")
]]]*/
/*[[[end]]]*/
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("// This file has been auto generated. Do not edit this file.")
cog.outl("//***************************************************************************")
]]]*/
/*[[[end]]]*/
//***************************************************************************
// To generate to header file, run this at the command line.
// Note: You will need Python and COG installed.
//
// python -m cogapp -d -e -olargest.h -DNTypes=<n> largest_generator.h
// Where <n> is the number of types to support.
//
// e.g.
// To generate handlers for up to 16 types...
// python -m cogapp -d -e -olargest.h -DNTypes=16 largest_generator.h
//
// See generate.bat
//***************************************************************************
#ifndef __ETL_LARGEST__
#define __ETL_LARGEST__
///\defgroup largest largest
///\ingroup utilities
#include "type_traits.h"
#include "smallest.h"
#include "static_assert.h"
namespace etl
{
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("/// Template to determine the largest type and size.")
cog.outl("/// Supports up to %s types." % NTypes)
cog.outl("/// Defines 'value_type' which is the type of the largest parameter.")
cog.outl("/// Defines 'size' which is the size of the largest parameter.")
cog.outl("///\ingroup largest")
cog.outl("//***************************************************************************")
cog.out("template <typename T1, ")
for n in range(2, int(NTypes)):
cog.out("typename T%s = void, " % n)
if n % 4 == 0:
cog.outl("")
cog.out(" ")
cog.outl("typename T%s = void>" % int(NTypes))
cog.outl("struct largest_type")
cog.outl("{")
cog.outl("private:")
cog.outl("")
cog.outl(" // Declaration.")
cog.outl(" template <const bool Boolean, typename TrueType, typename FalseType>")
cog.outl(" struct choose_type;")
cog.outl("")
cog.outl(" // Specialisation for 'true'.")
cog.outl(" // Defines 'type' as 'TrueType'.")
cog.outl(" template <typename TrueType, typename FalseType>")
cog.outl(" struct choose_type<true, TrueType, FalseType>")
cog.outl(" {")
cog.outl(" typedef TrueType type;")
cog.outl(" };")
cog.outl("")
cog.outl(" // Specialisation for 'false'. ")
cog.outl(" // Defines 'type' as 'FalseType'.")
cog.outl(" template <typename TrueType, typename FalseType>")
cog.outl(" struct choose_type<false, TrueType, FalseType>")
cog.outl(" {")
cog.outl(" typedef FalseType type;")
cog.outl(" };")
cog.outl("")
cog.outl("public:")
cog.outl("")
cog.outl(" // Define 'largest_other' as 'largest_type' with all but the first parameter. ")
cog.out(" typedef typename largest_type<")
for n in range(2, int(NTypes)):
cog.out("T%s, " % n)
if n % 16 == 0:
cog.outl("")
cog.out(" ")
cog.outl("T%s>::type largest_other;" % int(NTypes))
cog.outl("")
cog.outl(" // Set 'type' to be the largest of the first parameter and any of the others.")
cog.outl(" // This is recursive.")
cog.outl(" typedef typename choose_type<(sizeof(T1) > sizeof(largest_other)), // Boolean")
cog.outl(" T1, // TrueType")
cog.outl(" largest_other> // FalseType")
cog.outl(" ::type type; // The largest type of the two.")
cog.outl("")
cog.outl(" // The size of the largest type.")
cog.outl(" enum")
cog.outl(" {")
cog.outl(" size = sizeof(type)")
cog.outl(" };")
cog.outl("};")
cog.outl("")
cog.outl("//***************************************************************************")
cog.outl("// Specialisation for one template parameter.")
cog.outl("//***************************************************************************")
cog.outl("template <typename T1>")
cog.out("struct largest_type<T1, ")
for n in range(2, int(NTypes)):
cog.out("void, ")
if n % 8 == 0:
cog.outl("")
cog.out(" ")
cog.outl("void>")
cog.outl("{")
cog.outl(" typedef T1 type;")
cog.outl("")
cog.outl(" enum")
cog.outl(" {")
cog.outl(" size = sizeof(type)")
cog.outl(" };")
cog.outl("};")
]]]*/
/*[[[end]]]*/
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("/// Template to determine the largest alignment.")
cog.outl("/// Supports up to %s types." % int(NTypes))
cog.outl("/// Defines <b>value</b> which is the largest alignment of all the parameters.")
cog.outl("///\ingroup largest")
cog.outl("//***************************************************************************")
cog.out("template <typename T1, ")
for n in range(2, int(NTypes)):
cog.out("typename T%s = void, " % n)
if n % 4 == 0:
cog.outl("")
cog.out(" ")
cog.outl("typename T%s = void>" % NTypes)
cog.outl("struct largest_alignment")
cog.outl("{")
cog.outl("private:")
cog.outl("")
cog.outl(" // Determine the largest size.")
cog.outl(" template <const size_t size1, const size_t size2>")
cog.outl(" struct max_size")
cog.outl(" {")
cog.outl(" enum")
cog.outl(" {")
cog.outl(" value = (size1 > size2) ? size1 : size2")
cog.outl(" };")
cog.outl(" };")
cog.outl("")
cog.outl(" // All of the alignments.")
cog.outl(" enum")
cog.outl(" {")
for n in range(1, int(NTypes)):
cog.outl(" t%s = etl::alignment_of<T%s>::value," %(n, n))
cog.outl(" t%s = etl::alignment_of<T%s>::value" % (NTypes, NTypes))
cog.outl(" };")
cog.outl("")
cog.outl("public:")
cog.outl("")
cog.outl(" // The largest of all of them.")
cog.outl(" enum")
cog.outl(" {")
cog.out(" value = ")
for n in range(1, int(NTypes)):
cog.out("max_size<t%s, " %n)
if n % 8 == 0:
cog.outl("")
cog.out(" ")
cog.outl("t%s>" % int(NTypes))
cog.out(" ")
for n in range(1, int(NTypes) - 1):
cog.out("::value>")
if n % 8 == 0:
cog.outl("")
cog.out(" ")
cog.outl("::value")
cog.outl(" };")
cog.outl("};")
]]]*/
/*[[[end]]]*/
//***************************************************************************
/// Defines a type that is as larger or larger than the specified type.
/// Will return the specified type is there is not a larger type.
///\ingroup largest
//***************************************************************************
template <typename T>
struct larger_int_type
{
STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
typedef typename etl::smallest_int_for_bits<etl::integral_limits<typename etl::make_signed<T>::type>::bits + 1>::type type;
};
//***************************************************************************
/// Defines a type that is as larger or larger than the specified type.
/// Will return the specified type is there is not a larger type.
///\ingroup largest
//***************************************************************************
template <typename T>
struct larger_uint_type
{
STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
typedef typename etl::smallest_uint_for_bits<etl::integral_limits<typename etl::make_unsigned<T>::type>::bits + 1>::type type;
};
//***************************************************************************
/// Defines a type that is as larger or larger than the specified type.
/// Will return the specified type is there is not a larger type.
/// The returned type will be of the same sign.
///\ingroup largest
//***************************************************************************
template <typename T, bool IS_SIGNED = etl::is_signed<T>::value>
struct larger_type;
template <typename T>
struct larger_type<T, false>
{
STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
typedef typename etl::smallest_uint_for_bits<etl::integral_limits<T>::bits + 1>::type type;
};
template <typename T>
struct larger_type<T, true>
{
STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
typedef typename etl::smallest_int_for_bits<etl::integral_limits<T>::bits + 1>::type type;
};
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("/// Template to determine the largest type, size and alignment.")
cog.outl("/// Supports up to %s types." % NTypes)
cog.outl("/// Defines <b>value</b> which is the largest type, size and alignment of all the parameters.")
cog.outl("///\ingroup largest")
cog.outl("//***************************************************************************")
cog.out("template <typename T1, ")
for n in range(2, int(NTypes)):
cog.out("typename T%s = void, " % n)
if n % 4 == 0:
cog.outl("")
cog.out(" ")
cog.outl("typename T%s = void>" % NTypes)
cog.outl("struct largest")
cog.outl("{")
cog.out(" typedef typename etl::largest_type<")
for n in range(1, int(NTypes)):
cog.out("T%s, " % n)
if n % 16 == 0:
cog.outl("")
cog.out(" ")
cog.outl("T%s>::type type;" % NTypes)
cog.outl("")
cog.outl(" enum")
cog.outl(" {")
cog.out(" size = etl::largest_type<")
for n in range(1, int(NTypes)):
cog.out("T%s, " % n)
if n % 16 == 0:
cog.outl("")
cog.out(" ")
cog.outl("T%s>::size," % NTypes)
cog.out(" alignment = etl::largest_alignment<")
for n in range(1, int(NTypes)):
cog.out("T%s, " % n)
if n % 16 == 0:
cog.outl("")
cog.out(" ")
cog.outl("T%s>::value" % NTypes)
cog.outl(" };")
cog.outl("};")
]]]*/
/*[[[end]]]*/
}
#endif

View File

@ -662,6 +662,27 @@ namespace etl
return i_begin;
}
//*****************************************************************************
/// Copy constructs a derived class to an address.
///\tparam T The derived type.
///\ingroup memory
//*****************************************************************************
template <typename T>
struct create_copy
{
void create_copy_at(void* p)
{
new (p) T(static_cast<const T&>(*this));
}
template <typename TCounter>
void create_copy_at(void* p, TCounter& count)
{
new (p) T(static_cast<const T&>(*this));
++count;
}
};
}
#endif

96
src/message.h Normal file
View File

@ -0,0 +1,96 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://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_MESSAGE__
#define __ETL_MESSAGE__
#include <stdint.h>
#include "error_handler.h"
#include "exception.h"
#include "message_types.h"
#undef ETL_FILE
#define ETL_FILE "38"
namespace etl
{
//***************************************************************************
class message_exception : public etl::exception
{
public:
message_exception(string_type what, string_type file_name, numeric_type line_number)
: exception(what, file_name, line_number)
{
}
};
//***************************************************************************
class unhandled_message_exception : public etl::message_exception
{
public:
unhandled_message_exception(string_type file_name, numeric_type line_number)
: message_exception(ETL_ERROR_TEXT("message:unknown", ETL_FILE"A"), file_name, line_number)
{
}
};
//***************************************************************************
class imessage
{
public:
//********************************************
virtual ~imessage() {}
virtual etl::message_id_t get_message_id() const = 0;
};
//***************************************************************************
template <const etl::message_id_t ID_>
class message : public imessage
{
public:
enum
{
ID = ID_
};
//********************************************
etl::message_id_t get_message_id() const
{
return ID;
}
};
}
#undef ETL_FILE
#endif

389
src/message_bus.h Normal file
View File

@ -0,0 +1,389 @@
/******************************************************************************
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_MESSAGE_BUS_
#define __ETL_MESSAGE_BUS_
#include <stdint.h>
#include <algorithm>
#include "algorithm.h"
#include "vector.h"
#include "nullptr.h"
#include "error_handler.h"
#include "exception.h"
#include "message_types.h"
#include "message.h"
#include "message_router.h"
#undef ETL_FILE
#define ETL_FILE "39"
namespace etl
{
//***************************************************************************
/// Base exception class for message bus
//***************************************************************************
class message_bus_exception : public etl::exception
{
public:
message_bus_exception(string_type what, string_type file_name, numeric_type line_number)
: etl::exception(what, file_name, line_number)
{
}
};
//***************************************************************************
/// Too many subscribers.
//***************************************************************************
class message_bus_too_many_subscribers : public etl::message_bus_exception
{
public:
message_bus_too_many_subscribers(string_type file_name, numeric_type line_number)
: message_bus_exception(ETL_ERROR_TEXT("message bus:too many subscribers", ETL_FILE"A"), file_name, line_number)
{
}
};
//***************************************************************************
/// Interface for message bus
//***************************************************************************
class imessage_bus : public etl::imessage_router
{
private:
typedef etl::ivector<etl::imessage_router*> router_list_t;
public:
using etl::imessage_router::receive;
//*******************************************
/// Subscribe to the bus.
//*******************************************
bool subscribe(etl::imessage_router& router)
{
bool ok = true;
// There's no point actually adding null routers.
if (router.get_message_router_id() != etl::imessage_router::NULL_MESSAGE_ROUTER)
{
ok = !router_list.full();
ETL_ASSERT(ok, ETL_ERROR(etl::message_bus_too_many_subscribers));
if (ok)
{
if (router.get_message_router_id() == etl::imessage_router::MESSAGE_BUS)
{
// Message busses get added to the end.
router_list.push_back(&router);
}
else
{
// Routers get added in id order.
router_list_t::iterator irouter = std::upper_bound(router_list.begin(),
router_list.end(),
router.get_message_router_id(),
compare_router_id());
router_list.insert(irouter, &router);
}
}
}
return ok;
}
//*******************************************
/// Unsubscribe from the bus.
//*******************************************
void unsubscribe(etl::message_router_id_t id)
{
if (id == etl::imessage_bus::ALL_MESSAGE_ROUTERS)
{
clear();
}
else
{
std::pair<router_list_t::iterator, router_list_t::iterator> range = std::equal_range(router_list.begin(),
router_list.end(),
id,
compare_router_id());
router_list.erase(range.first, range.second);
}
}
//*******************************************
void unsubscribe(etl::imessage_router& router)
{
router_list_t::iterator irouter = std::find(router_list.begin(),
router_list.end(),
&router);
if (irouter != router_list.end())
{
router_list.erase(irouter);
}
}
//*******************************************
void receive(const etl::imessage& message)
{
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)
{
etl::null_message_router nmr;
receive(nmr, destination_router_id, message);
}
//*******************************************
void receive(etl::imessage_router& source,
const etl::imessage& message)
{
receive(source, etl::imessage_router::ALL_MESSAGE_ROUTERS, message);
}
//*******************************************
void receive(etl::imessage_router& source,
etl::message_router_id_t destination_router_id,
const etl::imessage& message)
{
switch (destination_router_id)
{
//*****************************
// Null message router. These routers can never be subscribed.
case etl::imessage_router::NULL_MESSAGE_ROUTER:
{
break;
}
//*****************************
// Broadcast to all routers.
case etl::imessage_router::ALL_MESSAGE_ROUTERS:
{
router_list_t::iterator irouter = router_list.begin();
// Broadcast to everyone.
while (irouter != router_list.end())
{
etl::imessage_router& router = **irouter;
if (router.get_message_router_id() == etl::imessage_router::MESSAGE_BUS)
{
// The router is actually a bus.
etl::imessage_bus& bus = static_cast<etl::imessage_bus&>(router);
// So pass it on.
bus.receive(source, destination_router_id, message);
}
else if (router.accepts(message.get_message_id()))
{
router.receive(source, message);
}
++irouter;
}
break;
}
//*****************************
// Must be an addressed message.
default:
{
router_list_t::iterator irouter = router_list.begin();
// Find routers with the id.
std::pair<router_list_t::iterator, router_list_t::iterator> range = std::equal_range(router_list.begin(),
router_list.end(),
destination_router_id,
compare_router_id());
// Call all of them.
while (range.first != range.second)
{
if ((*(range.first))->accepts(message.get_message_id()))
{
(*(range.first))->receive(source, message);
}
++range.first;
}
// Do any message buses.
// These are always at the end of the list.
irouter = std::lower_bound(router_list.begin(),
router_list.end(),
etl::imessage_bus::MESSAGE_BUS,
compare_router_id());
while (irouter != router_list.end())
{
// The router is actually a bus.
etl::imessage_bus& bus = static_cast<etl::imessage_bus&>(**irouter);
// So pass it on.
bus.receive(source, destination_router_id, message);
++irouter;
}
break;
}
}
}
using imessage_router::accepts;
//*******************************************
/// Does this message bus accept the message id?
/// Yes!, it accepts everything!
//*******************************************
bool accepts(etl::message_id_t id) const
{
return true;
}
//*******************************************
size_t size() const
{
return router_list.size();
}
//*******************************************
void clear()
{
return router_list.clear();
}
protected:
//*******************************************
/// Constructor.
//*******************************************
imessage_bus(router_list_t& list)
: imessage_router(etl::imessage_router::MESSAGE_BUS),
router_list(list)
{
}
private:
//*******************************************
// How to compare routers to router ids.
//*******************************************
struct compare_router_id
{
bool operator()(const etl::imessage_router* prouter, etl::message_router_id_t id) const
{
return prouter->get_message_router_id() < id;
}
bool operator()(etl::message_router_id_t id, const etl::imessage_router* prouter) const
{
return id < prouter->get_message_router_id();
}
};
router_list_t& router_list;
};
//***************************************************************************
/// The message bus
//***************************************************************************
template <uint_least8_t MAX_ROUTERS_>
class message_bus : public etl::imessage_bus
{
public:
//*******************************************
/// Constructor.
//*******************************************
message_bus()
: imessage_bus(router_list)
{
}
private:
etl::vector<etl::imessage_router*, MAX_ROUTERS_> router_list;
};
//***************************************************************************
/// Send a message to a bus.
//***************************************************************************
inline static void send_message(etl::imessage_bus& bus,
const etl::imessage& message)
{
bus.receive(message);
}
//***************************************************************************
/// Send a message to a bus.
//***************************************************************************
inline static void send_message(etl::imessage_bus& bus,
etl::message_router_id_t id,
const etl::imessage& message)
{
bus.receive(id, message);
}
//***************************************************************************
/// Send a message to a bus.
//***************************************************************************
inline static void send_message(etl::imessage_router& source,
etl::imessage_bus& bus,
const etl::imessage& message)
{
bus.receive(source, message);
}
//***************************************************************************
/// Send a message to a bus.
//***************************************************************************
inline static void send_message(etl::imessage_router& source,
etl::imessage_bus& bus,
etl::message_router_id_t id,
const etl::imessage& message)
{
bus.receive(source, id, message);
}
}
#undef ETL_FILE
#endif

2200
src/message_router.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,514 @@
/******************************************************************************
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.
******************************************************************************/
/*[[[cog
import cog
cog.outl("#if 0")
]]]*/
/*[[[end]]]*/
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
/*[[[cog
import cog
cog.outl("#endif")
]]]*/
/*[[[end]]]*/
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("// This file has been auto generated. Do not edit this file.")
cog.outl("//***************************************************************************")
]]]*/
/*[[[end]]]*/
//***************************************************************************
// To generate to header file, run this at the command line.
// Note: You will need Python and COG installed.
//
// python -m cogapp -d -e -omessage_router.h -DHandlers=<n> message_router_generator.h
// Where <n> is the number of messages to support.
//
// e.g.
// To generate handlers for up to 16 messages...
// python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h
//
// See generate.bat
//***************************************************************************
#ifndef __ETL_MESSAGE_ROUTER__
#define __ETL_MESSAGE_ROUTER__
#include <stdint.h>
#include "message.h"
#include "message_types.h"
#include "alignment.h"
#include "error_handler.h"
#include "exception.h"
#include "largest.h"
#undef ETL_FILE
#define ETL_FILE "35"
namespace etl
{
//***************************************************************************
/// Base exception class for message router
//***************************************************************************
class message_router_exception : public etl::exception
{
public:
message_router_exception(string_type what, string_type file_name, numeric_type line_number)
: etl::exception(what, file_name, line_number)
{
}
};
//***************************************************************************
/// Router id is out of the legal range.
//***************************************************************************
class message_router_illegal_id : public etl::message_router_exception
{
public:
message_router_illegal_id(string_type file_name, numeric_type line_number)
: message_router_exception(ETL_ERROR_TEXT("message router:illegal id", ETL_FILE"A"), file_name, line_number)
{
}
};
//***************************************************************************
class imessage_router
{
public:
virtual ~imessage_router() {}
virtual void receive(const etl::imessage& message) = 0;
virtual void receive(imessage_router& source, const etl::imessage& message) = 0;
virtual bool accepts(etl::message_id_t id) const = 0;
//********************************************
bool accepts(const etl::imessage& msg) const
{
return accepts(msg.get_message_id());
}
//********************************************
etl::message_router_id_t get_message_router_id() const
{
return message_router_id;
}
enum
{
NULL_MESSAGE_ROUTER = 255,
MESSAGE_BUS = 254,
ALL_MESSAGE_ROUTERS = 253,
MAX_MESSAGE_ROUTER = 249
};
protected:
imessage_router(etl::message_router_id_t id)
: message_router_id(id)
{
}
private:
// Disabled.
imessage_router(const imessage_router&);
imessage_router& operator =(const imessage_router&);
etl::message_router_id_t message_router_id;
};
//***************************************************************************
/// This router can be used either as a sink for messages
/// or as a producer-only of messages such an interrupt routine.
//***************************************************************************
class null_message_router : public imessage_router
{
public:
null_message_router()
: imessage_router(imessage_router::NULL_MESSAGE_ROUTER)
{
}
//********************************************
void receive(const etl::imessage& message)
{
}
//********************************************
void receive(etl::imessage_router& source, const etl::imessage& message)
{
}
//********************************************
bool accepts(etl::message_id_t id) const
{
return false;
}
//********************************************
static null_message_router& instance()
{
static null_message_router nmr;
return nmr;
}
};
//***************************************************************************
/// Send a message to a router.
/// Sets the 'sender' to etl::null_message_router type.
//***************************************************************************
inline static void send_message(etl::imessage_router& destination,
const etl::imessage& message)
{
destination.receive(message);
}
//***************************************************************************
/// Send a message to a router.
//***************************************************************************
inline static void send_message(etl::imessage_router& source,
etl::imessage_router& destination,
const etl::imessage& message)
{
destination.receive(source, message);
}
/*[[[cog
import cog
################################################
# The first definition for all of the messages.
################################################
cog.outl("//***************************************************************************")
cog.outl("// The definition for all %s message types." % Handlers)
cog.outl("//***************************************************************************")
cog.outl("template <typename TDerived,")
cog.out(" ")
cog.out("typename T1, ")
for n in range(2, int(Handlers)):
cog.out("typename T%s = void, " % n)
if n % 4 == 0:
cog.outl("")
cog.out(" ")
cog.outl("typename T%s = void>" % int(Handlers))
cog.out("class message_router")
cog.outl(" : public imessage_router")
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" class message_packet")
cog.outl(" {")
cog.outl(" public:")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" explicit message_packet(const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" const size_t id = msg.get_message_id();")
cog.outl("")
cog.outl(" void* p = data;")
cog.outl("")
cog.outl(" switch (id)")
cog.outl(" {")
for n in range(1, int(Handlers) + 1):
cog.outl(" case T%s::ID: ::new (p) T%s(static_cast<const T%s&>(msg)); break;" % (n, n, n))
cog.outl(" default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" template <typename T>")
cog.outl(" explicit message_packet(const T& msg)")
cog.outl(" {")
cog.out(" STATIC_ASSERT((etl::is_one_of<T, ")
for n in range(1, int(Handlers)):
cog.out("T%s, " % n)
if n % 16 == 0:
cog.outl("")
cog.out(" ")
cog.outl("""T%s>::value), "Unsupported type for this message packet");""" % int(Handlers))
cog.outl("")
cog.outl(" void* p = data;")
cog.outl(" ::new (p) T(static_cast<const T&>(msg));")
cog.outl(" }")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" ~message_packet()")
cog.outl(" {")
cog.outl(" static_cast<etl::imessage*>(data)->~imessage();")
cog.outl(" }")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" etl::imessage& get()")
cog.outl(" {")
cog.outl(" return *static_cast<etl::imessage*>(data);")
cog.outl(" }")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" const etl::imessage& get() const")
cog.outl(" {")
cog.outl(" return *static_cast<const etl::imessage*>(data);")
cog.outl(" }")
cog.outl("")
cog.outl(" enum")
cog.outl(" {")
cog.out(" SIZE = etl::largest<")
for n in range(1, int(Handlers)):
cog.out("T%s, " % n)
cog.outl("T%s>::size," % int(Handlers))
cog.out(" ALIGNMENT = etl::largest<")
for n in range(1, int(Handlers)):
cog.out("T%s, " % n)
cog.outl("T%s>::alignment" % int(Handlers))
cog.outl(" };")
cog.outl("")
cog.outl(" private:")
cog.outl("")
cog.outl(" typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;")
cog.outl(" };")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" message_router(etl::message_router_id_t id)")
cog.outl(" : imessage_router(id)")
cog.outl(" {")
cog.outl(" ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));")
cog.outl(" }")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" void receive(const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" receive(etl::null_message_router::instance(), msg);")
cog.outl(" }")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" void receive(etl::imessage_router& source, const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" const etl::message_id_t id = msg.get_message_id();")
cog.outl("")
cog.outl(" switch (id)")
cog.outl(" {")
for n in range(1, int(Handlers) + 1):
cog.out(" case T%d::ID:" % n)
cog.out(" static_cast<TDerived*>(this)->on_receive(source, static_cast<const T%d&>(msg));" % n)
cog.outl(" break;")
cog.out(" default:")
cog.out(" static_cast<TDerived*>(this)->on_receive_unknown(source, msg);")
cog.outl(" break;")
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")
cog.outl(" {")
cog.outl(" switch (id)")
cog.outl(" {")
cog.out(" ")
for n in range(1, int(Handlers) + 1):
cog.out("case T%d::ID: " % n)
if n % 8 == 0:
cog.outl("")
cog.out(" ")
cog.outl(" return true; break;")
cog.outl(" default:")
cog.outl(" return false; break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("};")
####################################
# All of the other specialisations.
####################################
for n in range(int(Handlers) - 1, 0, -1):
cog.outl("")
cog.outl("//***************************************************************************")
if n == 1:
cog.outl("// Specialisation for %d message type." % n)
else:
cog.outl("// Specialisation for %d message types." % n)
cog.outl("//***************************************************************************")
cog.outl("template <typename TDerived, ")
cog.out(" ")
for t in range(1, n):
cog.out("typename T%d, " % t)
if t % 4 == 0:
cog.outl("")
cog.out(" ")
cog.outl("typename T%d>" % n)
cog.out("class message_router<TDerived, ")
for t in range(1, n + 1):
cog.out("T%d, " % t)
if t % 16 == 0:
cog.outl("")
cog.out(" ")
for t in range(n + 1, int(Handlers)):
cog.out("void, ")
if t % 16 == 0:
cog.outl("")
cog.out(" ")
cog.outl("void>")
cog.outl(" : public imessage_router")
cog.outl("{")
cog.outl("public:")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" class message_packet")
cog.outl(" {")
cog.outl(" public:")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" explicit message_packet(const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" const size_t id = msg.get_message_id();")
cog.outl("")
cog.outl(" void* p = data;")
cog.outl("")
cog.outl(" switch (id)")
cog.outl(" {")
for t in range(1, n + 1):
cog.outl(" case T%s::ID: ::new (p) T%s(static_cast<const T%s&>(msg)); break;" % (t, t, t))
cog.outl(" default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" template <typename T>")
cog.outl(" explicit message_packet(const T& msg)")
cog.outl(" {")
cog.out(" STATIC_ASSERT((etl::is_one_of<T, ")
for t in range(1, n):
cog.out("T%s, " % t)
if t % 16 == 0:
cog.outl("")
cog.out(" ")
cog.outl("""T%s>::value), "Unsupported type for this message packet");""" % n)
cog.outl("")
cog.outl(" void* p = data;")
cog.outl(" ::new (p) T(static_cast<const T&>(msg));")
cog.outl(" }")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" ~message_packet()")
cog.outl(" {")
cog.outl(" static_cast<etl::imessage*>(data)->~imessage();")
cog.outl(" }")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" etl::imessage& get()")
cog.outl(" {")
cog.outl(" return *static_cast<etl::imessage*>(data);")
cog.outl(" }")
cog.outl("")
cog.outl(" //********************************************")
cog.outl(" const etl::imessage& get() const")
cog.outl(" {")
cog.outl(" return *static_cast<const etl::imessage*>(data);")
cog.outl(" }")
cog.outl("")
cog.outl(" enum")
cog.outl(" {")
cog.out(" SIZE = etl::largest<")
for t in range(1, n):
cog.out("T%s, " % t)
cog.outl("T%s>::size," % n)
cog.out(" ALIGNMENT = etl::largest<")
for t in range(1, n):
cog.out("T%s, " % t)
cog.outl("T%s>::alignment" % n)
cog.outl(" };")
cog.outl("")
cog.outl(" private:")
cog.outl("")
cog.outl(" typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;")
cog.outl(" };")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" message_router(etl::message_router_id_t id)")
cog.outl(" : imessage_router(id)")
cog.outl(" {")
cog.outl(" ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));")
cog.outl(" }")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" void receive(const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" receive(etl::null_message_router::instance(), msg);")
cog.outl(" }")
cog.outl("")
cog.outl(" //**********************************************")
cog.outl(" void receive(etl::imessage_router& source, const etl::imessage& msg)")
cog.outl(" {")
cog.outl(" const size_t id = msg.get_message_id();")
cog.outl("")
cog.outl(" switch (id)")
cog.outl(" {")
for t in range(1, n + 1):
cog.out(" case T%d::ID:" % t)
cog.out(" static_cast<TDerived*>(this)->on_receive(source, static_cast<const T%d&>(msg));" % t)
cog.outl(" break;")
cog.out(" default:")
cog.out(" static_cast<TDerived*>(this)->on_receive_unknown(source, msg);")
cog.outl(" break;")
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")
cog.outl(" {")
cog.outl(" switch (id)")
cog.outl(" {")
cog.out(" ")
for t in range(1, n + 1):
cog.out("case T%d::ID: " % t)
if t % 8 == 0:
cog.outl("")
cog.out(" ")
cog.outl("")
cog.outl(" return true; break;")
cog.outl(" default:")
cog.outl(" return false; break;")
cog.outl(" }")
cog.outl(" }")
cog.outl("};")
]]]*/
/*[[[end]]]*/
}
#undef ETL_FILE
#endif

46
src/message_types.h Normal file
View File

@ -0,0 +1,46 @@
/******************************************************************************
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_MESSAGE_DEFS__
#define __ETL_MESSAGE_DEFS__
#include <stdint.h>
namespace etl
{
/// Allow alternative type for message id.
#if !defined(ETL_MESSAGE_ID_TYPE)
typedef uint_least8_t message_id_t;
#else
typedef ETL_MESSAGE_ID_TYPE message_id_t;
#endif
typedef uint_least8_t message_router_id_t;
}
#endif

128
src/packet.h Normal file
View File

@ -0,0 +1,128 @@
///\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_PACKET__
#define __ETL_PACKET__
#include "platform.h"
#include "static_assert.h"
#include "alignment.h"
#undef ETL_FILE
#define ETL_FILE "38"
//*****************************************************************************
///\defgroup packet packet
/// A class that can contain one a several related types.
///\ingroup containers
//*****************************************************************************
namespace etl
{
//***************************************************************************
/// A template class that can store any types derived from TBase that conform
/// to the size and alignment requirements.
///\ingroup packet
//***************************************************************************
template <typename TBase, size_t SIZE, size_t ALIGNMENT>
class packet
{
public:
//***************************************************************************
/// Constructor that static asserts any types that do not conform to the max size and alignment.
//***************************************************************************
template <typename T>
explicit packet(const T& value)
{
STATIC_ASSERT((etl::is_base_of<TBase, T>::value), "Unsupported type");
STATIC_ASSERT(sizeof(T) <= SIZE, "Unsupported size");
STATIC_ASSERT(etl::alignment_of<T>::value <= ALIGNMENT, "Unsupported alignment");
::new (static_cast<T*>(data)) T(value);
}
//***************************************************************************
/// Destructor
//***************************************************************************
~packet()
{
static_cast<TBase*>(data)->~TBase();
}
//***************************************************************************
/// Assignment operator for type.
///\param value The value to assign.
//***************************************************************************
template <typename T>
packet& operator =(const T& value)
{
STATIC_ASSERT((etl::is_base_of<TBase, T>::value), "Unsupported type");
STATIC_ASSERT(sizeof(T) <= SIZE, "Unsupported size");
STATIC_ASSERT(etl::alignment_of<T>::value <= ALIGNMENT, "Unsupported alignment");
static_cast<TBase*>(data)->~TBase();
::new (static_cast<T*>(data)) T(value);
return *this;
}
//***************************************************************************
/// Get access to the contained object.
//***************************************************************************
TBase& get()
{
return *static_cast<TBase*>(data);
}
//***************************************************************************
/// Get access to the contained object.
//***************************************************************************
const TBase& get() const
{
return *static_cast<const TBase*>(data);
}
private:
packet(const packet& other);
packet& operator =(const packet& other);
//***************************************************************************
/// The internal storage.
/// Aligned on a suitable boundary, which should be good for all types.
//***************************************************************************
typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
};
}
#undef ETL_FILE
#endif

410
src/scheduler.h Normal file
View File

@ -0,0 +1,410 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://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_SCHEDULER__
#define __ETL_SCHEDULER__
#include <stdint.h>
#include "vector.h"
#include "nullptr.h"
#include "error_handler.h"
#include "exception.h"
#include "task.h"
#include "type_traits.h"
#include "function.h"
#undef ETL_FILE
#define ETL_FILE "36"
namespace etl
{
//***************************************************************************
/// Base exception class for scheduler.
//***************************************************************************
class scheduler_exception : public etl::exception
{
public:
scheduler_exception(string_type what, string_type file_name, numeric_type line_number)
: etl::exception(what, file_name, line_number)
{
}
};
//***************************************************************************
/// 'No tasks' exception.
//***************************************************************************
class scheduler_no_tasks_exception : public etl::scheduler_exception
{
public:
scheduler_no_tasks_exception(string_type file_name, numeric_type line_number)
: etl::scheduler_exception(ETL_ERROR_TEXT("scheduler:no tasks", ETL_FILE"A"), file_name, line_number)
{
}
};
//***************************************************************************
/// 'Null tasks' exception.
//***************************************************************************
class scheduler_null_task_exception : public etl::scheduler_exception
{
public:
scheduler_null_task_exception(string_type file_name, numeric_type line_number)
: etl::scheduler_exception(ETL_ERROR_TEXT("scheduler:null task", ETL_FILE"B"), file_name, line_number)
{
}
};
//***************************************************************************
/// 'Too many tasks' exception.
//***************************************************************************
class scheduler_too_many_tasks_exception : public etl::scheduler_exception
{
public:
scheduler_too_many_tasks_exception(string_type file_name, numeric_type line_number)
: etl::scheduler_exception(ETL_ERROR_TEXT("scheduler:too many tasks", ETL_FILE"C"), file_name, line_number)
{
}
};
//***************************************************************************
/// Sequencial Single.
/// A policy the scheduler can use to decide what to do next.
/// Only calls the task to process work once, if it has work to do.
//***************************************************************************
struct scheduler_policy_sequencial_single
{
bool schedule_tasks(etl::ivector<etl::task*>& task_list)
{
bool idle = true;
for (size_t index = 0; index < task_list.size(); ++index)
{
etl::task& task = *(task_list[index]);
if (task.task_request_work() > 0)
{
task.task_process_work();
idle = false;
}
}
return idle;
}
};
//***************************************************************************
/// Sequencial Multiple.
/// A policy the scheduler can use to decide what to do next.
/// Calls the task to process work until it reports that it has no more.
//***************************************************************************
struct scheduler_policy_sequencial_multiple
{
bool schedule_tasks(etl::ivector<etl::task*>& task_list)
{
bool idle = true;
for (size_t index = 0; index < task_list.size(); ++index)
{
etl::task& task = *(task_list[index]);
while (task.task_request_work() > 0)
{
task.task_process_work();
idle = false;
}
}
return idle;
}
};
//***************************************************************************
/// Highest Priority.
/// A policy the scheduler can use to decide what to do next.
/// Calls the highest priority task that has work.
//***************************************************************************
struct scheduler_policy_highest_priority
{
bool schedule_tasks(etl::ivector<etl::task*>& task_list)
{
bool idle = true;
size_t index = 0;
while (index < task_list.size())
{
etl::task& task = *(task_list[index]);
if (task.task_request_work() > 0)
{
task.task_process_work();
idle = false;
break;
}
else
{
++index;
}
}
return idle;
}
};
//***************************************************************************
/// Most Work.
/// A policy the scheduler can use to decide what to do next.
/// Calls the task that has the most work.
/// Starts looking from the task with the highest priority.
//***************************************************************************
struct scheduler_policy_most_work
{
bool schedule_tasks(etl::ivector<etl::task*>& task_list)
{
bool idle = true;
size_t most_index = 0;
uint_least8_t most_work = 0;
for (size_t index = 0; index < task_list.size(); ++index)
{
etl::task& task = *(task_list[index]);
uint_least8_t n_work = task.task_request_work();
if (n_work > most_work)
{
most_index = index;
most_work = n_work;
idle = false;
}
}
if (!idle)
{
task_list[most_index]->task_process_work();
}
return idle;
}
};
//***************************************************************************
/// Scheduler base.
//***************************************************************************
class ischeduler
{
public:
//*******************************************
// Virtuals.
//*******************************************
virtual void start() = 0;
virtual ~ischeduler()
{
}
//*******************************************
/// Set the idle callback.
//*******************************************
void set_idle_callback(etl::ifunction<void>& callback)
{
p_idle_callback = &callback;
}
//*******************************************
/// Set the watchdog callback.
//*******************************************
void set_watchdog_callback(etl::ifunction<void>& callback)
{
p_watchdog_callback = &callback;
}
//*******************************************
/// Set the running state for the scheduler.
//*******************************************
void set_scheduler_running(bool scheduler_running_)
{
scheduler_running = scheduler_running_;
}
//*******************************************
/// Get the running state for the scheduler.
//*******************************************
bool scheduler_is_running() const
{
return scheduler_running;
}
//*******************************************
/// Force the scheduler to exit.
//*******************************************
void exit_scheduler()
{
scheduler_exit = true;
}
//*******************************************
/// Add a task.
/// Add to the task list in priority order.
//*******************************************
void add_task(etl::task& task)
{
ETL_ASSERT(!task_list.full(), ETL_ERROR(etl::scheduler_too_many_tasks_exception))
if (!task_list.full())
{
typename task_list_t::iterator itask = std::upper_bound(task_list.begin(),
task_list.end(),
task.get_task_priority(),
compare_priority());
task_list.insert(itask, &task);
}
}
//*******************************************
/// Add a task list.
/// Adds to the tasks to the internal task list in priority order.
/// Input order is ignored.
//*******************************************
template <typename TSize>
void add_task_list(etl::task** p_tasks, TSize size)
{
for (TSize i = 0; i < size; ++i)
{
ETL_ASSERT((p_tasks[i] != nullptr), ETL_ERROR(etl::scheduler_null_task_exception));
add_task(*(p_tasks[i]));
}
}
protected:
//*******************************************
/// Constructor.
//*******************************************
ischeduler(etl::ivector<etl::task*>& task_list_)
: scheduler_running(false),
scheduler_exit(false),
p_idle_callback(nullptr),
p_watchdog_callback(nullptr),
task_list(task_list_)
{
}
bool scheduler_running;
bool scheduler_exit;
etl::ifunction<void>* p_idle_callback;
etl::ifunction<void>* p_watchdog_callback;
private:
//*******************************************
// Used to order tasks in descending priority.
//*******************************************
struct compare_priority
{
bool operator()(etl::task* ptask, etl::task_priority_t priority) const
{
return ptask->get_task_priority() > priority;
}
bool operator()(etl::task_priority_t priority, etl::task* ptask) const
{
return priority > ptask->get_task_priority();
}
};
typedef etl::ivector<etl::task*> task_list_t;
task_list_t& task_list;
};
//***************************************************************************
/// Scheduler.
//***************************************************************************
template <typename TSchedulerPolicy, size_t MAX_TASKS_>
class scheduler : public etl::ischeduler, protected TSchedulerPolicy
{
public:
enum
{
MAX_TASKS = MAX_TASKS_,
};
scheduler()
: ischeduler(task_list)
{
}
//*******************************************
/// Start the scheduler. SEQUENCIAL_SINGLE
/// Only calls the task to process work once, if it has work to do.
//*******************************************
void start()
{
ETL_ASSERT(task_list.size() > 0, ETL_ERROR(etl::scheduler_no_tasks_exception));
const size_t task_list_size = task_list.size();
scheduler_running = true;
while (!scheduler_exit)
{
if (scheduler_running)
{
bool idle = TSchedulerPolicy::schedule_tasks(task_list);
if (p_watchdog_callback)
{
(*p_watchdog_callback)();
}
if (idle && p_idle_callback)
{
(*p_idle_callback)();
}
}
}
}
private:
typedef etl::vector<etl::task*, MAX_TASKS> task_list_t;
task_list_t task_list;
};
}
#undef ETL_FILE
#endif

View File

@ -5,7 +5,7 @@ The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
https://www.etlcpp.com
Copyright(c) 2014 jwellbelove
@ -28,6 +28,28 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#if 0
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
#endif
//***************************************************************************
// This file has been auto generated. Do not edit this file.
//***************************************************************************
//***************************************************************************
// To generate to header file, run this at the command line.
// Note: You will need Python and COG installed.
//
// python -m cogapp -d -e -osmallest.h -DNTypes=<n> smallest_generator.h
// Where <n> is the number of types to support.
//
// e.g.
// To generate handlers for up to 16 types...
// python -m cogapp -d -e -osmallest.h -DNTypes=16 smallest_generator.h
//
// See generate.bat
//***************************************************************************
#ifndef __ETL_SMALLEST__
#define __ETL_SMALLEST__
@ -47,9 +69,9 @@ namespace etl
/// Defines 'size' which is the size of the smallest parameter.
///\ingroup smallest
//***************************************************************************
template <typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
template <typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
struct smallest_type
{
@ -82,10 +104,10 @@ namespace etl
// Set 'type' to be the smallest of the first parameter and any of the others.
// This is recursive.
typedef typename choose_type<(sizeof(T1) < sizeof(smallest_other)),// Boolean
T1, // TrueType
smallest_other> // FalseType
::type type; // The smallest type of the two.
typedef typename choose_type<(sizeof(T1) < sizeof(smallest_other)), // Boolean
T1, // TrueType
smallest_other> // FalseType
::type type; // The smallest type of the two.
// The size of the smallest type.
enum
@ -98,10 +120,8 @@ namespace etl
// Specialisation for one template parameter.
//***************************************************************************
template <typename T1>
struct smallest_type <T1, void, void, void,
void, void, void, void,
void, void, void, void,
void, void, void, void>
struct smallest_type<T1, void, void, void, void, void, void, void,
void, void, void, void, void, void, void, void>
{
typedef T1 type;

336
src/smallest_generator.h Normal file
View File

@ -0,0 +1,336 @@
///\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.
******************************************************************************/
/*[[[cog
import cog
cog.outl("#if 0")
]]]*/
/*[[[end]]]*/
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
/*[[[cog
import cog
cog.outl("#endif")
]]]*/
/*[[[end]]]*/
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("// This file has been auto generated. Do not edit this file.")
cog.outl("//***************************************************************************")
]]]*/
/*[[[end]]]*/
//***************************************************************************
// To generate to header file, run this at the command line.
// Note: You will need Python and COG installed.
//
// python -m cogapp -d -e -osmallest.h -DNTypes=<n> smallest_generator.h
// Where <n> is the number of types to support.
//
// e.g.
// To generate handlers for up to 16 types...
// python -m cogapp -d -e -osmallest.h -DNTypes=16 smallest_generator.h
//
// See generate.bat
//***************************************************************************
#ifndef __ETL_SMALLEST__
#define __ETL_SMALLEST__
#include <stdint.h>
#include "integral_limits.h"
///\defgroup smallest smallest
///\ingroup utilities
namespace etl
{
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("/// Template to determine the smallest type and size.")
cog.outl("/// Supports up to %s types." % NTypes)
cog.outl("/// Defines 'value_type' which is the type of the smallest parameter.")
cog.outl("/// Defines 'size' which is the size of the smallest parameter.")
cog.outl("///\ingroup smallest")
cog.outl("//***************************************************************************")
cog.out("template <typename T1, ")
for n in range(2, int(NTypes)):
cog.out("typename T%s = void, " % n)
if n % 4 == 0:
cog.outl("")
cog.out(" ")
cog.outl("typename T%s = void>" % int(NTypes))
cog.outl("struct smallest_type")
cog.outl("{")
cog.outl("private:")
cog.outl("")
cog.outl(" // Declaration.")
cog.outl(" template <const bool Boolean, typename TrueType, typename FalseType>")
cog.outl(" struct choose_type;")
cog.outl("")
cog.outl(" // Specialisation for 'true'.")
cog.outl(" // Defines 'type' as 'TrueType'.")
cog.outl(" template <typename TrueType, typename FalseType>")
cog.outl(" struct choose_type<true, TrueType, FalseType>")
cog.outl(" {")
cog.outl(" typedef TrueType type;")
cog.outl(" };")
cog.outl("")
cog.outl(" // Specialisation for 'false'. ")
cog.outl(" // Defines 'type' as 'FalseType'.")
cog.outl(" template <typename TrueType, typename FalseType>")
cog.outl(" struct choose_type<false, TrueType, FalseType>")
cog.outl(" {")
cog.outl(" typedef FalseType type;")
cog.outl(" };")
cog.outl("")
cog.outl("public:")
cog.outl("")
cog.outl(" // Define 'smallest_other' as 'smallest_type' with all but the first parameter. ")
cog.out(" typedef typename smallest_type<")
for n in range(2, int(NTypes)):
cog.out("T%s, " % n)
if n % 16 == 0:
cog.outl("")
cog.out(" ")
cog.outl("T%s>::type smallest_other;" % int(NTypes))
cog.outl("")
cog.outl(" // Set 'type' to be the smallest of the first parameter and any of the others.")
cog.outl(" // This is recursive.")
cog.outl(" typedef typename choose_type<(sizeof(T1) < sizeof(smallest_other)), // Boolean")
cog.outl(" T1, // TrueType")
cog.outl(" smallest_other> // FalseType")
cog.outl(" ::type type; // The smallest type of the two.")
cog.outl("")
cog.outl(" // The size of the smallest type.")
cog.outl(" enum")
cog.outl(" {")
cog.outl(" size = sizeof(type)")
cog.outl(" };")
cog.outl("};")
cog.outl("")
cog.outl("//***************************************************************************")
cog.outl("// Specialisation for one template parameter.")
cog.outl("//***************************************************************************")
cog.outl("template <typename T1>")
cog.out("struct smallest_type<T1, ")
for n in range(2, int(NTypes)):
cog.out("void, ")
if n % 8 == 0:
cog.outl("")
cog.out(" ")
cog.outl("void>")
cog.outl("{")
cog.outl(" typedef T1 type;")
cog.outl("")
cog.outl(" enum")
cog.outl(" {")
cog.outl(" size = sizeof(type)")
cog.outl(" };")
cog.outl("};")
]]]*/
/*[[[end]]]*/
namespace __private_smallest__
{
//*************************************************************************
// Determine the type to hold the number of bits based on the index.
//*************************************************************************
template <const int index>
struct best_fit_uint_type;
//*************************************************************************
// Less than or equal to 8 bits.
//*************************************************************************
template <>
struct best_fit_uint_type<0>
{
typedef uint_least8_t type;
};
//*************************************************************************
// 9 to 16 bits.
//*************************************************************************
template <>
struct best_fit_uint_type<1>
{
typedef uint_least16_t type;
};
//*************************************************************************
// 17 to 31 bits.
//*************************************************************************
template <>
struct best_fit_uint_type<2>
{
typedef uint_least32_t type;
};
//*************************************************************************
// Greater than 32 bits.
//*************************************************************************
template <>
struct best_fit_uint_type<3>
{
typedef uint_least64_t type;
};
//*************************************************************************
// Determine the type to hold the number of bits based on the index.
//*************************************************************************
template <const int index>
struct best_fit_int_type;
//*************************************************************************
// Less than or equal to 8 bits.
//*************************************************************************
template <>
struct best_fit_int_type<0>
{
typedef int_least8_t type;
};
//*************************************************************************
// 9 to 16 bits.
//*************************************************************************
template <>
struct best_fit_int_type<1>
{
typedef int_least16_t type;
};
//*************************************************************************
// 17 to 31 bits.
//*************************************************************************
template <>
struct best_fit_int_type<2>
{
typedef int_least32_t type;
};
//*************************************************************************
// Greater than 32 bits.
//*************************************************************************
template <>
struct best_fit_int_type<3>
{
typedef int_least64_t type;
};
}
//***************************************************************************
/// Template to determine the smallest unsigned int type that can contain a
/// value with the specified number of bits.
/// Defines 'type' which is the type of the smallest unsigned integer.
///\ingroup smallest
//***************************************************************************
template <const size_t NBITS>
struct smallest_uint_for_bits
{
private:
// Determines the index of the best unsigned type for the required number of bits.
static const int TYPE_INDEX = ((NBITS > 8) ? 1 : 0) +
((NBITS > 16) ? 1 : 0) +
((NBITS > 32) ? 1 : 0);
public:
typedef typename __private_smallest__::best_fit_uint_type<TYPE_INDEX>::type type;
};
//***************************************************************************
/// Template to determine the smallest signed int type that can contain a
/// value with the specified number of bits.
/// Defines 'type' which is the type of the smallest signed integer.
///\ingroup smallest
//***************************************************************************
template <const size_t NBITS>
struct smallest_int_for_bits
{
private:
// Determines the index of the best unsigned type for the required number of bits.
static const int TYPE_INDEX = ((NBITS > 8) ? 1 : 0) +
((NBITS > 16) ? 1 : 0) +
((NBITS > 32) ? 1 : 0);
public:
typedef typename __private_smallest__::best_fit_int_type<TYPE_INDEX>::type type;
};
//***************************************************************************
/// Template to determine the smallest unsigned int type that can contain the
/// specified unsigned value.
/// Defines 'type' which is the type of the smallest unsigned integer.
///\ingroup smallest
//***************************************************************************
template <const uintmax_t VALUE>
struct smallest_uint_for_value
{
private:
// Determines the index of the best unsigned type for the required value.
static const int TYPE_INDEX = ((VALUE > UINT_LEAST8_MAX) ? 1 : 0) +
((VALUE > UINT16_MAX) ? 1 : 0) +
((VALUE > UINT32_MAX) ? 1 : 0);
public:
typedef typename __private_smallest__::best_fit_uint_type<TYPE_INDEX>::type type;
};
//***************************************************************************
/// Template to determine the smallest int type that can contain the
/// specified signed value.
/// Defines 'type' which is the type of the smallest signed integer.
///\ingroup smallest
//***************************************************************************
template <const intmax_t VALUE>
struct smallest_int_for_value
{
private:
// Determines the index of the best signed type for the required value.
static const int TYPE_INDEX = (((VALUE > INT_LEAST8_MAX) || (VALUE < INT_LEAST8_MIN)) ? 1 : 0) +
(((VALUE > INT16_MAX) || (VALUE < INT16_MIN)) ? 1 : 0) +
(((VALUE > INT32_MAX) || (VALUE < INT32_MIN)) ? 1 : 0);
public:
typedef typename __private_smallest__::best_fit_int_type<TYPE_INDEX>::type type;
};
}
#endif

125
src/task.h Normal file
View File

@ -0,0 +1,125 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://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_TASK__
#define __ETL_TASK__
#include <stdint.h>
#include "error_handler.h"
#include "exception.h"
#undef ETL_FILE
#define ETL_FILE "37"
namespace etl
{
//***************************************************************************
/// Base exception class for task.
//***************************************************************************
class task_exception : public etl::exception
{
public:
task_exception(string_type what, string_type file_name, numeric_type line_number)
: etl::exception(what, file_name, line_number)
{
}
};
typedef uint_least8_t task_priority_t;
//***************************************************************************
/// Scheduler.
//***************************************************************************
class task
{
public:
//*******************************************
/// Constructor.
//*******************************************
task(task_priority_t priority)
: task_running(true),
task_priority(priority)
{
}
//*******************************************
/// Destructor.
//*******************************************
virtual ~task()
{
}
//*******************************************
/// Called to check if the task has work.
/// Returns a score as to the amount of work it has to do.
//*******************************************
virtual uint32_t task_request_work() const = 0;
//*******************************************
/// Called to get the task to do work.
//*******************************************
virtual void task_process_work() = 0;
//*******************************************
/// Set the running state for the task.
//*******************************************
void set_task_running(bool task_running_)
{
task_running = task_running_;
}
//*******************************************
/// Get the running state for the task.
//*******************************************
bool task_is_running() const
{
return task_running;
}
//*******************************************
/// Get the priority of the task.
/// Higher value = higher priority.
//*******************************************
etl::task_priority_t get_task_priority() const
{
return task_priority;
}
private:
bool task_running;
etl::task_priority_t task_priority;
};
}
#undef ETL_FILE
#endif

View File

@ -5,7 +5,7 @@ The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
https://www.etlcpp.com
Copyright(c) 2014 jwellbelove
@ -28,6 +28,28 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#if 0
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
#endif
//***************************************************************************
// This file has been auto generated. Do not edit this file.
//***************************************************************************
//***************************************************************************
// To generate to header file, run this at the command line.
// Note: You will need Python and COG installed.
//
// python -m cogapp -d -e -otypes.h -DHandlers=<n> types_generator.h
// Where <n> is the number of types to support.
//
// e.g.
// To generate handlers for up to 16 types...
// python -m cogapp -d -e -otype_traits.h -DIsOneOf=16 type_traits_generator.h
//
// See generate.bat
//***************************************************************************
#ifndef __ETL_TYPE_TRAITS__
#define __ETL_TYPE_TRAITS__
@ -152,7 +174,6 @@ namespace etl
template <typename T> struct is_integral<volatile T> : is_integral<T> {};
template <typename T> struct is_integral<const volatile T> : is_integral<T> {};
/// is_signed
///\ingroup type_traits
template <typename T> struct is_signed : false_type {};
@ -237,15 +258,15 @@ namespace etl
template <typename T> struct is_reference<T&> : true_type {};
/// is_pod
/// For C++03, only fundamental and pointers types are recognised.
///\ingroup type_traits
#if defined(ETL_C11_TYPE_TRAITS_SUPPORTED)// && !defined(ETL_IN_UNIT_TEST)
// For compilers that support C++11
template <typename T> struct is_pod : std::is_pod<T> {};
#else
/// For C++03, only fundamental and pointers types are recognised.
template <typename T> struct is_pod : etl::integral_constant<bool, etl::is_fundamental<T>::value ||
etl::is_pointer<T>::value> {};
etl::is_pointer<T>::value> {};
#endif
#if defined(ETL_C11_TYPE_TRAITS_SUPPORTED) && defined(ETL_C11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED)// && !defined(ETL_IN_UNIT_TEST)
@ -290,6 +311,7 @@ namespace etl
template <typename T> struct is_trivially_copy_assignable : etl::is_pod<T> {};
#endif
/// conditional
///\ingroup type_traits
template <bool B, typename T, typename F> struct conditional { typedef T type; };
@ -392,29 +414,80 @@ namespace etl
typename etl::remove_cv<U>::type>::type type;
};
/// is_base_of
///\ingroup type_traits
template<class TBase, class TDerived>
struct is_base_of
{
private:
template<typename T> struct dummy {};
struct internal: TDerived, dummy<int>{};
static TBase* check(TBase*);
template<typename T> static char check(dummy<T>*);
public:
static const bool value = (sizeof(check((internal*)0)) == sizeof(TBase*));
};
/// Alignment templates.
/// These require compiler specific intrinsics.
///\ingroup type_traits
#if defined(ETL_C11_ALIGNOF_SUPPORTED)
template <typename T> struct alignment_of : integral_constant<size_t, size_t(alignof(T))> {};
#elif defined(ETL_COMPILER_MICROSOFT)
#ifdef ETL_COMPILER_MICROSOFT
template <typename T> struct alignment_of : integral_constant<size_t, size_t(__alignof(T))> {};
#elif defined(ETL_COMPILER_GCC)
#endif
#ifdef ETL_COMPILER_GCC
template <typename T> struct alignment_of : integral_constant<size_t, size_t(__alignof__(T))> {};
#elif defined(ETL_COMPILER_KEIL)
#endif
#ifdef ETL_COMPILER_KEIL
template <typename T> struct alignment_of : integral_constant<size_t, size_t(__alignof__(T))> {};
#elif defined(ETL_COMPILER_IAR)
#endif
#ifdef ETL_COMPILER_IAR
template <typename T> struct alignment_of : integral_constant<size_t, size_t(__ALIGNOF__(T))> {};
#elif defined(ETL_COMPILER_TI)
#endif
#ifdef ETL_COMPILER_TI
template <typename T> struct alignment_of : integral_constant<size_t, size_t(__ALIGNOF__(T))> {};
#else
// Best guess!
template <typename T> struct alignment_of : integral_constant<size_t, size_t(__alignof__(T))> {};
#endif
/// Specialisation of 'alignment_of' for 'void'.
///\ingroup type_traits
template <> struct alignment_of<void> : integral_constant <size_t, 0>{};
//***************************************************************************
/// Template to determine if a type is one of a specified list.
///\ingroup types
//***************************************************************************
template <typename T,
typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
struct is_one_of
{
static const bool value =
etl::is_same<T, T1>::value ||
etl::is_same<T, T2>::value ||
etl::is_same<T, T3>::value ||
etl::is_same<T, T4>::value ||
etl::is_same<T, T5>::value ||
etl::is_same<T, T6>::value ||
etl::is_same<T, T7>::value ||
etl::is_same<T, T8>::value ||
etl::is_same<T, T9>::value ||
etl::is_same<T, T10>::value ||
etl::is_same<T, T11>::value ||
etl::is_same<T, T12>::value ||
etl::is_same<T, T13>::value ||
etl::is_same<T, T14>::value ||
etl::is_same<T, T15>::value ||
etl::is_same<T, T16>::value;
};
}
#endif

500
src/type_traits_generator.h Normal file
View File

@ -0,0 +1,500 @@
///\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.
******************************************************************************/
/*[[[cog
import cog
cog.outl("#if 0")
]]]*/
/*[[[end]]]*/
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
/*[[[cog
import cog
cog.outl("#endif")
]]]*/
/*[[[end]]]*/
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("// This file has been auto generated. Do not edit this file.")
cog.outl("//***************************************************************************")
]]]*/
/*[[[end]]]*/
//***************************************************************************
// To generate to header file, run this at the command line.
// Note: You will need Python and COG installed.
//
// python -m cogapp -d -e -otypes.h -DHandlers=<n> types_generator.h
// Where <n> is the number of types to support.
//
// e.g.
// To generate handlers for up to 16 types...
// python -m cogapp -d -e -otype_traits.h -DIsOneOf=16 type_traits_generator.h
//
// See generate.bat
//***************************************************************************
#ifndef __ETL_TYPE_TRAITS__
#define __ETL_TYPE_TRAITS__
#include <stddef.h>
#include "platform.h"
#include "nullptr.h"
#if defined(ETL_C11_TYPE_TRAITS_SUPPORTED)
#include <type_traits>
#endif
///\defgroup type_traits type_traits
/// A set of type traits definitions for compilers that do not support the standard header.
/// \ingroup utilities
namespace etl
{
/// integral_constant
///\ingroup type_traits
template <typename T, const T VALUE>
struct integral_constant
{
static const T value = VALUE;
typedef T value_type;
typedef integral_constant<T, VALUE> type;
operator value_type() const
{
return value;
}
};
/// integral_constant specialisations
///\ingroup type_traits
typedef integral_constant<bool, false> false_type;
typedef integral_constant<bool, true> true_type;
/// remove_reference
///\ingroup type_traits
template <typename T> struct remove_reference { typedef T type; };
template <typename T> struct remove_reference<T&> { typedef T type; };
/// add_reference
///\ingroup type_traits
template <typename T> struct add_reference { typedef T& type; };
template <typename T> struct add_reference<T&> { typedef T& type; };
/// remove_pointer
///\ingroup type_traits
template <typename T> struct remove_pointer { typedef T type; };
template <typename T> struct remove_pointer<T*> { typedef T type; };
/// add_pointer
///\ingroup type_traits
template <typename T> struct add_pointer { typedef typename remove_reference<T>::type* type; };
/// is_const
///\ingroup type_traits
template <typename T> struct is_const : false_type {};
template <typename T> struct is_const<const T> : true_type {};
template <typename T> struct is_const<const volatile T> : true_type {};
/// remove_const
///\ingroup type_traits
template <typename T> struct remove_const { typedef T type; };
template <typename T> struct remove_const<const T> { typedef T type; };
/// add_const
///\ingroup type_traits
template <typename T> struct add_const { typedef const T type; };
template <typename T> struct add_const<const T> { typedef const T type; };
/// is_volatile
///\ingroup type_traits
template <typename T> struct is_volatile : false_type {};
template <typename T> struct is_volatile<volatile T> : true_type {};
template <typename T> struct is_volatile<const volatile T> : true_type {};
/// remove_volatile
///\ingroup type_traits
template <typename T> struct remove_volatile { typedef T type; };
template <typename T> struct remove_volatile<volatile T> { typedef T type; };
/// add_volatile
///\ingroup type_traits
template <typename T> struct add_volatile { typedef volatile T type; };
template <typename T> struct add_volatile<volatile T> { typedef volatile T type; };
/// remove_cv
///\ingroup type_traits
template <typename T> struct remove_cv
{
typedef typename remove_volatile<typename remove_const<T>::type>::type type;
};
/// add_cv
///\ingroup type_traits
template <typename T> struct add_cv
{
typedef typename add_volatile<typename add_const<T>::type>::type type;
};
/// is_integral
///\ingroup type_traits
template <typename T> struct is_integral : false_type {};
template <> struct is_integral<bool> : true_type {};
template <> struct is_integral<char> : true_type {};
template <> struct is_integral<unsigned char> : true_type {};
template <> struct is_integral<signed char> : true_type {};
template <> struct is_integral<wchar_t> : true_type {};
template <> struct is_integral<short> : true_type {};
template <> struct is_integral<unsigned short> : true_type {};
template <> struct is_integral<int> : true_type {};
template <> struct is_integral<unsigned int> : true_type {};
template <> struct is_integral<long> : true_type {};
template <> struct is_integral<unsigned long> : true_type {};
template <> struct is_integral<long long> : true_type {};
template <> struct is_integral<unsigned long long> : true_type {};
template <typename T> struct is_integral<const T> : is_integral<T> {};
template <typename T> struct is_integral<volatile T> : is_integral<T> {};
template <typename T> struct is_integral<const volatile T> : is_integral<T> {};
/// is_signed
///\ingroup type_traits
template <typename T> struct is_signed : false_type {};
template <> struct is_signed<char> : integral_constant<bool, (char(255) < 0)> {};
template <> struct is_signed<wchar_t> : public etl::integral_constant<bool, static_cast<bool>(wchar_t(-1) < wchar_t(0))> {};
template <> struct is_signed<signed char> : true_type {};
template <> struct is_signed<short> : true_type {};
template <> struct is_signed<int> : true_type {};
template <> struct is_signed<long> : true_type {};
template <> struct is_signed<long long> : true_type {};
template <> struct is_signed<float> : true_type{};
template <> struct is_signed<double> : true_type{};
template <> struct is_signed<long double> : true_type{};
template <typename T> struct is_signed<const T> : is_signed<T> {};
template <typename T> struct is_signed<volatile T> : is_signed<T> {};
template <typename T> struct is_signed<const volatile T> : is_signed<T> {};
/// is_unsigned
///\ingroup type_traits
template <typename T> struct is_unsigned : false_type {};
template <> struct is_unsigned<bool> : true_type {};
template <> struct is_unsigned<char> : integral_constant<bool, (char(255) > 0)> {};
template <> struct is_unsigned<unsigned char> : true_type {};
template <> struct is_unsigned<wchar_t> : public etl::integral_constant<bool, (wchar_t(-1) > wchar_t(0))> {};
template <> struct is_unsigned<unsigned short> : true_type {};
template <> struct is_unsigned<unsigned int> : true_type {};
template <> struct is_unsigned<unsigned long> : true_type {};
template <> struct is_unsigned<unsigned long long> : true_type {};
template <typename T> struct is_unsigned<const T> : is_unsigned<T> {};
template <typename T> struct is_unsigned<volatile T> : is_unsigned<T> {};
template <typename T> struct is_unsigned<const volatile T> : is_unsigned<T> {};
/// is_floating_point
///\ingroup type_traits
template <typename T> struct is_floating_point : false_type {};
template <> struct is_floating_point<float> : true_type {};
template <> struct is_floating_point<double> : true_type {};
template <> struct is_floating_point<long double> : true_type {};
template <typename T> struct is_floating_point<const T> : is_floating_point<T> {};
template <typename T> struct is_floating_point<volatile T> : is_floating_point<T> {};
template <typename T> struct is_floating_point<const volatile T> : is_floating_point<T> {};
/// is_same
///\ingroup type_traits
template <typename T1, typename T2> struct is_same : public false_type {};
template <typename T> struct is_same<T, T> : public true_type {};
/// is_void
///\ingroup type_traits
template<typename T> struct is_void : false_type {};
template<> struct is_void<void> : true_type {};
/// is_arithmetic
///\ingroup type_traits
template<typename T> struct is_arithmetic : integral_constant<bool, is_integral<T>::value || is_floating_point<T>::value> {};
/// is_fundamental
///\ingroup type_traits
template <typename T> struct is_fundamental : integral_constant<bool, is_arithmetic<T>::value ||
is_void<T>::value ||
is_same<std::nullptr_t,
typename remove_cv<T>::type>::value> {};
/// is_compound
///\ingroup type_traits
template <typename T> struct is_compound : integral_constant<bool, !is_fundamental<T>::value> {};
/// is_array
///\ingroup type_traits
template <typename T> struct is_array : false_type {};
template <typename T> struct is_array<T[]> : true_type {};
template <typename T, size_t MAXN> struct is_array<T[MAXN]> : true_type {};
/// is_pointer
///\ingroup type_traits
template <typename T> struct is_pointer : false_type {};
template <typename T> struct is_pointer<T*> : true_type {};
/// is_reference
///\ingroup type_traits
template <typename T> struct is_reference : false_type {};
template <typename T> struct is_reference<T&> : true_type {};
/// is_pod
/// For C++03, only fundamental and pointers types are recognised.
///\ingroup type_traits
#if defined(ETL_C11_TYPE_TRAITS_SUPPORTED)// && !defined(ETL_IN_UNIT_TEST)
// For compilers that support C++11
template <typename T> struct is_pod : std::is_pod<T> {};
#else
/// For C++03, only fundamental and pointers types are recognised.
template <typename T> struct is_pod : etl::integral_constant<bool, etl::is_fundamental<T>::value ||
etl::is_pointer<T>::value> {};
#endif
#if defined(ETL_C11_TYPE_TRAITS_SUPPORTED) && defined(ETL_C11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED)// && !defined(ETL_IN_UNIT_TEST)
/// is_trivially_constructible
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct is_trivially_constructible : std::is_trivially_constructible<T> {};
/// is_trivially_copy_constructible
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T> {};
/// is_trivially_destructible
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct is_trivially_destructible : std::is_trivially_destructible<T> {};
/// is_trivially_copy_assignable
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct is_trivially_copy_assignable : std::is_trivially_copy_assignable<T> {};
#else
/// is_trivially_constructible
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct is_trivially_constructible : etl::is_pod<T> {};
/// is_trivially_copy_constructible
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct is_trivially_copy_constructible : etl::is_pod<T> {};
/// is_trivially_destructible
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct is_trivially_destructible : etl::is_pod<T> {};
/// is_trivially_copy_assignable
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct is_trivially_copy_assignable : etl::is_pod<T> {};
#endif
/// conditional
///\ingroup type_traits
template <bool B, typename T, typename F> struct conditional { typedef T type; };
template <typename T, typename F> struct conditional<false, T, F> { typedef F type; };
/// make_signed
///\ingroup type_traits
template <typename T> struct make_signed { typedef T type; };
template <> struct make_signed<char> { typedef signed char type; };
template <> struct make_signed<unsigned char> { typedef signed char type; };
template <> struct make_signed<wchar_t>
{
typedef etl::conditional<sizeof(wchar_t) == sizeof(int16_t),
int16_t,
etl::conditional<sizeof(wchar_t) == sizeof(int32_t),
int32_t,
void>::type>::type type;
};
template <> struct make_signed<unsigned short> { typedef short type; };
template <> struct make_signed<unsigned int> { typedef int type; };
template <> struct make_signed<unsigned long> { typedef long type; };
template <> struct make_signed<unsigned long long> { typedef long long type; };
template <typename T> struct make_signed<const T> : add_const<typename make_signed<T>::type> {};
template <typename T> struct make_signed<volatile T> : add_volatile<typename make_signed<T>::type> {};
template <typename T> struct make_signed<const volatile T> : add_const<typename add_volatile<typename make_signed<T>::type>::type> {};
/// make_unsigned
///\ingroup type_traits
template <typename T> struct make_unsigned { typedef T type; };
template <> struct make_unsigned<char> { typedef unsigned char type; };
template <> struct make_unsigned<signed char> { typedef unsigned char type; };
template <> struct make_unsigned<short> { typedef unsigned short type; };
template <> struct make_unsigned<wchar_t>
{
typedef etl::conditional<sizeof(wchar_t) == sizeof(uint16_t),
uint16_t,
etl::conditional<sizeof(wchar_t) == sizeof(uint32_t),
uint32_t,
void>::type>::type type;
};
template <> struct make_unsigned<int> { typedef unsigned int type; };
template <> struct make_unsigned<long> { typedef unsigned long type; };
template <> struct make_unsigned<long long> { typedef unsigned long long type; };
template <typename T> struct make_unsigned<const T> : add_const<typename make_unsigned<T>::type> {};
template <typename T> struct make_unsigned<volatile T> : add_volatile<typename make_unsigned<T>::type> {};
template <typename T> struct make_unsigned<const volatile T> : add_const<typename add_volatile<typename make_unsigned<T>::type>::type> {};
/// enable_if
///\ingroup type_traits
template <bool B, typename T = void> struct enable_if {};
template <typename T> struct enable_if<true, T> { typedef T type; };
/// extent
///\ingroup type_traits
template <typename T, size_t MAXN = 0>
struct extent : integral_constant<size_t, 0> {};
template <typename T>
struct extent<T[], 0> : integral_constant<size_t, 0> {};
template <typename T, size_t MAXN>
struct extent<T[], MAXN> : integral_constant<size_t, extent<T, MAXN - 1>::value> {};
template <typename T, size_t MAXN>
struct extent<T[MAXN], 0> : integral_constant<size_t, MAXN> {};
template <typename T, size_t I, size_t MAXN>
struct extent<T[I], MAXN> : integral_constant<size_t, extent<T, MAXN - 1>::value> {};
/// remove_extent
///\ingroup type_traits
template <typename T> struct remove_extent { typedef T type; };
template <typename T> struct remove_extent<T[]> { typedef T type; };
template <typename T, size_t MAXN> struct remove_extent<T[MAXN]> { typedef T type;};
/// remove_all_extents
///\ingroup type_traits
template <typename T> struct remove_all_extents { typedef T type;};
template <typename T> struct remove_all_extents<T[]> { typedef typename remove_all_extents<T>::type type; };
template <typename T, size_t MAXN> struct remove_all_extents<T[MAXN]> { typedef typename remove_all_extents<T>::type type; };
/// rank
///\ingroup type_traits
template <typename T>struct rank : integral_constant<size_t, 0> {};
template <typename T> struct rank<T[]> : public integral_constant<size_t, rank<T>::value + 1> {};
template <typename T, size_t MAXN> struct rank<T[MAXN]> : public integral_constant<size_t, rank<T>::value + 1> {};
/// decay
///\ingroup type_traits
template <typename T>
struct decay
{
typedef typename etl::remove_reference<T>::type U;
typedef typename etl::conditional<etl::is_array<U>::value,
typename etl::remove_extent<U>::type*,
typename etl::remove_cv<U>::type>::type type;
};
/// is_base_of
///\ingroup type_traits
template<class TBase, class TDerived>
struct is_base_of
{
private:
template<typename T> struct dummy {};
struct internal: TDerived, dummy<int>{};
static TBase* check(TBase*);
template<typename T> static char check(dummy<T>*);
public:
static const bool value = (sizeof(check((internal*)0)) == sizeof(TBase*));
};
/// Alignment templates.
/// These require compiler specific intrinsics.
///\ingroup type_traits
#ifdef ETL_COMPILER_MICROSOFT
template <typename T> struct alignment_of : integral_constant<size_t, size_t(__alignof(T))> {};
#endif
#ifdef ETL_COMPILER_GCC
template <typename T> struct alignment_of : integral_constant<size_t, size_t(__alignof__(T))> {};
#endif
#ifdef ETL_COMPILER_KEIL
template <typename T> struct alignment_of : integral_constant<size_t, size_t(__alignof__(T))> {};
#endif
#ifdef ETL_COMPILER_IAR
template <typename T> struct alignment_of : integral_constant<size_t, size_t(__ALIGNOF__(T))> {};
#endif
#ifdef ETL_COMPILER_TI
template <typename T> struct alignment_of : integral_constant<size_t, size_t(__ALIGNOF__(T))> {};
#endif
/// Specialisation of 'alignment_of' for 'void'.
///\ingroup type_traits
template <> struct alignment_of<void> : integral_constant <size_t, 0>{};
/*[[[cog
import cog
cog.outl("//***************************************************************************")
cog.outl("/// Template to determine if a type is one of a specified list.")
cog.outl("///\ingroup types")
cog.outl("//***************************************************************************")
cog.outl("template <typename T,")
cog.out(" ")
cog.out("typename T1, ")
for n in range(2, int(IsOneOf)):
cog.out("typename T%s = void, " % n)
if n % 4 == 0:
cog.outl("")
cog.out(" ")
cog.outl("typename T%s = void>" % IsOneOf)
cog.outl("struct is_one_of")
cog.outl("{")
cog.outl(" static const bool value = ")
for n in range(1, int(IsOneOf)):
cog.outl(" etl::is_same<T, T%s>::value ||" % n)
cog.outl(" etl::is_same<T, T%s>::value;" % IsOneOf)
cog.outl("};")
]]]*/
/*[[[end]]]*/
}
#endif

View File

@ -89,43 +89,16 @@ SOFTWARE.
TypeName operator ++(int) { TypeName temp(*this); TypeName::operator ++(); return temp; } \
TypeName& operator --() { --value; return *this; } \
TypeName operator --(int) { TypeName temp(*this); TypeName::operator --(); return temp; } \
TypeName& operator +=(const TypeName& rhs) { value += rhs.value; return *this; } \
TypeName& operator -=(const TypeName& rhs) { value -= rhs.value; return *this; } \
TypeName& operator *=(const TypeName& rhs) { value *= rhs.value; return *this; } \
TypeName& operator /=(const TypeName& rhs) { value /= rhs.value; return *this; } \
TypeName& operator %=(const TypeName& rhs) { value %= rhs.value; return *this; } \
TypeName& operator &=(const TypeName& rhs) { value &= rhs.value; return *this; } \
TypeName& operator &=(ValueType mask) { value &= mask; return *this; } \
TypeName& operator |=(const TypeName& rhs) { value |= rhs.value; return *this; } \
TypeName& operator |=(ValueType mask) { value &= mask; return *this; } \
TypeName& operator ^=(const TypeName& rhs) { value ^= rhs.value; return *this; } \
TypeName& operator ^=(ValueType mask) { value ^= mask; return *this; } \
TypeName& operator +=(const ValueType& rhs) { value += rhs; return *this; } \
TypeName& operator -=(const ValueType& rhs) { value -= rhs; return *this; } \
TypeName& operator *=(const ValueType& rhs) { value *= rhs; return *this; } \
TypeName& operator /=(const ValueType& rhs) { value /= rhs; return *this; } \
TypeName& operator %=(const ValueType& rhs) { value %= rhs; return *this; } \
TypeName& operator &=(const ValueType& rhs) { value &= rhs; return *this; } \
TypeName& operator |=(const ValueType& rhs) { value |= rhs; return *this; } \
TypeName& operator ^=(const ValueType& rhs) { value ^= rhs; return *this; } \
TypeName& operator <<=(ValueType distance) { value <<= distance; return *this; } \
TypeName& operator >>=(ValueType distance) { value >>= distance; return *this; } \
\
/* Volatile definitions.*/ \
TypeName(const volatile TypeName &other) : value(other.value) {} \
void operator=(const volatile TypeName &other) volatile { value = other.value; } \
operator ValueType() volatile const { return value; } \
volatile ValueType& get() volatile { return value; } \
const volatile ValueType& get() volatile const { return value; } \
void operator ++() volatile { ++value; } \
volatile TypeName operator ++(int) volatile { volatile TypeName temp(*this); TypeName::operator ++(); return temp; } \
void operator --() volatile { --value; } \
volatile TypeName operator --(int) volatile { volatile TypeName temp(*this); TypeName::operator --(); return temp; } \
void operator +=(const volatile TypeName& rhs) volatile { value += rhs.value; } \
void operator -=(const volatile TypeName& rhs) volatile { value -= rhs.value; } \
void operator *=(const volatile TypeName& rhs) volatile { value *= rhs.value; } \
void operator /=(const volatile TypeName& rhs) volatile { value /= rhs.value; } \
void operator %=(const volatile TypeName& rhs) volatile { value %= rhs.value; } \
void operator &=(const volatile TypeName& rhs) volatile { value &= rhs.value; } \
void operator &=(ValueType mask) volatile { value &= mask; } \
void operator |=(const volatile TypeName& rhs) volatile { value |= rhs.value; } \
void operator |=(ValueType mask) volatile { value &= mask; } \
void operator ^=(const volatile TypeName& rhs) volatile { value ^= rhs.value; } \
void operator ^=(ValueType mask) volatile { value ^= mask; } \
void operator <<=(ValueType distance) volatile { value <<= distance; } \
void operator >>=(ValueType distance) volatile { value >>= distance; } \
private: \
ValueType value; \
public: \

View File

@ -5,7 +5,7 @@ The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
https://www.etlcpp.com
Copyright(c) 2014 jwellbelove
@ -42,7 +42,6 @@ SOFTWARE.
#include "static_assert.h"
#include "alignment.h"
#include "error_handler.h"
#include "largest.h"
#if defined(ETL_COMPILER_KEIL)
#pragma diag_suppress 940
@ -124,6 +123,11 @@ namespace etl
//***************************************************************************
typedef typename largest_type<T1, T2, T3, T4, T5, T6, T7, T8>::type largest_t;
//***************************************************************************
/// The largest size.
//***************************************************************************
static const size_t SIZE = sizeof(largest_t);
//***************************************************************************
/// The largest alignment.
//***************************************************************************
@ -139,46 +143,6 @@ namespace etl
//***************************************************************************
static const type_id_t UNSUPPORTED_TYPE_ID = integral_limits<type_id_t>::max;
//***************************************************************************
/// Do we pass this type by value?
//***************************************************************************
template <typename T>
struct pass_by_value : integral_constant<bool, etl::is_fundamental<T>::value || etl::is_pointer<T>::value>
{
};
//***************************************************************************
/// Define the type for a parameter.
//***************************************************************************
template <typename T, bool>
struct type_definition;
//***************************************************************************
/// Pass by value.
//***************************************************************************
template <typename T>
struct type_definition<T, true>
{
typedef T type;
};
//***************************************************************************
/// Pass by const reference.
//***************************************************************************
template <typename T>
struct type_definition<T, false>
{
typedef const T& type;
};
//***************************************************************************
/// Determines the type for parameters.
//***************************************************************************
template <typename T>
struct parameter_type : public type_definition<T, pass_by_value<T>::value>
{
};
//***************************************************************************
/// Short form of no_type placeholders.
//***************************************************************************
@ -249,14 +213,14 @@ namespace etl
friend class variant;
virtual void read(typename parameter_type<R1>::type value) = 0;
virtual void read(typename parameter_type<R2>::type value) = 0;
virtual void read(typename parameter_type<R3>::type value) = 0;
virtual void read(typename parameter_type<R4>::type value) = 0;
virtual void read(typename parameter_type<R5>::type value) = 0;
virtual void read(typename parameter_type<R6>::type value) = 0;
virtual void read(typename parameter_type<R7>::type value) = 0;
virtual void read(typename parameter_type<R8>::type value) = 0;
virtual void read(typename etl::parameter_type<R1>::type value) = 0;
virtual void read(typename etl::parameter_type<R2>::type value) = 0;
virtual void read(typename etl::parameter_type<R3>::type value) = 0;
virtual void read(typename etl::parameter_type<R4>::type value) = 0;
virtual void read(typename etl::parameter_type<R5>::type value) = 0;
virtual void read(typename etl::parameter_type<R6>::type value) = 0;
virtual void read(typename etl::parameter_type<R7>::type value) = 0;
virtual void read(typename etl::parameter_type<R8>::type value) = 0;
};
//*************************************************************************
@ -269,13 +233,13 @@ namespace etl
friend class variant;
virtual void read(typename parameter_type<R1>::type value) = 0;
virtual void read(typename parameter_type<R2>::type value) = 0;
virtual void read(typename parameter_type<R3>::type value) = 0;
virtual void read(typename parameter_type<R4>::type value) = 0;
virtual void read(typename parameter_type<R5>::type value) = 0;
virtual void read(typename parameter_type<R6>::type value) = 0;
virtual void read(typename parameter_type<R7>::type value) = 0;
virtual void read(typename etl::parameter_type<R1>::type value) = 0;
virtual void read(typename etl::parameter_type<R2>::type value) = 0;
virtual void read(typename etl::parameter_type<R3>::type value) = 0;
virtual void read(typename etl::parameter_type<R4>::type value) = 0;
virtual void read(typename etl::parameter_type<R5>::type value) = 0;
virtual void read(typename etl::parameter_type<R6>::type value) = 0;
virtual void read(typename etl::parameter_type<R7>::type value) = 0;
private:
@ -292,12 +256,12 @@ namespace etl
friend class variant;
virtual void read(typename parameter_type<R1>::type value) = 0;
virtual void read(typename parameter_type<R2>::type value) = 0;
virtual void read(typename parameter_type<R3>::type value) = 0;
virtual void read(typename parameter_type<R4>::type value) = 0;
virtual void read(typename parameter_type<R5>::type value) = 0;
virtual void read(typename parameter_type<R6>::type value) = 0;
virtual void read(typename etl::parameter_type<R1>::type value) = 0;
virtual void read(typename etl::parameter_type<R2>::type value) = 0;
virtual void read(typename etl::parameter_type<R3>::type value) = 0;
virtual void read(typename etl::parameter_type<R4>::type value) = 0;
virtual void read(typename etl::parameter_type<R5>::type value) = 0;
virtual void read(typename etl::parameter_type<R6>::type value) = 0;
private:
@ -315,11 +279,11 @@ namespace etl
friend class variant;
virtual void read(typename parameter_type<R1>::type value) = 0;
virtual void read(typename parameter_type<R2>::type value) = 0;
virtual void read(typename parameter_type<R3>::type value) = 0;
virtual void read(typename parameter_type<R4>::type value) = 0;
virtual void read(typename parameter_type<R5>::type value) = 0;
virtual void read(typename etl::parameter_type<R1>::type value) = 0;
virtual void read(typename etl::parameter_type<R2>::type value) = 0;
virtual void read(typename etl::parameter_type<R3>::type value) = 0;
virtual void read(typename etl::parameter_type<R4>::type value) = 0;
virtual void read(typename etl::parameter_type<R5>::type value) = 0;
private:
@ -338,10 +302,10 @@ namespace etl
friend class variant;
virtual void read(typename parameter_type<R1>::type value) = 0;
virtual void read(typename parameter_type<R2>::type value) = 0;
virtual void read(typename parameter_type<R3>::type value) = 0;
virtual void read(typename parameter_type<R4>::type value) = 0;
virtual void read(typename etl::parameter_type<R1>::type value) = 0;
virtual void read(typename etl::parameter_type<R2>::type value) = 0;
virtual void read(typename etl::parameter_type<R3>::type value) = 0;
virtual void read(typename etl::parameter_type<R4>::type value) = 0;
private:
@ -361,9 +325,9 @@ namespace etl
friend class variant;
virtual void read(typename parameter_type<R1>::type value) = 0;
virtual void read(typename parameter_type<R2>::type value) = 0;
virtual void read(typename parameter_type<R3>::type value) = 0;
virtual void read(typename etl::parameter_type<R1>::type value) = 0;
virtual void read(typename etl::parameter_type<R2>::type value) = 0;
virtual void read(typename etl::parameter_type<R3>::type value) = 0;
private:
@ -384,8 +348,8 @@ namespace etl
friend class variant;
virtual void read(typename parameter_type<R1>::type value) = 0;
virtual void read(typename parameter_type<R2>::type value) = 0;
virtual void read(typename etl::parameter_type<R1>::type value) = 0;
virtual void read(typename etl::parameter_type<R2>::type value) = 0;
private:
@ -407,7 +371,7 @@ namespace etl
friend class variant;
virtual void read(typename parameter_type<R1>::type value) = 0;
virtual void read(typename etl::parameter_type<R1>::type value) = 0;
private:
@ -862,7 +826,7 @@ namespace etl
//***************************************************************************
void clear()
{
type_id = UNSUPPORTED_TYPE_ID;
destruct_current();
}
//***************************************************************************
@ -962,7 +926,7 @@ namespace etl
/// The internal storage.
/// Aligned on a suitable boundary, which should be good for all types.
//***************************************************************************
typename etl::aligned_storage<sizeof(largest_t), etl::largest_alignment<T1, T2, T3, T4, T5, T6, T7, T8>::value>::type data;
typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
//***************************************************************************
/// The id of the current stored type.

984
temp/message_router.h Normal file
View File

@ -0,0 +1,984 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://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_MESSAGE_ROUTER__
#define __ETL_MESSAGE_ROUTER__
#include <stdint.h>
namespace etl
{
/// Allow alternative type for message id.
#if !defined(ETL_MESSAGE_ID_TYPE)
typedef uint_least8_t message_id_t;
#else
typedef ETL_MESSAGE_ID_TYPE message_id_t;
#endif
//***************************************************************************
class imessage
{
public:
virtual ~imessage() {}
virtual etl::message_id_t get_message_id() const = 0;
};
//***************************************************************************
template <const size_t ID_>
class message : public imessage
{
public:
enum
{
ID = ID_
};
//*******************************************
etl::message_id_t get_message_id() const
{
return etl::message_id_t(ID);
}
};
//***************************************************************************
class imessage_router
{
public:
virtual ~imessage_router() {}
virtual void receive(const etl::imessage& message) = 0;
virtual void receive(imessage_router& source, const etl::imessage& message) = 0;
virtual bool accepts(etl::message_id_t id) const = 0;
//*******************************************
bool accepts(const etl::imessage& msg) const
{
return accepts(msg.get_message_id());
}
//*******************************************
void send_message(imessage_router& destination,
const etl::imessage& message)
{
destination.receive(*this, message);
}
};
//***************************************************************************
/// This router can be used either as a sink for messages
/// or as a producer-only of messages such an interrupt routine.
//***************************************************************************
class null_message_router : public imessage_router
{
public:
//*******************************************
void receive(const etl::imessage& message)
{
}
//*******************************************
void receive(etl::imessage_router& source, const etl::imessage& message)
{
}
//*******************************************
bool accepts(etl::message_id_t id) const
{
return false;
}
//*******************************************
static null_message_router& get()
{
static null_message_router instance;
return instance;
}
};
//***************************************************************************
/// Send a message to a router.
/// Sets the 'sender' to etl::null_message_router type.
//***************************************************************************
inline static void send_message(etl::imessage_router& destination,
const etl::imessage& message)
{
destination.receive(message);
}
//***************************************************************************
/// Send a message to a router.
//***************************************************************************
inline static void send_message(etl::imessage_router& source,
etl::imessage_router& destination,
const etl::imessage& message)
{
destination.receive(source, message);
}
//***************************************************************************
// To generate to header file, run this at the command line.
// Note: You will need Python and COG installed.
//
// python -m cogapp -d -e -omessage_router.h -DHandlers=<n> message_router_generator.h
// Where <n> is the number of messages to support.
//
// e.g.
// To generate handlers for up to 16 messages...
// python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h
//
// See CreateMessageProcessor.bat
//***************************************************************************
//***************************************************************************
// The code below has been auto generated. Do not manually edit.
//***************************************************************************
//***************************************************************************
// The definition for all 16 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
class message_router : public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const etl::message_id_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
case T12::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
case T13::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
case T14::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T14&>(msg)); break;
case T15::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T15&>(msg)); break;
case T16::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T16&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: case T16::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 15 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8,
typename T9, typename T10, typename T11, typename T12,
typename T13, typename T14, typename T15>
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
case T12::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
case T13::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
case T14::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T14&>(msg)); break;
case T15::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T15&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 14 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8,
typename T9, typename T10, typename T11, typename T12,
typename T13, typename T14>
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
case T12::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
case T13::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
case T14::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T14&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 13 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8,
typename T9, typename T10, typename T11, typename T12,
typename T13>
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
case T12::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
case T13::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 12 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8,
typename T9, typename T10, typename T11, typename T12>
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
case T12::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID: case T12::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 11 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8,
typename T9, typename T10, typename T11>
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, void, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
case T11::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID: case T11::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 10 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8,
typename T9, typename T10>
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, void, void, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
case T10::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID: case T10::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 9 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8,
typename T9>
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, T9, void, void, void, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
case T9::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
case T9::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 8 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8>
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, T8, void, void, void, void, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
case T8::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 7 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7>
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, T7, void, void, void, void, void, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
case T7::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 6 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6>
class message_router<TProcessor, T1, T2, T3, T4, T5, T6, void, void, void, void, void, void, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
case T6::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 5 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4,
typename T5>
class message_router<TProcessor, T1, T2, T3, T4, T5, void, void, void, void, void, void, void, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
case T5::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 4 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3, typename T4>
class message_router<TProcessor, T1, T2, T3, T4, void, void, void, void, void, void, void, void, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
case T4::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID: case T4::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 3 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2, typename T3>
class message_router<TProcessor, T1, T2, T3, void, void, void, void, void, void, void, void, void, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
case T3::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID: case T3::ID:
return true; break;
default:
return false; break;
}
}
class message_packet
{
public:
explicit message_packet(const imessage& msg)
{
const etl::message_id_t id = msg.get_message_id();
switch (id)
{
case T1::ID: new (&storage) T1(static_cast<const T1&>(msg)); break;
case T2::ID: new (&storage) T2(static_cast<const T2&>(msg)); break;
case T3::ID: new (&storage) T3(static_cast<const T3&>(msg)); break;
default: break;
}
}
~message_packet()
{
static_cast<const etl::imessage*>(storage).~imessage();
}
message_packet(const message_packet& other)
{
const etl::message_id_t id = other.get_imessage().get_message_id();
switch (id)
{
case T1::ID: new (&storage) T1(static_cast<const T1&>(msg)); break;
case T2::ID: new (&storage) T2(static_cast<const T2&>(msg)); break;
case T3::ID: new (&storage) T3(static_cast<const T3&>(msg)); break;
default: break;
}
}
message_packet& operator = (const message_packet& other)
{
if (this != &other)
{
static_cast<const etl::imessage*>(storage).~imessage();
new (this) message_packet(other);
}
}
const etl::imessage& get_imessage() const
{
return *reiniterpret_cast<const imessage*>(storage);
}
operator const imessage&() const
{
return get_imessage();
}
private:
etl::aligned_storage<etl::largest<T1, T2, T3>::size, etl::largest_alignment<T1, T2, T3>::value>::type storage;
};
};
//***************************************************************************
// Specialisation for 2 message types.
//***************************************************************************
template <typename TProcessor,
typename T1, typename T2>
class message_router<TProcessor, T1, T2, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
case T2::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID: case T2::ID:
return true; break;
default:
return false; break;
}
}
};
//***************************************************************************
// Specialisation for 1 message type.
//***************************************************************************
template <typename TProcessor,
typename T1>
class message_router<TProcessor, T1, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
: public imessage_router
{
public:
void receive(const etl::imessage& msg)
{
receive(etl::null_message_router::get(), msg);
}
void receive(etl::imessage_router& source, const etl::imessage& msg)
{
const size_t id = msg.get_message_id();
switch (id)
{
case T1::ID: static_cast<TProcessor*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
default: static_cast<TProcessor*>(this)->on_receive_unknown(source, msg); break;
}
}
bool accepts(etl::message_id_t id) const
{
switch (id)
{
case T1::ID:
return true; break;
default:
return false; break;
}
}
};
}
#endif

View File

@ -172,6 +172,8 @@
<Unit filename="../../src/fnv_1.h" />
<Unit filename="../../src/forward_list.h" />
<Unit filename="../../src/frame_check_sequence.h" />
<Unit filename="../../src/fsm.h" />
<Unit filename="../../src/fsm_generator.h" />
<Unit filename="../../src/function.h" />
<Unit filename="../../src/functional.h" />
<Unit filename="../../src/functors.h" />
@ -193,12 +195,17 @@
<Unit filename="../../src/iterator.h" />
<Unit filename="../../src/jenkins.h" />
<Unit filename="../../src/largest.h" />
<Unit filename="../../src/largest_generator.h" />
<Unit filename="../../src/list.h" />
<Unit filename="../../src/log.h" />
<Unit filename="../../src/map.h" />
<Unit filename="../../src/memory.h" />
<Unit filename="../../src/message_bus.h" />
<Unit filename="../../src/message_processor.h" />
<Unit filename="../../src/message_processor_generator.h" />
<Unit filename="../../src/message_router.h" />
<Unit filename="../../src/message_router_generator.h" />
<Unit filename="../../src/message_types.h" />
<Unit filename="../../src/multimap.h" />
<Unit filename="../../src/multiset.h" />
<Unit filename="../../src/murmur3.h" />
@ -206,6 +213,7 @@
<Unit filename="../../src/numeric.h" />
<Unit filename="../../src/observer.h" />
<Unit filename="../../src/optional.h" />
<Unit filename="../../src/packet.h" />
<Unit filename="../../src/parameter_type.h" />
<Unit filename="../../src/pearson.cpp" />
<Unit filename="../../src/pearson.h" />
@ -226,12 +234,16 @@
<Unit filename="../../src/reference_flat_multimap.h" />
<Unit filename="../../src/reference_flat_multiset.h" />
<Unit filename="../../src/reference_flat_set.h" />
<Unit filename="../../src/scheduler.h" />
<Unit filename="../../src/set.h" />
<Unit filename="../../src/smallest.h" />
<Unit filename="../../src/smallest_generator.h" />
<Unit filename="../../src/stack.h" />
<Unit filename="../../src/static_assert.h" />
<Unit filename="../../src/task.h" />
<Unit filename="../../src/type_def.h" />
<Unit filename="../../src/type_traits.h" />
<Unit filename="../../src/type_traits_generator.h" />
<Unit filename="../../src/u16string.h" />
<Unit filename="../../src/u32string.h" />
<Unit filename="../../src/unordered_map.h" />
@ -273,6 +285,7 @@
<Unit filename="../test_flat_set.cpp" />
<Unit filename="../test_fnv_1.cpp" />
<Unit filename="../test_forward_list.cpp" />
<Unit filename="../test_fsm.cpp" />
<Unit filename="../test_function.cpp" />
<Unit filename="../test_functional.cpp" />
<Unit filename="../test_hash.cpp" />
@ -291,12 +304,15 @@
<Unit filename="../test_map.cpp" />
<Unit filename="../test_maths.cpp" />
<Unit filename="../test_memory.cpp" />
<Unit filename="../test_message_bus.cpp" />
<Unit filename="../test_message_router.cpp" />
<Unit filename="../test_multimap.cpp" />
<Unit filename="../test_multiset.cpp" />
<Unit filename="../test_murmur3.cpp" />
<Unit filename="../test_numeric.cpp" />
<Unit filename="../test_observer.cpp" />
<Unit filename="../test_optional.cpp" />
<Unit filename="../test_packet.cpp" />
<Unit filename="../test_pearson.cpp" />
<Unit filename="../test_pool.cpp" />
<Unit filename="../test_priority_queue.cpp" />
@ -314,12 +330,14 @@
<Unit filename="../test_string_u16.cpp" />
<Unit filename="../test_string_u32.cpp" />
<Unit filename="../test_string_wchar_t.cpp" />
<Unit filename="../test_task_scheduler.cpp" />
<Unit filename="../test_type_def.cpp" />
<Unit filename="../test_type_traits.cpp" />
<Unit filename="../test_unordered_map.cpp" />
<Unit filename="../test_unordered_multimap.cpp" />
<Unit filename="../test_unordered_multiset.cpp" />
<Unit filename="../test_unordered_set.cpp" />
<Unit filename="../test_user_type.cpp" />
<Unit filename="../test_utility.cpp" />
<Unit filename="../test_variant.cpp" />
<Unit filename="../test_vector.cpp" />

View File

@ -3289,7 +3289,7 @@
"CurrentTest.h"
"ReportAssertImpl.h"
1501066687 source:d:\users\john\documents\programming\github\etl\test\test_algorithm.cpp
1501803139 source:d:\users\john\documents\programming\github\etl\test\test_algorithm.cpp
"UnitTest++.h"
"algorithm.h"
"container.h"
@ -3538,7 +3538,7 @@
"static_assert.h"
"exception.h"
1501067284 source:d:\users\john\documents\programming\github\etl\test\test_deque.cpp
1501803126 source:d:\users\john\documents\programming\github\etl\test\test_deque.cpp
"UnitTest++.h"
"ExtraCheckMacros.h"
"deque.h"
@ -3727,7 +3727,7 @@
1482623723 v_1.h"
1497713618 source:d:\users\john\documents\programming\github\etl\test\test_forward_list.cpp
1501803126 source:d:\users\john\documents\programming\github\etl\test\test_forward_list.cpp
"UnitTest++.h"
"ExtraCheckMacros.h"
"data.h"
@ -4151,12 +4151,12 @@
"../exception.h"
"../error_handler.h"
1500986416 source:d:\users\john\documents\programming\github\etl\test\test_type_traits.cpp
1501803140 source:d:\users\john\documents\programming\github\etl\test\test_type_traits.cpp
"UnitTest++.h"
"type_traits.h"
<type_traits>
1500986416 source:d:\users\john\documents\programming\github\etl\test\test_variant.cpp
1501803140 source:d:\users\john\documents\programming\github\etl\test\test_variant.cpp
"UnitTest++.h"
"ExtraCheckMacros.h"
"variant.h"
@ -5302,7 +5302,7 @@
"platform.h"
"static_assert.h"
1501066686 d:\users\john\documents\programming\github\etl\src\algorithm.h
1502118978 d:\users\john\documents\programming\github\etl\src\algorithm.h
<algorithm>
<iterator>
<utility>
@ -5312,7 +5312,7 @@
"iterator.h"
"type_traits.h"
1501066686 d:\users\john\documents\programming\github\etl\src\type_traits.h
1502118978 d:\users\john\documents\programming\github\etl\src\type_traits.h
<stddef.h>
"platform.h"
"nullptr.h"
@ -5322,7 +5322,7 @@
<stddef.h>
<iterator>
1500986416 d:\users\john\documents\programming\github\etl\src\alignment.h
1502118978 d:\users\john\documents\programming\github\etl\src\alignment.h
<stdint.h>
"type_traits.h"
"static_assert.h"
@ -5370,7 +5370,7 @@
<stdint.h>
"log.h"
1501066686 d:\users\john\documents\programming\github\etl\src\smallest.h
1502118978 d:\users\john\documents\programming\github\etl\src\smallest.h
<stdint.h>
"integral_limits.h"
@ -5484,7 +5484,7 @@
"static_assert.h"
"exception.h"
1501067284 d:\users\john\documents\programming\github\etl\src\deque.h
1501803126 d:\users\john\documents\programming\github\etl\src\deque.h
<stddef.h>
<stdint.h>
<iterator>
@ -5561,7 +5561,7 @@
"../error_handler.h"
"../debug_count.h"
1501067284 d:\users\john\documents\programming\github\etl\src\vector.h
1501803126 d:\users\john\documents\programming\github\etl\src\vector.h
<type_traits>
<stddef.h>
<stdint.h>
@ -5606,7 +5606,7 @@
"../ivector.h"
"../error_handler.h"
1497713617 d:\users\john\documents\programming\github\etl\src\forward_list.h
1501803126 d:\users\john\documents\programming\github\etl\src\forward_list.h
<iterator>
<algorithm>
<functional>
@ -5703,12 +5703,12 @@
"nullptr.h"
"parameter_type.h"
1501067284 d:\users\john\documents\programming\github\etl\src\largest.h
1502118978 d:\users\john\documents\programming\github\etl\src\largest.h
"type_traits.h"
"smallest.h"
"static_assert.h"
1501067284 d:\users\john\documents\programming\github\etl\src\list.h
1502118941 d:\users\john\documents\programming\github\etl\src\list.h
<iterator>
<algorithm>
<functional>
@ -5930,7 +5930,7 @@
"exception.h"
"error_handler.h"
1500986416 d:\users\john\documents\programming\github\etl\src\variant.h
1501803139 d:\users\john\documents\programming\github\etl\src\variant.h
<stdint.h>
"platform.h"
"array.h"
@ -5941,7 +5941,6 @@
"static_assert.h"
"alignment.h"
"error_handler.h"
"largest.h"
1479515291 d:\users\john\documents\programming\github\etl\src\visitor.h
@ -7825,7 +7824,7 @@
<iterator>
"type_traits.h"
1501066686 d:\users\john\documents\programming\github\etl\src\memory.h
1502118978 d:\users\john\documents\programming\github\etl\src\memory.h
<iterator>
<algorithm>
"type_traits.h"
@ -7835,10 +7834,10 @@
<assert.h>
"platform.h"
1501067284 source:d:\users\john\documents\programming\github\etl\src\random.cpp
1501803126 source:d:\users\john\documents\programming\github\etl\src\random.cpp
"random.h"
1501067284 d:\users\john\documents\programming\github\etl\src\random.h
1501803126 d:\users\john\documents\programming\github\etl\src\random.h
<stdint.h>
1494277861 source:d:\users\john\documents\programming\github\etl\test\test_intrusive_flat_map.cpp
@ -7933,7 +7932,7 @@
"UnitTest++.h"
"iterator.h"
1500986416 source:d:\users\john\documents\programming\github\etl\test\test_memory.cpp
1501803139 source:d:\users\john\documents\programming\github\etl\test\test_memory.cpp
"UnitTest++.h"
"memory.h"
"debug_count.h"
@ -7944,7 +7943,7 @@
<stdint.h>
<vector>
1501067284 source:d:\users\john\documents\programming\github\etl\test\test_random.cpp
1501803126 source:d:\users\john\documents\programming\github\etl\test\test_random.cpp
"UnitTest++.h"
<stdint.h>
"random.h"
@ -7952,7 +7951,7 @@
<algorithm>
<fstream>
1501067284 source:d:\users\john\documents\programming\github\etl\test\test_vector_non_trivial.cpp
1501803126 source:d:\users\john\documents\programming\github\etl\test\test_vector_non_trivial.cpp
"UnitTest++.h"
<vector>
<array>
@ -8229,3 +8228,133 @@
"exception.h"
"vector.h"
1479515291 source:d:\users\john\documents\programming\github\etl\test\test_compile.cpp
"algorithm.h"
"alignment.h"
"array.h"
"bitset.h"
"container.h"
"crc8_ccitt.h"
"crc16.h"
"crc16_ccitt.h"
"crc16_kermit.h"
"crc32.h"
"crc64_ecma.h"
"cyclic_value.h"
"deque.h"
"io_port.h"
"vector.h"
"variant.h"
"list.h"
"map.h"
<algorithm>
1501803139 source:d:\users\john\documents\programming\github\etl\test\test_fsm.cpp
"UnitTest++.h"
"fsm.h"
"enum_type.h"
"container.h"
<iostream>
1501803139 d:\users\john\documents\programming\github\etl\src\fsm.h
<stdint.h>
"array.h"
"nullptr.h"
"error_handler.h"
"exception.h"
"user_type.h"
"message_router.h"
"integral_limits.h"
"largest.h"
1501803139 d:\users\john\documents\programming\github\etl\src\user_type.h
1501803139 d:\users\john\documents\programming\github\etl\src\message_router.h
<stdint.h>
"message.h"
"message_types.h"
"alignment.h"
"error_handler.h"
"exception.h"
"largest.h"
1501803140 source:d:\users\john\documents\programming\github\etl\test\test_message_router.cpp
"UnitTest++.h"
"ExtraCheckMacros.h"
"message_router.h"
"queue.h"
"largest.h"
"packet.h"
1501803139 d:\users\john\documents\programming\github\etl\src\packet.h
"platform.h"
"static_assert.h"
"alignment.h"
1501803140 source:d:\users\john\documents\programming\github\etl\test\test_packet.cpp
"UnitTest++.h"
"ExtraCheckMacros.h"
"packet.h"
"largest.h"
"queue.h"
"pool.h"
1501803140 source:d:\users\john\documents\programming\github\etl\test\test_task_scheduler.cpp
"UnitTest++.h"
<stdint.h>
<string>
<vector>
"task.h"
"scheduler.h"
"container.h"
1501803139 d:\users\john\documents\programming\github\etl\src\task.h
<stdint.h>
"error_handler.h"
"exception.h"
1501803139 d:\users\john\documents\programming\github\etl\src\scheduler.h
<stdint.h>
"vector.h"
"nullptr.h"
"error_handler.h"
"exception.h"
"task.h"
"type_traits.h"
"function.h"
1501803139 d:\users\john\documents\programming\github\etl\src\message.h
<stdint.h>
"error_handler.h"
"exception.h"
"message_types.h"
1501803139 d:\users\john\documents\programming\github\etl\src\message_types.h
<stdint.h>
1501803139 source:d:\users\john\documents\programming\github\etl\test\test_message_bus.cpp
"UnitTest++.h"
"ExtraCheckMacros.h"
"message_router.h"
"message_bus.h"
"queue.h"
"largest.h"
"packet.h"
1501803139 d:\users\john\documents\programming\github\etl\src\message_bus.h
<stdint.h>
<algorithm>
"algorithm.h"
"vector.h"
"nullptr.h"
"error_handler.h"
"exception.h"
"message_types.h"
"message.h"
"message_router.h"
1501803140 source:d:\users\john\documents\programming\github\etl\test\test_user_type.cpp
"UnitTest++.h"
<string>
"user_type.h"

View File

@ -2,269 +2,24 @@
<CodeBlocks_layout_file>
<FileVersion major="1" minor="0" />
<ActiveTarget name="Windows" />
<File name="..\test_memory.cpp" open="0" top="0" tabpos="25" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="15446" topLine="391" />
</Cursor>
</File>
<File name="..\..\src\vector.h" open="0" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="15560" topLine="342" />
</Cursor>
</File>
<File name="..\..\src\error_handler.h" open="0" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="4288" topLine="74" />
</Cursor>
</File>
<File name="..\test_list.cpp" open="0" top="0" tabpos="27" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="17914" topLine="493" />
</Cursor>
</File>
<File name="..\..\src\queue.h" open="0" top="0" tabpos="17" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="11193" topLine="229" />
</Cursor>
</File>
<File name="..\test_algorithm.cpp" open="0" top="0" tabpos="8" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="11590" topLine="274" />
</Cursor>
</File>
<File name="..\test_type_traits.cpp" open="0" top="0" tabpos="11" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="37662" topLine="472" />
</Cursor>
</File>
<File name="..\..\src\unordered_multimap.h" open="0" top="0" tabpos="10" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="22871" topLine="625" />
</Cursor>
</File>
<File name="..\..\src\private\pvoidvector.h" open="0" top="0" tabpos="19" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="7770" topLine="137" />
</Cursor>
</File>
<File name="..\..\src\deque.h" open="0" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="54765" topLine="1616" />
</Cursor>
</File>
<File name="..\main.cpp" open="0" top="0" tabpos="18" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="141" topLine="0" />
</Cursor>
</File>
<File name="..\test_vector.cpp" open="0" top="0" tabpos="9" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="1450" topLine="0" />
</Cursor>
</File>
<File name="..\..\src\unordered_multiset.h" open="0" top="0" tabpos="9" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="22451" topLine="619" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\Test.cpp" open="0" top="0" tabpos="19" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="699" topLine="0" />
</Cursor>
</File>
<File name="..\..\src\integral_limits.h" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="7252" topLine="152" />
</Cursor>
</File>
<File name="..\test_flat_multimap.cpp" open="0" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="3425" topLine="85" />
</Cursor>
</File>
<File name="..\..\src\alignment.h" open="0" top="0" tabpos="16" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="1527" topLine="15" />
</Cursor>
</File>
<File name="..\test_flat_multiset.cpp" open="0" top="0" tabpos="21" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="3011" topLine="58" />
</Cursor>
</File>
<File name="..\test_flat_map.cpp" open="0" top="0" tabpos="20" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="18781" topLine="559" />
</Cursor>
</File>
<File name="..\..\src\intrusive_flat_map.h" open="0" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="4065" topLine="242" />
</Cursor>
</File>
<File name="..\test_io_port.cpp" open="0" top="0" tabpos="14" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="1452" topLine="3" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\Checks.h" open="0" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="469" topLine="0" />
</Cursor>
</File>
<File name="..\test_map.cpp" open="0" top="0" tabpos="19" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="6368" topLine="164" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\TestReporterStdout.cpp" open="0" top="0" tabpos="25" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="883" topLine="0" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\TestRunner.cpp" open="0" top="0" tabpos="20" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="2279" topLine="25" />
</Cursor>
</File>
<File name="..\test_vector_pointer.cpp" open="0" top="0" tabpos="10" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="1450" topLine="0" />
</Cursor>
</File>
<File name="..\test_deque.cpp" open="0" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="1445" topLine="0" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\Config.h" open="0" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="792" topLine="7" />
</Cursor>
</File>
<File name="..\test_intrusive_list.cpp" open="0" top="0" tabpos="24" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="27580" topLine="735" />
</Cursor>
</File>
<File name="..\..\src\flat_map.h" open="0" top="0" tabpos="8" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="2722" topLine="43" />
</Cursor>
</File>
<File name="..\test_integral_limits.cpp" open="0" top="0" tabpos="18" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="0" topLine="49" />
</Cursor>
</File>
<File name="..\..\src\forward_list.h" open="0" top="0" tabpos="11" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="31509" topLine="979" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\TestMacros.h" open="0" top="0" tabpos="13" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="1865" topLine="28" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\TestRunner.h" open="0" top="0" tabpos="21" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="156" topLine="0" />
</Cursor>
</File>
<File name="..\test_flat_set.cpp" open="0" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="11541" topLine="359" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\Win32\TimeHelpers.cpp" open="0" top="0" tabpos="9" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="103" topLine="6" />
</Cursor>
</File>
<File name="..\..\src\variant.h" open="0" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="36839" topLine="839" />
</Cursor>
</File>
<File name="..\..\src\flat_multimap.h" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="0" topLine="87" />
</Cursor>
</File>
<File name="..\test_intrusive_forward_list.cpp" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="29068" topLine="703" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\TestResults.cpp" open="0" top="0" tabpos="24" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="537" topLine="0" />
</Cursor>
</File>
<File name="..\..\src\unordered_set.h" open="0" top="0" tabpos="8" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="22041" topLine="620" />
</Cursor>
</File>
<File name="..\..\src\static_assert.h" open="0" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="1477" topLine="0" />
</Cursor>
</File>
<File name="..\..\src\intrusive_flat_multiset.h" open="0" top="0" tabpos="11" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="7605" topLine="248" />
</Cursor>
</File>
<File name="..\..\src\intrusive_flat_multimap.h" open="0" top="0" tabpos="9" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="3269" topLine="248" />
</Cursor>
</File>
<File name="..\..\src\iterator.h" open="0" top="0" tabpos="17" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="1557" topLine="0" />
</Cursor>
</File>
<File name="..\test_forward_list.cpp" open="1" top="1" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="8719" topLine="184" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\CurrentTest.cpp" open="0" top="0" tabpos="26" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="368" topLine="0" />
</Cursor>
</File>
<File name="..\..\src\algorithm.h" open="0" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="0" topLine="0" />
</Cursor>
</File>
<File name="..\..\src\type_traits.h" open="0" top="0" tabpos="12" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="16936" topLine="334" />
</Cursor>
</File>
<File name="..\test_iterator.cpp" open="0" top="0" tabpos="16" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<File name="..\..\..\unittest-cpp\UnitTest++\TestReporterStdout.cpp" open="0" top="0" tabpos="25" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="6722" topLine="118" />
<Cursor1 position="883" topLine="0" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\ExecuteTest.h" open="0" top="0" tabpos="18" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<File name="..\..\..\unittest-cpp\UnitTest++\Checks.h" open="0" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="426" topLine="0" />
</Cursor>
</File>
<File name="..\..\src\list.h" open="0" top="0" tabpos="22" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="35098" topLine="1063" />
</Cursor>
</File>
<File name="..\..\src\binary.h" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="14624" topLine="373" />
<Cursor1 position="469" topLine="0" />
</Cursor>
</File>
<File name="..\..\src\intrusive_flat_set.h" open="0" top="0" tabpos="13" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
@ -272,4 +27,64 @@
<Cursor1 position="7487" topLine="243" />
</Cursor>
</File>
<File name="..\..\src\flat_map.h" open="0" top="0" tabpos="8" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="2722" topLine="43" />
</Cursor>
</File>
<File name="..\..\src\error_handler.h" open="0" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="4288" topLine="74" />
</Cursor>
</File>
<File name="..\main.cpp" open="0" top="0" tabpos="18" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="141" topLine="0" />
</Cursor>
</File>
<File name="..\..\src\flat_multimap.h" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="0" topLine="87" />
</Cursor>
</File>
<File name="..\..\src\queue.h" open="0" top="0" tabpos="17" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="11193" topLine="229" />
</Cursor>
</File>
<File name="..\..\..\unittest-cpp\UnitTest++\TestRunner.h" open="0" top="0" tabpos="21" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="156" topLine="0" />
</Cursor>
</File>
<File name="..\..\src\message_bus.h" open="1" top="1" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="10784" topLine="332" />
</Cursor>
</File>
<File name="..\test_type_traits.cpp" open="0" top="0" tabpos="11" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="37662" topLine="472" />
</Cursor>
</File>
<File name="..\test_map.cpp" open="0" top="0" tabpos="19" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="6368" topLine="164" />
</Cursor>
</File>
<File name="..\test_forward_list.cpp" open="1" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="16670" topLine="442" />
</Cursor>
</File>
<File name="..\test_flat_multimap.cpp" open="0" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="3425" topLine="85" />
</Cursor>
</File>
<File name="..\..\src\vector.h" open="0" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="15560" topLine="342" />
</Cursor>
</File>
</CodeBlocks_layout_file>

View File

@ -42,6 +42,39 @@ namespace
typedef std::vector<int> Data;
Data data = { 2, 1, 4, 3, 6, 5, 8, 7, 10, 9 };
struct StructData
{
int a;
int b;
};
bool operator ==(const StructData& lhs, const StructData& rhs)
{
return (lhs.a == rhs.a) && (lhs.b == rhs.b);
}
struct StructDataPredicate
{
bool operator ()(const StructData& lhs, const StructData& rhs) const
{
return lhs.a < rhs.a;
}
};
struct StructDataEquality
{
bool operator ()(const StructData& lhs, const StructData& rhs) const
{
return lhs.a == rhs.a;
}
};
std::ostream& operator << (std::ostream& os, const StructData& data)
{
os << data.a << "," << data.b;
return os;
}
SUITE(test_algorithm)
{
//=========================================================================
@ -543,10 +576,40 @@ namespace
int data1[] = { 1, 2, 3, 5, 6, 7, 8 };
// Find the element not less than 4.
int* p = std::find_if_not(std::begin(data1), std::end(data1), std::bind2nd(std::less<int>(), 4));
int* p = etl::find_if_not(std::begin(data1), std::end(data1), std::bind2nd(std::less<int>(), 4));
CHECK_EQUAL(5, *p);
}
//=========================================================================
TEST(binary_find)
{
int data1[] = { 1, 2, 3, 5, 6, 7, 8 };
// Find the element of value 5.
int* p = etl::binary_find(std::begin(data1), std::end(data1), 5);
CHECK_EQUAL(5, *p);
// Find the element of value 4.
p = etl::binary_find(std::begin(data1), std::end(data1), 4);
CHECK_EQUAL(std::end(data1), p);
}
//=========================================================================
TEST(binary_find_StructDataPredicate_StructDataEquality)
{
StructData data1[] = { { 1, 8 }, { 2, 7 }, { 3, 6 },{ 4, 5 },{ 5, 4 },{ 6, 3 },{ 7, 2 },{ 8, 1 } };
StructData test1 = { 4, 5 };
StructData test2 = { 9, 0 };
// Find the element of value 5.
StructData* p = etl::binary_find(std::begin(data1), std::end(data1), test1, StructDataPredicate(), StructDataEquality());
CHECK_EQUAL(test1, *p);
// Find the element of value 4.
p = etl::binary_find(std::begin(data1), std::end(data1), test2, StructDataPredicate(), StructDataEquality());
CHECK_EQUAL(std::end(data1), p);
}
//=========================================================================
TEST(for_each_if)
{

503
test/test_fsm.cpp Normal file
View File

@ -0,0 +1,503 @@
/******************************************************************************
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.
******************************************************************************/
#include "UnitTest++.h"
#include "fsm.h"
#include "enum_type.h"
#include "container.h"
#include <iostream>
namespace
{
const etl::message_router_id_t MOTOR_CONTROL = 0;
//***************************************************************************
// Events
struct EventId
{
enum enum_type
{
START,
STOP,
STOPPED,
SET_SPEED,
UNSUPPORTED
};
ETL_DECLARE_ENUM_TYPE(EventId, etl::message_id_t)
ETL_ENUM_TYPE(START, "Start")
ETL_ENUM_TYPE(STOP, "Stop")
ETL_ENUM_TYPE(STOPPED, "Stopped")
ETL_ENUM_TYPE(SET_SPEED, "Set Speed")
ETL_ENUM_TYPE(UNSUPPORTED, "Unsupported")
ETL_END_ENUM_TYPE
};
//***********************************
class Start : public etl::message<EventId::START>
{
};
//***********************************
class Stop : public etl::message<EventId::STOP>
{
public:
Stop() : isEmergencyStop(false) {}
Stop(bool emergency) : isEmergencyStop(emergency) {}
const bool isEmergencyStop;
};
//***********************************
class SetSpeed : public etl::message<EventId::SET_SPEED>
{
public:
SetSpeed(int speed) : speed(speed) {}
const int speed;
};
//***********************************
class Stopped : public etl::message<EventId::STOPPED>
{
};
//***********************************
class Unsupported : public etl::message<EventId::UNSUPPORTED>
{
};
//***************************************************************************
// States
struct StateId
{
enum enum_type
{
IDLE,
RUNNING,
WINDING_DOWN,
LOCKED,
NUMBER_OF_STATES
};
ETL_DECLARE_ENUM_TYPE(StateId, etl::fsm_state_id_t)
ETL_ENUM_TYPE(IDLE, "Idle")
ETL_ENUM_TYPE(RUNNING, "Running")
ETL_ENUM_TYPE(WINDING_DOWN, "Winding Down")
ETL_ENUM_TYPE(LOCKED, "Locked")
ETL_END_ENUM_TYPE
};
//***********************************
// The motor control FSM.
//***********************************
class MotorControl : public etl::fsm
{
public:
MotorControl(etl::ifsm_state** p_states, size_t size)
: fsm(MOTOR_CONTROL)
{
set_states(p_states, size);
ClearStatistics();
}
//***********************************
void ClearStatistics()
{
startCount = 0;
stopCount = 0;
setSpeedCount = 0;
unknownCount = 0;
stoppedCount = 0;
isLampOn = false;
speed = 0;
}
//***********************************
void SetSpeed(int speed_)
{
speed = speed_;
}
//***********************************
void TurnRunningLampOn()
{
isLampOn = true;
}
//***********************************
void TurnRunningLampOff()
{
isLampOn = false;
}
int startCount;
int stopCount;
int setSpeedCount;
int unknownCount;
int stoppedCount;
bool isLampOn;
int speed;
};
//***********************************
// The idle state.
//***********************************
class Idle : public etl::fsm_state<MotorControl, Idle, StateId::IDLE, Start>
{
public:
//***********************************
etl::fsm_state_id_t on_event(etl::imessage_router& sender, const Start& event)
{
++get_fsm_context().startCount;
return StateId::RUNNING;
}
//***********************************
etl::fsm_state_id_t on_event_unknown(etl::imessage_router& sender, const etl::imessage& event)
{
++get_fsm_context().unknownCount;
return STATE_ID;
}
//***********************************
etl::fsm_state_id_t on_enter_state()
{
get_fsm_context().TurnRunningLampOff();
return StateId::LOCKED;
}
};
//***********************************
// The running state.
//***********************************
class Running : public etl::fsm_state<MotorControl, Running, StateId::RUNNING, Stop, SetSpeed>
{
public:
//***********************************
etl::fsm_state_id_t on_event(etl::imessage_router& sender, const Stop& event)
{
++get_fsm_context().stopCount;
if (event.isEmergencyStop)
{
return StateId::IDLE;
}
else
{
return StateId::WINDING_DOWN;
}
}
//***********************************
etl::fsm_state_id_t on_event(etl::imessage_router& sender, const SetSpeed& event)
{
++get_fsm_context().setSpeedCount;
get_fsm_context().SetSpeed(event.speed);
return STATE_ID;
}
//***********************************
etl::fsm_state_id_t on_event_unknown(etl::imessage_router& sender, const etl::imessage& event)
{
++get_fsm_context().unknownCount;
return STATE_ID;
}
//***********************************
etl::fsm_state_id_t on_enter_state()
{
get_fsm_context().TurnRunningLampOn();
return STATE_ID;
}
};
//***********************************
// The winding down state.
//***********************************
class WindingDown : public etl::fsm_state<MotorControl, WindingDown, StateId::WINDING_DOWN, Stopped>
{
public:
//***********************************
etl::fsm_state_id_t on_event(etl::imessage_router& source, const Stopped& event)
{
++get_fsm_context().stoppedCount;
return StateId::IDLE;
}
//***********************************
etl::fsm_state_id_t on_event_unknown(etl::imessage_router& source, const etl::imessage& event)
{
++get_fsm_context().unknownCount;
return STATE_ID;
}
};
//***********************************
// The locked state.
//***********************************
class Locked : public etl::fsm_state<MotorControl, Locked, StateId::LOCKED>
{
public:
//***********************************
etl::fsm_state_id_t on_event_unknown(etl::imessage_router& source, const etl::imessage& event)
{
++get_fsm_context().unknownCount;
return STATE_ID;
}
};
// The states.
Idle idle;
Running running;
WindingDown windingDown;
Locked locked;
etl::ifsm_state* stateList[StateId::NUMBER_OF_STATES] =
{
&idle, &running, &windingDown, &locked
};
MotorControl motorControl(stateList, etl::size(stateList));
SUITE(test_map)
{
//*************************************************************************
TEST(test_fsm)
{
etl::null_message_router nmr;
motorControl.reset();
motorControl.ClearStatistics();
CHECK(!motorControl.is_started());
// Start the FSM.
motorControl.start();
CHECK(motorControl.is_started());
// Now in Idle state.
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(false, motorControl.isLampOn);
CHECK_EQUAL(0, motorControl.setSpeedCount);
CHECK_EQUAL(0, motorControl.speed);
CHECK_EQUAL(0, motorControl.startCount);
CHECK_EQUAL(0, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(0, motorControl.unknownCount);
// Send unhandled events.
motorControl.receive(nmr, Stop());
motorControl.receive(nmr, Stopped());
motorControl.receive(nmr, SetSpeed(10));
CHECK_EQUAL(StateId::IDLE, motorControl.get_state_id());
CHECK_EQUAL(StateId::IDLE, motorControl.get_state().get_state_id());
CHECK_EQUAL(false, motorControl.isLampOn);
CHECK_EQUAL(0, motorControl.setSpeedCount);
CHECK_EQUAL(0, motorControl.speed);
CHECK_EQUAL(0, motorControl.startCount);
CHECK_EQUAL(0, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(3, motorControl.unknownCount);
// Send Start event.
motorControl.receive(nmr, Start());
// Now in Running state.
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(true, motorControl.isLampOn);
CHECK_EQUAL(0, motorControl.setSpeedCount);
CHECK_EQUAL(0, motorControl.speed);
CHECK_EQUAL(1, motorControl.startCount);
CHECK_EQUAL(0, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(3, motorControl.unknownCount);
// Send unhandled events.
motorControl.receive(nmr, Start());
motorControl.receive(nmr, Stopped());
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(true, motorControl.isLampOn);
CHECK_EQUAL(0, motorControl.setSpeedCount);
CHECK_EQUAL(0, motorControl.speed);
CHECK_EQUAL(1, motorControl.startCount);
CHECK_EQUAL(0, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(5, motorControl.unknownCount);
// Send SetSpeed event.
motorControl.receive(nmr, SetSpeed(100));
// Still in Running state.
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(true, motorControl.isLampOn);
CHECK_EQUAL(1, motorControl.setSpeedCount);
CHECK_EQUAL(100, motorControl.speed);
CHECK_EQUAL(1, motorControl.startCount);
CHECK_EQUAL(0, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(5, motorControl.unknownCount);
// Send Stop event.
motorControl.receive(nmr, Stop());
// Now in WindingDown state.
CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(true, motorControl.isLampOn);
CHECK_EQUAL(1, motorControl.setSpeedCount);
CHECK_EQUAL(100, motorControl.speed);
CHECK_EQUAL(1, motorControl.startCount);
CHECK_EQUAL(1, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(5, motorControl.unknownCount);
// Send unhandled events.
motorControl.receive(nmr, Start());
motorControl.receive(nmr, Stop());
motorControl.receive(nmr, SetSpeed(100));
CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(true, motorControl.isLampOn);
CHECK_EQUAL(1, motorControl.setSpeedCount);
CHECK_EQUAL(100, motorControl.speed);
CHECK_EQUAL(1, motorControl.startCount);
CHECK_EQUAL(1, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(8, motorControl.unknownCount);
// Send Stopped event.
motorControl.receive(nmr, Stopped());
// Now in Locked state via Idle state.
CHECK_EQUAL(StateId::LOCKED, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::LOCKED, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(false, motorControl.isLampOn);
CHECK_EQUAL(1, motorControl.setSpeedCount);
CHECK_EQUAL(100, motorControl.speed);
CHECK_EQUAL(1, motorControl.startCount);
CHECK_EQUAL(1, motorControl.stopCount);
CHECK_EQUAL(1, motorControl.stoppedCount);
CHECK_EQUAL(8, motorControl.unknownCount);
}
//*************************************************************************
TEST(test_fsm_emergency_stop)
{
etl::null_message_router nmr;
motorControl.reset();
motorControl.ClearStatistics();
CHECK(!motorControl.is_started());
// Start the FSM.
motorControl.start();
CHECK(motorControl.is_started());
// Now in Idle state.
// Send Start event.
motorControl.receive(nmr, Start());
// Now in Running state.
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(true, motorControl.isLampOn);
CHECK_EQUAL(0, motorControl.setSpeedCount);
CHECK_EQUAL(0, motorControl.speed);
CHECK_EQUAL(1, motorControl.startCount);
CHECK_EQUAL(0, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(0, motorControl.unknownCount);
// Send emergency Stop event.
motorControl.receive(nmr, Stop(true));
// Now in Locked state via Idle state.
CHECK_EQUAL(StateId::LOCKED, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::LOCKED, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(false, motorControl.isLampOn);
CHECK_EQUAL(0, motorControl.setSpeedCount);
CHECK_EQUAL(0, motorControl.speed);
CHECK_EQUAL(1, motorControl.startCount);
CHECK_EQUAL(1, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(0, motorControl.unknownCount);
}
//*************************************************************************
TEST(test_fsm_supported)
{
CHECK(motorControl.accepts(EventId::SET_SPEED));
CHECK(motorControl.accepts(EventId::START));
CHECK(motorControl.accepts(EventId::STOP));
CHECK(motorControl.accepts(EventId::STOPPED));
CHECK(motorControl.accepts(EventId::UNSUPPORTED));
CHECK(motorControl.accepts(SetSpeed(0)));
CHECK(motorControl.accepts(Start()));
CHECK(motorControl.accepts(Stop()));
CHECK(motorControl.accepts(Stopped()));
CHECK(motorControl.accepts(Unsupported()));
}
};
}

View File

@ -445,5 +445,31 @@ namespace
etl::destroy(p, p + SIZE, count);
CHECK_EQUAL(0U, count);
}
//*************************************************************************
TEST(test_create_copy)
{
struct Test : etl::create_copy<Test>
{
std::string text;
};
char buffer[sizeof(Test)];
Test test1;
test1.text = "12345678";
test1.create_copy_at(buffer);
test1.text = "87654321";
Test& test2 = *reinterpret_cast<Test*>(buffer);
CHECK_EQUAL(std::string("87654321"), test1.text);
CHECK_EQUAL(std::string("12345678"), test2.text);
int count = 0;
test1.create_copy_at(buffer, count);
CHECK_EQUAL(1, count);
}
};
}

729
test/test_message_bus.cpp Normal file
View File

@ -0,0 +1,729 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://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.
******************************************************************************/
#include "UnitTest++.h"
#include "ExtraCheckMacros.h"
#include "message_router.h"
#include "message_bus.h"
#include "queue.h"
#include "largest.h"
#include "packet.h"
//***************************************************************************
// The set of messages.
//***************************************************************************
namespace
{
enum
{
MESSAGE1,
MESSAGE2,
MESSAGE3,
MESSAGE4,
MESSAGE5
};
enum
{
ROUTER1 = 1,
ROUTER2 = 2,
ROUTER3 = 3,
ROUTER4 = 4,
ROUTER5 = 5
};
struct Message1 : public etl::message<MESSAGE1>
{
};
struct Message2 : public etl::message<MESSAGE2>
{
};
struct Message3 : public etl::message<MESSAGE3>
{
int value[10];
};
struct Message4 : public etl::message<MESSAGE4>
{
};
struct Message5 : public etl::message<MESSAGE5>
{
};
Message1 message1;
Message2 message2;
Message3 message3;
Message4 message4;
Message5 message5;
int call_order;
//***************************************************************************
// Router that handles messages 1, 2, 3, 4, 5.
//***************************************************************************
class RouterA : public etl::message_router<RouterA, Message1, Message2, Message3, Message4, Message5>
{
public:
RouterA(etl::message_router_id_t id)
: message_router(id),
message1_count(0),
message2_count(0),
message3_count(0),
message4_count(0),
message5_count(0),
message_unknown_count(0)
{
}
void on_receive(etl::imessage_router& sender, const Message1& msg)
{
++message1_count;
etl::send_message(sender, message5);
order = call_order++;
}
void on_receive(etl::imessage_router& sender, const Message2& msg)
{
++message2_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message3& msg)
{
++message3_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message4& msg)
{
++message4_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message5& msg)
{
++message5_count;
}
void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg)
{
++message_unknown_count;
}
int message1_count;
int message2_count;
int message3_count;
int message4_count;
int message5_count;
int message_unknown_count;
int order;
};
//***************************************************************************
// Router that handles messages 1, 2, 4 and 5 and returns nothing.
//***************************************************************************
class RouterB : public etl::message_router<RouterB, Message1, Message2, Message4, Message5>
{
public:
RouterB(etl::message_router_id_t id)
: message_router(id),
message1_count(0),
message2_count(0),
message4_count(0),
message5_count(0),
message_unknown_count(0)
{
}
void on_receive(etl::imessage_router& sender, const Message1& msg)
{
++message1_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message2& msg)
{
++message2_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message4& msg)
{
++message4_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message5& msg)
{
++message5_count;
}
void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg)
{
++message_unknown_count;
etl::send_message(sender, message5);
}
int message1_count;
int message2_count;
int message4_count;
int message5_count;
int message_unknown_count;
};
etl::imessage_router* p_router;
etl::imessage_bus* p_bus;
SUITE(test_message_router)
{
//=========================================================================
TEST(message_bus_subscribe_unsubscribe)
{
etl::message_bus<2> bus1;
RouterA router1(0);
RouterB router2(1);
RouterA router3(2);
CHECK_EQUAL(0U, bus1.size());
CHECK_NO_THROW(bus1.subscribe(router1));
CHECK_EQUAL(1U, bus1.size());
CHECK_NO_THROW(bus1.subscribe(router2));
CHECK_EQUAL(2U, bus1.size());
CHECK_THROW(bus1.subscribe(router3), etl::message_bus_too_many_subscribers);
CHECK_EQUAL(2U, bus1.size());
bus1.unsubscribe(router1);
CHECK_EQUAL(1U, bus1.size());
// Erase router not in list.
bus1.unsubscribe(router3);
CHECK_EQUAL(1U, bus1.size());
// Erase using id.
bus1.unsubscribe(router2.get_message_router_id());
CHECK_EQUAL(0U, bus1.size());
// Erase router from empty list.
bus1.unsubscribe(router2);
CHECK_EQUAL(0U, bus1.size());
}
//=========================================================================
TEST(message_bus_subscribe_unsubscribe_sub_bus)
{
etl::message_bus<4> bus1;
etl::message_bus<2> bus2;
etl::message_bus<3> bus3;
RouterA router1(ROUTER1);
RouterA router2(ROUTER2);
RouterA router3(ROUTER3);
RouterA router4(ROUTER4);
bus1.subscribe(router1);
bus1.subscribe(router2);
bus1.subscribe(bus2);
bus1.subscribe(bus3);
bus2.subscribe(router3);
bus3.subscribe(router4);
CHECK_EQUAL(4U, bus1.size());
bus1.unsubscribe(etl::imessage_bus::MESSAGE_BUS);
CHECK_EQUAL(2U, bus1.size());
bus1.unsubscribe(etl::imessage_bus::ALL_MESSAGE_ROUTERS);
CHECK_EQUAL(0U, bus1.size());
}
//=========================================================================
TEST(message_bus_broadcast)
{
etl::message_bus<2> bus1;
RouterA router1(ROUTER1);
RouterB router2(ROUTER2);
RouterA sender(ROUTER3);
bus1.subscribe(router1);
bus1.subscribe(router2);
bus1.receive(sender, message1);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(0, router1.message2_count);
CHECK_EQUAL(0, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(1, router2.message1_count);
CHECK_EQUAL(0, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(2, sender.message5_count);
bus1.receive(sender, message2);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(1, router1.message2_count);
CHECK_EQUAL(0, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(1, router2.message1_count);
CHECK_EQUAL(1, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(4, sender.message5_count);
bus1.receive(sender, message3);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(1, router1.message2_count);
CHECK_EQUAL(1, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(1, router2.message1_count);
CHECK_EQUAL(1, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(5, sender.message5_count);
// Use global function.
etl::send_message(sender, bus1, message4);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(1, router1.message2_count);
CHECK_EQUAL(1, router1.message3_count);
CHECK_EQUAL(1, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(1, router2.message1_count);
CHECK_EQUAL(1, router2.message2_count);
CHECK_EQUAL(1, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(7, sender.message5_count);
}
//=========================================================================
TEST(message_bus_broadcast_as_router)
{
etl::message_bus<2> bus1;
RouterA router1(ROUTER1);
RouterB router2(ROUTER2);
RouterA sender(ROUTER3);
bus1.subscribe(router1);
bus1.subscribe(router2);
// Reference to router sub-type
etl::imessage_router& irouter = bus1;
irouter.receive(sender, message1);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(0, router1.message2_count);
CHECK_EQUAL(0, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(1, router2.message1_count);
CHECK_EQUAL(0, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(2, sender.message5_count);
irouter.receive(sender, message2);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(1, router1.message2_count);
CHECK_EQUAL(0, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(1, router2.message1_count);
CHECK_EQUAL(1, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(4, sender.message5_count);
irouter.receive(sender, message3);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(1, router1.message2_count);
CHECK_EQUAL(1, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(1, router2.message1_count);
CHECK_EQUAL(1, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(5, sender.message5_count);
// Use global function.
etl::send_message(sender, irouter, message4);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(1, router1.message2_count);
CHECK_EQUAL(1, router1.message3_count);
CHECK_EQUAL(1, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(1, router2.message1_count);
CHECK_EQUAL(1, router2.message2_count);
CHECK_EQUAL(1, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(7, sender.message5_count);
}
//=========================================================================
TEST(message_bus_addressed)
{
etl::message_bus<2> bus1;
RouterA router1(ROUTER1);
RouterB router2(ROUTER2);
RouterA sender(ROUTER3);
bus1.subscribe(router1);
bus1.subscribe(router2);
bus1.receive(sender, ROUTER1, message1);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(0, router1.message2_count);
CHECK_EQUAL(0, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(0, router2.message1_count);
CHECK_EQUAL(0, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(1, sender.message5_count);
bus1.receive(sender, ROUTER2, message2);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(0, router1.message2_count);
CHECK_EQUAL(0, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(0, router2.message1_count);
CHECK_EQUAL(1, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(2, sender.message5_count);
bus1.receive(sender, ROUTER1, message3);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(0, router1.message2_count);
CHECK_EQUAL(1, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(0, router2.message1_count);
CHECK_EQUAL(1, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(3, sender.message5_count);
// Use global function.
etl::send_message(sender, bus1, ROUTER2, message4);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(0, router1.message2_count);
CHECK_EQUAL(1, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(0, router2.message1_count);
CHECK_EQUAL(1, router2.message2_count);
CHECK_EQUAL(1, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(4, sender.message5_count);
// Send to a router not subscribed to the bus.
bus1.receive(sender, ROUTER5, message1);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(0, router1.message2_count);
CHECK_EQUAL(1, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(0, router2.message1_count);
CHECK_EQUAL(1, router2.message2_count);
CHECK_EQUAL(1, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(4, sender.message5_count);
}
//=========================================================================
TEST(message_bus_addressed_duplicate_router_id)
{
etl::message_bus<3> bus1;
RouterA router1(ROUTER1);
RouterB router2(ROUTER1);
RouterB router3(ROUTER2);
RouterA sender(ROUTER3);
bus1.subscribe(router1);
bus1.subscribe(router2);
bus1.subscribe(router3);
bus1.receive(sender, ROUTER1, message1);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(0, router1.message2_count);
CHECK_EQUAL(0, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(1, router2.message1_count);
CHECK_EQUAL(0, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(0, router3.message1_count);
CHECK_EQUAL(0, router3.message2_count);
CHECK_EQUAL(0, router3.message4_count);
CHECK_EQUAL(0, router3.message5_count);
CHECK_EQUAL(0, router3.message_unknown_count);
CHECK_EQUAL(2, sender.message5_count);
}
//=========================================================================
TEST(message_bus_broadcast_addressed_sub_bus)
{
etl::message_bus<3> bus1;
etl::message_bus<2> bus2;
RouterA router1(ROUTER1);
RouterA router2(ROUTER2);
RouterA router3(ROUTER3);
RouterA router4(ROUTER4);
RouterA sender(ROUTER5);
bus1.subscribe(router1);
bus1.subscribe(router2);
bus1.subscribe(bus2);
bus2.subscribe(router3);
bus2.subscribe(router4);
// Broadcast to bus1
bus1.receive(sender, message1);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(0, router1.message2_count);
CHECK_EQUAL(0, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(1, router2.message1_count);
CHECK_EQUAL(0, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(1, router3.message1_count);
CHECK_EQUAL(0, router3.message2_count);
CHECK_EQUAL(0, router3.message4_count);
CHECK_EQUAL(0, router3.message5_count);
CHECK_EQUAL(0, router3.message_unknown_count);
CHECK_EQUAL(1, router4.message1_count);
CHECK_EQUAL(0, router4.message2_count);
CHECK_EQUAL(0, router4.message4_count);
CHECK_EQUAL(0, router4.message5_count);
CHECK_EQUAL(0, router4.message_unknown_count);
CHECK_EQUAL(4, sender.message5_count);
// Addressed to ROUTER2
bus1.receive(sender, ROUTER2, message1);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(0, router1.message2_count);
CHECK_EQUAL(0, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(2, router2.message1_count);
CHECK_EQUAL(0, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(1, router3.message1_count);
CHECK_EQUAL(0, router3.message2_count);
CHECK_EQUAL(0, router3.message4_count);
CHECK_EQUAL(0, router3.message5_count);
CHECK_EQUAL(0, router3.message_unknown_count);
CHECK_EQUAL(1, router4.message1_count);
CHECK_EQUAL(0, router4.message2_count);
CHECK_EQUAL(0, router4.message4_count);
CHECK_EQUAL(0, router4.message5_count);
CHECK_EQUAL(0, router4.message_unknown_count);
CHECK_EQUAL(5, sender.message5_count);
// Addressed to ROUTER3 via bus2
bus1.receive(sender, ROUTER3, message1);
CHECK_EQUAL(1, router1.message1_count);
CHECK_EQUAL(0, router1.message2_count);
CHECK_EQUAL(0, router1.message3_count);
CHECK_EQUAL(0, router1.message4_count);
CHECK_EQUAL(0, router1.message5_count);
CHECK_EQUAL(0, router1.message_unknown_count);
CHECK_EQUAL(2, router2.message1_count);
CHECK_EQUAL(0, router2.message2_count);
CHECK_EQUAL(0, router2.message4_count);
CHECK_EQUAL(0, router2.message5_count);
CHECK_EQUAL(0, router2.message_unknown_count);
CHECK_EQUAL(2, router3.message1_count);
CHECK_EQUAL(0, router3.message2_count);
CHECK_EQUAL(0, router3.message4_count);
CHECK_EQUAL(0, router3.message5_count);
CHECK_EQUAL(0, router3.message_unknown_count);
CHECK_EQUAL(1, router4.message1_count);
CHECK_EQUAL(0, router4.message2_count);
CHECK_EQUAL(0, router4.message4_count);
CHECK_EQUAL(0, router4.message5_count);
CHECK_EQUAL(0, router4.message_unknown_count);
CHECK_EQUAL(6, sender.message5_count);
}
//=========================================================================
TEST(message_bus_broadcast_order)
{
etl::message_bus<4> bus1;
etl::message_bus<2> bus2;
etl::message_bus<2> bus3;
RouterA router1(ROUTER1);
RouterA router2(ROUTER2);
RouterA router3(ROUTER3);
RouterA router4a(ROUTER4);
RouterA router4b(ROUTER4);
RouterA sender(ROUTER5);
bus1.subscribe(router1);
bus1.subscribe(bus3);
bus1.subscribe(bus2);
bus1.subscribe(router2);
bus2.subscribe(router3);
bus3.subscribe(router4b);
bus3.subscribe(router4a);
call_order = 0;
bus1.receive(sender, message1);
CHECK_EQUAL(0, router1.order);
CHECK_EQUAL(1, router2.order);
CHECK_EQUAL(2, router4b.order);
CHECK_EQUAL(3, router4a.order);
CHECK_EQUAL(4, router3.order);
}
};
}

View File

@ -0,0 +1,421 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://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.
******************************************************************************/
#include "UnitTest++.h"
#include "ExtraCheckMacros.h"
#include "message_router.h"
#include "queue.h"
#include "largest.h"
#include "packet.h"
//***************************************************************************
// The set of messages.
//***************************************************************************
namespace
{
enum
{
MESSAGE1,
MESSAGE2,
MESSAGE3,
MESSAGE4,
MESSAGE5
};
enum
{
ROUTER1,
ROUTER2
};
struct Message1 : public etl::message<MESSAGE1>
{
};
struct Message2 : public etl::message<MESSAGE2>
{
};
struct Message3 : public etl::message<MESSAGE3>
{
int value[10];
};
struct Message4 : public etl::message<MESSAGE4>
{
};
struct Message5 : public etl::message<MESSAGE5>
{
};
Message1 message1;
Message2 message2;
Message3 message3;
Message4 message4;
Message5 message5;
//***************************************************************************
// Router that handles messages 1, 2, 3, 4 and 5 and returns nothing.
//***************************************************************************
class Router1 : public etl::message_router<Router1, Message1, Message2, Message3, Message4, Message5>
{
public:
Router1()
: message_router(ROUTER1),
message1_count(0),
message2_count(0),
message3_count(0),
message4_count(0),
message_unknown_count(0),
callback_count(0)
{
}
void on_receive(etl::imessage_router& sender, const Message1& msg)
{
++message1_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message2& msg)
{
++message2_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message3& msg)
{
++message3_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message4& msg)
{
++message4_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message5& msg)
{
++callback_count;
}
void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg)
{
++message_unknown_count;
}
int message1_count;
int message2_count;
int message3_count;
int message4_count;
int message_unknown_count;
int callback_count;
};
//***************************************************************************
// Router that handles messages 1, 2, 4 and 5 and returns nothing.
//***************************************************************************
class Router2 : public etl::message_router<Router2, Message1, Message2, Message4, Message5>
{
public:
Router2()
: message_router(ROUTER2),
message1_count(0),
message2_count(0),
message4_count(0),
message_unknown_count(0),
callback_count(0)
{
}
void on_receive(etl::imessage_router& sender, const Message1& msg)
{
++message1_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message2& msg)
{
++message2_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message4& msg)
{
++message4_count;
etl::send_message(sender, message5);
}
void on_receive(etl::imessage_router& sender, const Message5& msg)
{
++callback_count;
}
void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg)
{
++message_unknown_count;
etl::send_message(sender, message5);
}
int message1_count;
int message2_count;
int message4_count;
int message_unknown_count;
int callback_count;
};
etl::imessage_router* p_router;
SUITE(test_message_router)
{
//=========================================================================
TEST(message_router)
{
Router1 r1;
Router2 r2;
p_router = &r1;
p_router->receive(r2, message1);
CHECK_EQUAL(1, r1.message1_count);
CHECK_EQUAL(0, r1.message2_count);
CHECK_EQUAL(0, r1.message3_count);
CHECK_EQUAL(0, r1.message4_count);
CHECK_EQUAL(0, r1.message_unknown_count);
CHECK_EQUAL(1, r2.callback_count);
p_router->receive(r2, message2);
CHECK_EQUAL(1, r1.message1_count);
CHECK_EQUAL(1, r1.message2_count);
CHECK_EQUAL(0, r1.message3_count);
CHECK_EQUAL(0, r1.message4_count);
CHECK_EQUAL(0, r1.message_unknown_count);
CHECK_EQUAL(2, r2.callback_count);
p_router->receive(r2, message3);
CHECK_EQUAL(1, r1.message1_count);
CHECK_EQUAL(1, r1.message2_count);
CHECK_EQUAL(1, r1.message3_count);
CHECK_EQUAL(0, r1.message4_count);
CHECK_EQUAL(0, r1.message_unknown_count);
CHECK_EQUAL(3, r2.callback_count);
p_router->receive(r2, message4);
CHECK_EQUAL(1, r1.message1_count);
CHECK_EQUAL(1, r1.message2_count);
CHECK_EQUAL(1, r1.message3_count);
CHECK_EQUAL(1, r1.message4_count);
CHECK_EQUAL(0, r1.message_unknown_count);
CHECK_EQUAL(4, r2.callback_count);
p_router = &r2;
p_router->receive(r1, message1);
CHECK_EQUAL(1, r2.message1_count);
CHECK_EQUAL(0, r2.message2_count);
CHECK_EQUAL(0, r2.message4_count);
CHECK_EQUAL(0, r2.message_unknown_count);
CHECK_EQUAL(1, r1.callback_count);
p_router->receive(r1, message2);
CHECK_EQUAL(1, r2.message1_count);
CHECK_EQUAL(1, r2.message2_count);
CHECK_EQUAL(0, r2.message4_count);
CHECK_EQUAL(0, r2.message_unknown_count);
CHECK_EQUAL(2, r1.callback_count);
p_router->receive(r1, message3);
CHECK_EQUAL(1, r2.message1_count);
CHECK_EQUAL(1, r2.message2_count);
CHECK_EQUAL(0, r2.message4_count);
CHECK_EQUAL(1, r2.message_unknown_count);
CHECK_EQUAL(3, r1.callback_count);
p_router->receive(r1, message4);
CHECK_EQUAL(1, r2.message1_count);
CHECK_EQUAL(1, r2.message2_count);
CHECK_EQUAL(1, r2.message4_count);
CHECK_EQUAL(1, r2.message_unknown_count);
CHECK_EQUAL(4, r1.callback_count);
}
//=========================================================================
TEST(message_null_router)
{
Router2 router;
etl::null_message_router null_router;
// Send from the null router.
etl::send_message(router, message1);
CHECK_EQUAL(1, router.message1_count);
CHECK_EQUAL(0, router.message2_count);
CHECK_EQUAL(0, router.message4_count);
CHECK_EQUAL(0, router.message_unknown_count);
etl::send_message(router, message2);
CHECK_EQUAL(1, router.message1_count);
CHECK_EQUAL(1, router.message2_count);
CHECK_EQUAL(0, router.message4_count);
CHECK_EQUAL(0, router.message_unknown_count);
etl::send_message(router, message3);
CHECK_EQUAL(1, router.message1_count);
CHECK_EQUAL(1, router.message2_count);
CHECK_EQUAL(0, router.message4_count);
CHECK_EQUAL(1, router.message_unknown_count);
etl::send_message(router, message4);
CHECK_EQUAL(1, router.message1_count);
CHECK_EQUAL(1, router.message2_count);
CHECK_EQUAL(1, router.message4_count);
CHECK_EQUAL(1, router.message_unknown_count);
// Send to the null router.
etl::send_message(null_router, message1);
CHECK_EQUAL(1, router.message1_count);
CHECK_EQUAL(1, router.message2_count);
CHECK_EQUAL(1, router.message4_count);
CHECK_EQUAL(1, router.message_unknown_count);
etl::send_message(null_router, message2);
CHECK_EQUAL(1, router.message1_count);
CHECK_EQUAL(1, router.message2_count);
CHECK_EQUAL(1, router.message4_count);
CHECK_EQUAL(1, router.message_unknown_count);
etl::send_message(null_router, message3);
CHECK_EQUAL(1, router.message1_count);
CHECK_EQUAL(1, router.message2_count);
CHECK_EQUAL(1, router.message4_count);
CHECK_EQUAL(1, router.message_unknown_count);
etl::send_message(null_router, message4);
CHECK_EQUAL(1, router.message1_count);
CHECK_EQUAL(1, router.message2_count);
CHECK_EQUAL(1, router.message4_count);
CHECK_EQUAL(1, router.message_unknown_count);
}
//=========================================================================
TEST(message_router_accepts)
{
Router2 r2;
CHECK(r2.accepts(message1));
CHECK(r2.accepts(message1.get_message_id()));
CHECK(r2.accepts(message2));
CHECK(r2.accepts(message2.get_message_id()));
CHECK(!r2.accepts(message3));
CHECK(!r2.accepts(message3.get_message_id()));
CHECK(r2.accepts(message4));
CHECK(r2.accepts(message4.get_message_id()));
CHECK(r2.accepts(message5));
CHECK(r2.accepts(message5.get_message_id()));
}
//=========================================================================
TEST(message_router_queue)
{
Router1 r1;
Router2 r2;
typedef Router2::message_packet Packet;
typedef etl::queue<Packet, 4> Queue;
Queue queue;
etl::imessage* im;
// Queue some messages in the message packet queue.
im = &message1;
queue.emplace(*im);
im = &message2;
queue.emplace(*im);
// The router2 queue doesn't accept Message3 types.
im = &message3;
CHECK_THROW(queue.emplace(*im), etl::unhandled_message_exception);
im = &message4;
queue.emplace(*im);
im = &message4;
queue.emplace(*im);
etl::imessage& imr1 = queue.front().get();
r2.receive(r1, imr1);
CHECK_EQUAL(1, r2.message1_count);
CHECK_EQUAL(0, r2.message2_count);
CHECK_EQUAL(0, r2.message4_count);
CHECK_EQUAL(0, r2.message_unknown_count);
CHECK_EQUAL(1, r1.callback_count);
queue.pop();
etl::imessage& imr2 = queue.front().get();
r2.receive(r1, imr2);
CHECK_EQUAL(1, r2.message1_count);
CHECK_EQUAL(1, r2.message2_count);
CHECK_EQUAL(0, r2.message4_count);
CHECK_EQUAL(0, r2.message_unknown_count);
CHECK_EQUAL(2, r1.callback_count);
queue.pop();
const etl::imessage& imr3 = queue.front().get();
r2.receive(r1, imr3);
CHECK_EQUAL(1, r2.message1_count);
CHECK_EQUAL(1, r2.message2_count);
CHECK_EQUAL(1, r2.message4_count);
CHECK_EQUAL(0, r2.message_unknown_count);
CHECK_EQUAL(3, r1.callback_count);
queue.pop();
const Queue& crqueue = queue;
const etl::imessage& imr4 = crqueue.front().get();
r2.receive(r1, imr4);
CHECK_EQUAL(1, r2.message1_count);
CHECK_EQUAL(1, r2.message2_count);
CHECK_EQUAL(2, r2.message4_count);
CHECK_EQUAL(0, r2.message_unknown_count);
CHECK_EQUAL(4, r1.callback_count);
queue.pop();
}
};
}

183
test/test_packet.cpp Normal file
View File

@ -0,0 +1,183 @@
/******************************************************************************
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.
******************************************************************************/
#include "UnitTest++.h"
#include "ExtraCheckMacros.h"
#include "packet.h"
#include "largest.h"
#include "queue.h"
#include "pool.h"
namespace
{
// Test classes for polymorphic tests.
struct base
{
base(int v_)
: v(v_)
{
}
virtual ~base()
{
}
virtual int value() const = 0;
protected:
const int v;
};
struct not_base
{
not_base()
{
}
};
struct derived_1 : public base
{
derived_1(int value)
: base(value)
{
}
int value() const
{
return v;
}
static int count;
};
struct derived_2 : public base
{
derived_2(int value)
: base(value)
{
}
int value() const
{
return v;
}
};
typedef etl::largest<derived_1, derived_2> types;
//
//// Test packet types.
typedef etl::packet<base, types::size, types::alignment> packet1_t;
typedef etl::packet<not_base, types::size, types::alignment> packet2_t;
SUITE(test_packet)
{
//*************************************************************************
TEST(test_constructor_value)
{
derived_1 d1(1);
derived_2 d2(2);
packet1_t p11(d1);
packet1_t p12(d2);
base* b;
b = &p11.get();
CHECK_EQUAL(d1.value(), b->value());
b = &p12.get();
CHECK_EQUAL(d2.value(), b->value());
// These lines should fail to compile.
//p11 = p12;
//packet2_t p21(d1);
//packet2_t p22(d1);
}
//*************************************************************************
TEST(test_assignment)
{
derived_1 d1(1);
derived_2 d2(2);
packet1_t p(d1);
base* b;
b = &p.get();
CHECK_EQUAL(d1.value(), b->value());
p = d2;
CHECK_EQUAL(d2.value(), b->value());
}
//*************************************************************************
TEST(test_packet_queueing)
{
derived_1 da(1);
derived_2 db(2);
derived_1 dc(3);
derived_2 dd(4);
etl::queue<packet1_t, 4> queue;
queue.emplace(da);
queue.emplace(db);
queue.emplace(dc);
queue.emplace(dd);
CHECK_EQUAL(da.value(), queue.front().get().value());
queue.pop();
CHECK_EQUAL(db.value(), queue.front().get().value());
queue.pop();
CHECK_EQUAL(dc.value(), queue.front().get().value());
queue.pop();
CHECK_EQUAL(dd.value(), queue.front().get().value());
queue.pop();
}
//*************************************************************************
TEST(test_packet_get)
{
derived_1 da(1);
// Non-const.
packet1_t p1(da);
base& rb = p1.get();
CHECK_EQUAL(da.value(), rb.value());
// Const.
const packet1_t p2(da);
const base& crb = p2.get();
CHECK_EQUAL(da.value(), crb.value());
}
}
}

View File

@ -0,0 +1,263 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://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.
******************************************************************************/
#include "UnitTest++.h"
#include <stdint.h>
#include <string>
#include <vector>
#include "task.h"
#include "scheduler.h"
#include "container.h"
typedef std::vector<std::string> WorkList_t;
//*****************************************************************************
struct Common
{
//*********************************************
Common()
: idle_callback(*this, &Common::IdleCallback),
watchdog_callback(*this, &Common::WatchdogCallback),
watchdog_called(false)
{
}
//*********************************************
void Clear()
{
workList.clear();
}
//*********************************************
void IdleCallback()
{
pScheduler->exit_scheduler();
}
//*********************************************
void WatchdogCallback()
{
watchdog_called = true;
}
WorkList_t workList;
etl::function<Common, void> idle_callback;
etl::function<Common, void> watchdog_callback;
etl::ischeduler* pScheduler;
bool watchdog_called;
};
//*****************************************************************************
class Task : public etl::task
{
public:
//*********************************************
Task(etl::task_priority_t priority, WorkList_t& work, Common& common)
: task(priority),
work(work),
common(common),
workIndex(0),
addAtIndex(0),
workToAdd(""),
pTaskToAddTo(nullptr)
{
workCopy = work;
}
//*********************************************
void Reset()
{
workIndex = 0;
addAtIndex = 0;
workToAdd = "";
pTaskToAddTo = nullptr;
work = workCopy;
}
//*********************************************
void WorkToAdd(int addAtIndex_, const std::string& workToAdd_, Task& taskToAddTo_)
{
addAtIndex = addAtIndex_;
workToAdd = workToAdd_;
pTaskToAddTo = &taskToAddTo_;
}
//*********************************************
uint32_t task_request_work() const
{
return uint_least8_t(work.size() - workIndex);
}
//*********************************************
void task_process_work()
{
common.workList.push_back(work[workIndex]);
++workIndex;
if (workIndex == addAtIndex)
{
pTaskToAddTo->work.push_back(workToAdd);
}
}
private:
WorkList_t work;
WorkList_t workCopy;
Common &common;
uint_least8_t workIndex;
int addAtIndex;
std::string workToAdd;
Task* pTaskToAddTo;
};
Common common;
WorkList_t work1 = { "T1W1", "T1W2", "T1W3" };
WorkList_t work2 = { "T2W1", "T2W2", "T2W3", "T2W4" };
WorkList_t work3 = { "T3W1", "T3W2" };
Task task1(1, work1, common);
Task task2(2, work2, common);
Task task3(3, work3, common);
etl::task* taskList[] = { &task1, &task2, &task3 };
typedef etl::scheduler<etl::scheduler_policy_sequencial_single, sizeof(etl::array_size(taskList))> SchedulerSequencialSingle;
typedef etl::scheduler<etl::scheduler_policy_sequencial_multiple, sizeof(etl::array_size(taskList))> SchedulerSequencialMultiple;
typedef etl::scheduler<etl::scheduler_policy_highest_priority, sizeof(etl::array_size(taskList))> SchedulerHighestPriority;
typedef etl::scheduler<etl::scheduler_policy_most_work, sizeof(etl::array_size(taskList))> SchedulerMostWork;
namespace
{
SUITE(test_task_scheduler)
{
//=========================================================================
TEST(test_scheduler_sequencial_single)
{
SchedulerSequencialSingle s;
task1.Reset();
task2.Reset();
task3.Reset();
task2.WorkToAdd(2, "T3W3", task3);
common.Clear();
common.pScheduler = &s;
s.set_idle_callback(common.idle_callback);
s.set_watchdog_callback(common.watchdog_callback);
s.add_task_list(taskList, etl::size(taskList));
s.start(); // If 'start' returns then the idle callback was sucessfully called.
WorkList_t expected = { "T3W1", "T2W1", "T1W1", "T3W2", "T2W2", "T1W2", "T3W3", "T2W3", "T1W3", "T2W4" };
CHECK(expected == common.workList);
CHECK(common.watchdog_called);
}
//=========================================================================
TEST(test_scheduler_sequencial_multiple)
{
SchedulerSequencialMultiple s;
task1.Reset();
task2.Reset();
task3.Reset();
task2.WorkToAdd(2, "T3W3", task3);
common.Clear();
common.pScheduler = &s;
s.set_idle_callback(common.idle_callback);
s.set_watchdog_callback(common.watchdog_callback);
s.add_task_list(taskList, etl::size(taskList));
s.start(); // If 'start' returns then the idle callback was sucessfully called.
WorkList_t expected = { "T3W1", "T3W2", "T2W1", "T2W2", "T2W3", "T2W4", "T1W1", "T1W2", "T1W3", "T3W3" };
CHECK(expected == common.workList);
CHECK(common.watchdog_called);
}
//=========================================================================
TEST(test_scheduler_highest_priority)
{
SchedulerHighestPriority s;
task1.Reset();
task2.Reset();
task3.Reset();
task2.WorkToAdd(2, "T3W3", task3);
common.Clear();
common.pScheduler = &s;
s.set_idle_callback(common.idle_callback);
s.set_watchdog_callback(common.watchdog_callback);
s.add_task_list(taskList, etl::size(taskList));
s.start(); // If 'start' returns then the idle callback was sucessfully called.
WorkList_t expected = { "T3W1", "T3W2", "T2W1", "T2W2", "T3W3", "T2W3", "T2W4", "T1W1", "T1W2", "T1W3" };
CHECK(expected == common.workList);
CHECK(common.watchdog_called);
}
//=========================================================================
TEST(test_scheduler_most_work)
{
SchedulerMostWork s;
task1.Reset();
task2.Reset();
task3.Reset();
task2.WorkToAdd(3, "T3W3", task3);
common.Clear();
common.pScheduler = &s;
s.set_idle_callback(common.idle_callback);
s.set_watchdog_callback(common.watchdog_callback);
s.add_task_list(taskList, etl::size(taskList));
s.start(); // If 'start' returns then the idle callback was sucessfully called.
WorkList_t expected = { "T2W1", "T2W2", "T1W1", "T3W1", "T2W3", "T3W2", "T1W2", "T3W3", "T2W4", "T1W3" };
CHECK(expected == common.workList);
CHECK(common.watchdog_called);
}
};
}

View File

@ -41,14 +41,20 @@ namespace std
#include "type_traits.h"
#include <type_traits>
// A class to test non-fundamental types.
struct Test
{
int a;
};
namespace
{
// A class to test non-fundamental types.
struct Test
{
int a;
};
// A class to test etl::is_one_of
template <const int I>
struct Type
{
};
SUITE(test_type_traits)
{
//*************************************************************************
@ -525,5 +531,55 @@ namespace
CHECK(std::alignment_of<double>::value == etl::alignment_of<double>::value);
CHECK(std::alignment_of<Test>::value == etl::alignment_of<Test>::value);
}
//*************************************************************************
TEST(test_is_one_of)
{
typedef Type<0> T0;
typedef Type<1> T1;
typedef Type<2> T2;
typedef Type<3> T3;
typedef Type<4> T4;
CHECK(bool(etl::is_one_of<char, char>::value));
CHECK(!(etl::is_one_of<char, T0>::value));
CHECK(bool(etl::is_one_of<char, T0, char>::value));
CHECK(!(etl::is_one_of<char, T0, T1>::value));
CHECK(bool(etl::is_one_of<char, T0, T1, char>::value));
CHECK(!(etl::is_one_of<char, T0, T1, T2>::value));
CHECK(bool(etl::is_one_of<char, T0, T1, T2, char>::value));
CHECK(!(etl::is_one_of<char, T0, T1, T2, T3>::value));
CHECK(bool(etl::is_one_of<char, T0, T1, T2, char>::value));
CHECK(!(etl::is_one_of<char, T0, T1, T2, T3>::value));
CHECK(bool(etl::is_one_of<char, char, T0, T1, T2, T3>::value));
CHECK(bool(etl::is_one_of<char, T0, char, T1, T2, T3>::value));
CHECK(bool(etl::is_one_of<char, T0, T1, char, T2, T3>::value));
CHECK(bool(etl::is_one_of<char, T0, T1, T2, char, T3>::value));
CHECK(bool(etl::is_one_of<char, T0, T1, T2, T3, char>::value));
CHECK(!(etl::is_one_of<char, T0, T1, T2, T3, T4>::value));
}
//*************************************************************************
TEST(test_is_base_of)
{
struct A { };
struct B : public A { };
struct C { };
CHECK((std::is_base_of<A, A>::value) == (etl::is_base_of<A, A>::value));
CHECK((std::is_base_of<A, B>::value) == (etl::is_base_of<A, B>::value));
CHECK((std::is_base_of<A, C>::value) == (etl::is_base_of<A, C>::value));
CHECK((std::is_base_of<B, A>::value) == (etl::is_base_of<B, A>::value));
CHECK((std::is_base_of<B, B>::value) == (etl::is_base_of<B, B>::value));
CHECK((std::is_base_of<B, C>::value) == (etl::is_base_of<B, C>::value));
CHECK((std::is_base_of<C, A>::value) == (etl::is_base_of<C, A>::value));
CHECK((std::is_base_of<C, B>::value) == (etl::is_base_of<C, B>::value));
CHECK((std::is_base_of<C, C>::value) == (etl::is_base_of<C, C>::value));
}
};
}

224
test/test_user_type.cpp Normal file
View File

@ -0,0 +1,224 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://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.
******************************************************************************/
#include "UnitTest++.h"
#include <string>
#include "user_type.h"
ETL_DECLARE_USER_TYPE(CompassDirection, int)
ETL_USER_TYPE(North, 0)
ETL_USER_TYPE(South, 180)
ETL_USER_TYPE(East, 90)
ETL_USER_TYPE(West, 270)
ETL_END_USER_TYPE(CompassDirection)
namespace
{
SUITE(test_user_type)
{
//*************************************************************************
TEST(Values)
{
CHECK_EQUAL(0, CompassDirection::North);
CHECK_EQUAL(180, CompassDirection::South);
CHECK_EQUAL(90, CompassDirection::East);
CHECK_EQUAL(270, CompassDirection::West);
}
//*************************************************************************
TEST(test_assignment)
{
CompassDirection value1 = CompassDirection::North;
CompassDirection value2 = CompassDirection(135);
value1 = value2;
CHECK_EQUAL(135, value1);
}
//*************************************************************************
TEST(test_equality)
{
CompassDirection value1 = CompassDirection::North;
CompassDirection value2 = CompassDirection::South;
CompassDirection value3 = CompassDirection::South;
CHECK(value1 != value2);
CHECK(value2 == value3);
}
//*************************************************************************
TEST(test_get_value)
{
CompassDirection actual = CompassDirection::North;
CompassDirection expected = CompassDirection::North;
CHECK_EQUAL(expected, actual.get());
}
//*************************************************************************
TEST(test_pre_increment)
{
CompassDirection value = CompassDirection::North;
CompassDirection expected = CompassDirection(CompassDirection::North + 1);
CHECK_EQUAL(expected, ++value);
}
//*************************************************************************
TEST(test_post_increment)
{
CompassDirection value = CompassDirection::North;
CompassDirection expected = CompassDirection(CompassDirection::North + 1);
CHECK_EQUAL(CompassDirection::North, value++);
CHECK_EQUAL(expected, value);
}
//*************************************************************************
TEST(test_pre_decrement)
{
CompassDirection value = CompassDirection::North;
CompassDirection expected = CompassDirection(CompassDirection::North - 1);
CHECK_EQUAL(expected, --value);
}
//*************************************************************************
TEST(test_post_decrement)
{
CompassDirection value = CompassDirection::North;
CompassDirection expected = CompassDirection(CompassDirection::North - 1);
CHECK_EQUAL(CompassDirection::North, value--);
CHECK_EQUAL(expected, value);
}
//*************************************************************************
TEST(test_add_equal)
{
CompassDirection value = CompassDirection::North;
value += 3;
CompassDirection expected = CompassDirection(CompassDirection::North + 3);
CHECK_EQUAL(expected, value);
}
//*************************************************************************
TEST(test_subtract_equal)
{
CompassDirection value = CompassDirection::North;
value -= 3;
CompassDirection expected = CompassDirection(CompassDirection::North - 3);
CHECK_EQUAL(expected, value);
}
//*************************************************************************
TEST(test_muliply_equal)
{
CompassDirection value = CompassDirection::North;
value *= 3;
CompassDirection expected = CompassDirection(CompassDirection::North * 3);
CHECK_EQUAL(expected, value);
}
//*************************************************************************
TEST(test_divide_equal)
{
CompassDirection value = CompassDirection::North;
value /= 3;
CompassDirection expected = CompassDirection(CompassDirection::North / 3);
CHECK_EQUAL(expected, value);
}
//*************************************************************************
TEST(test_mod_equal)
{
CompassDirection value = CompassDirection::North;
value %= 3;
CompassDirection expected = CompassDirection(CompassDirection::North % 3);
CHECK_EQUAL(expected, value);
}
//*************************************************************************
TEST(test_and_equal)
{
CompassDirection value = CompassDirection::North;
value &= 0xAAAAAAAA;
CompassDirection expected = CompassDirection(CompassDirection::North & 0xAAAAAAAA);
CHECK_EQUAL(expected, value);
}
//*************************************************************************
TEST(test_or_equal)
{
CompassDirection value = CompassDirection::North;
value |= 0xAAAAAAAA;
CompassDirection expected = CompassDirection(CompassDirection::North | 0xAAAAAAAA);
CHECK_EQUAL(expected, value);
}
//*************************************************************************
TEST(test_xor_equal)
{
CompassDirection value = CompassDirection::North;
value ^= 0xAAAAAAAA;
CompassDirection expected = CompassDirection(CompassDirection::North ^ 0xAAAAAAAA);
CHECK_EQUAL(expected, value);
}
//*************************************************************************
TEST(test_shift_left)
{
CompassDirection value = CompassDirection::North;
value <<= 2;
CompassDirection expected = CompassDirection(CompassDirection::North << 2);
CHECK_EQUAL(expected, value);
}
//*************************************************************************
TEST(test_shift_right)
{
CompassDirection value = CompassDirection::North;
value >>= 2;
CompassDirection expected = CompassDirection(CompassDirection::North >> 2);
CHECK_EQUAL(expected, value);
}
};
}

View File

@ -35,70 +35,70 @@ SOFTWARE.
#include <vector>
#include <algorithm>
// Test classes for polymorphic tests.
struct base
{
virtual ~base()
{
}
base()
: value(0)
{
}
virtual void set() = 0;
int value;
};
struct not_base
{
not_base()
: value(0)
{
}
virtual void set() = 0;
int value;
};
struct derived_1 : public base
{
void set()
{
value = 1;
}
};
struct derived_2 : public base
{
void set()
{
value = 2;
}
};
// Test variant types.
typedef etl::variant<char, int, std::string> test_variant_3a;
typedef etl::variant<int, short, double> test_variant_3b;
typedef etl::variant<int8_t> test_variant_1;
typedef etl::variant<int8_t, uint8_t> test_variant_2;
typedef etl::variant<int8_t, uint8_t, int16_t> test_variant_3;
typedef etl::variant<int8_t, uint8_t, int16_t, uint16_t> test_variant_4;
typedef etl::variant<int8_t, uint8_t, int16_t, uint16_t, int32_t> test_variant_5;
typedef etl::variant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t> test_variant_6;
typedef etl::variant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t> test_variant_7;
typedef etl::variant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t> test_variant_8;
typedef etl::variant<derived_1, derived_2> test_variant_polymorphic;
typedef etl::variant<char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long> test_variant_max_types;
// This line should compile with no errors.
test_variant_max_types variant_max;
namespace
{
// Test classes for polymorphic tests.
struct base
{
virtual ~base()
{
}
base()
: value(0)
{
}
virtual void set() = 0;
int value;
};
struct not_base
{
not_base()
: value(0)
{
}
virtual void set() = 0;
int value;
};
struct derived_1 : public base
{
void set()
{
value = 1;
}
};
struct derived_2 : public base
{
void set()
{
value = 2;
}
};
// Test variant types.
typedef etl::variant<char, int, std::string> test_variant_3a;
typedef etl::variant<int, short, double> test_variant_3b;
typedef etl::variant<int8_t> test_variant_1;
typedef etl::variant<int8_t, uint8_t> test_variant_2;
typedef etl::variant<int8_t, uint8_t, int16_t> test_variant_3;
typedef etl::variant<int8_t, uint8_t, int16_t, uint16_t> test_variant_4;
typedef etl::variant<int8_t, uint8_t, int16_t, uint16_t, int32_t> test_variant_5;
typedef etl::variant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t> test_variant_6;
typedef etl::variant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t> test_variant_7;
typedef etl::variant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t> test_variant_8;
typedef etl::variant<derived_1, derived_2> test_variant_polymorphic;
typedef etl::variant<char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long> test_variant_max_types;
// This line should compile with no errors.
test_variant_max_types variant_max;
SUITE(test_variant)
{
TEST(test_alignment)

View File

@ -128,6 +128,19 @@
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\src\fsm.h" />
<ClInclude Include="..\..\src\fsm_generator.h" />
<ClInclude Include="..\..\src\largest_generator.h" />
<ClInclude Include="..\..\src\message.h" />
<ClInclude Include="..\..\src\message_bus.h" />
<ClInclude Include="..\..\src\message_types.h" />
<ClInclude Include="..\..\src\message_router.h" />
<ClInclude Include="..\..\src\message_router_generator.h" />
<ClInclude Include="..\..\src\packet.h" />
<ClInclude Include="..\..\src\scheduler.h" />
<ClInclude Include="..\..\src\smallest_generator.h" />
<ClInclude Include="..\..\src\task.h" />
<ClInclude Include="..\..\src\type_traits_generator.h" />
<ClInclude Include="..\..\unittest-cpp\UnitTest++\AssertException.h" />
<ClInclude Include="..\..\unittest-cpp\UnitTest++\CheckMacros.h" />
<ClInclude Include="..\..\unittest-cpp\UnitTest++\Checks.h" />
@ -212,7 +225,6 @@
<ClInclude Include="..\..\src\flat_map.h" />
<ClInclude Include="..\..\src\map.h" />
<ClInclude Include="..\..\src\memory.h" />
<ClInclude Include="..\..\src\mru_cache.h" />
<ClInclude Include="..\..\src\multimap.h" />
<ClInclude Include="..\..\src\multiset.h" />
<ClInclude Include="..\..\src\multi_array.h" />
@ -236,7 +248,6 @@
<ClInclude Include="..\..\src\reference_flat_multimap.h" />
<ClInclude Include="..\..\src\reference_flat_multiset.h" />
<ClInclude Include="..\..\src\reference_flat_set.h" />
<ClInclude Include="..\..\src\rr_cache.h" />
<ClInclude Include="..\..\src\set.h" />
<ClInclude Include="..\..\src\smallest.h" />
<ClInclude Include="..\..\src\stack.h" />
@ -329,6 +340,7 @@
</ClCompile>
<ClCompile Include="..\test_fnv_1.cpp" />
<ClCompile Include="..\test_forward_list.cpp" />
<ClCompile Include="..\test_fsm.cpp" />
<ClCompile Include="..\test_function.cpp" />
<ClCompile Include="..\test_functional.cpp" />
<ClCompile Include="..\test_hash.cpp" />
@ -364,6 +376,8 @@
</ClCompile>
<ClCompile Include="..\test_maths.cpp" />
<ClCompile Include="..\test_memory.cpp" />
<ClCompile Include="..\test_message_bus.cpp" />
<ClCompile Include="..\test_message_router.cpp" />
<ClCompile Include="..\test_multimap.cpp" />
<ClCompile Include="..\test_multiset.cpp" />
<ClCompile Include="..\test_murmur3.cpp" />
@ -373,6 +387,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug No Unit Tests|Win32'">false</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\test_optional.cpp" />
<ClCompile Include="..\test_packet.cpp" />
<ClCompile Include="..\test_pearson.cpp" />
<ClCompile Include="..\test_pool.cpp" />
<ClCompile Include="..\test_priority_queue.cpp" />
@ -393,12 +408,14 @@
<ClCompile Include="..\test_string_u16.cpp" />
<ClCompile Include="..\test_string_u32.cpp" />
<ClCompile Include="..\test_string_wchar_t.cpp" />
<ClCompile Include="..\test_task_scheduler.cpp" />
<ClCompile Include="..\test_type_def.cpp" />
<ClCompile Include="..\test_type_traits.cpp" />
<ClCompile Include="..\test_unordered_map.cpp" />
<ClCompile Include="..\test_unordered_multimap.cpp" />
<ClCompile Include="..\test_unordered_multiset.cpp" />
<ClCompile Include="..\test_unordered_set.cpp" />
<ClCompile Include="..\test_user_type.cpp" />
<ClCompile Include="..\test_utility.cpp" />
<ClCompile Include="..\test_variant.cpp" />
<ClCompile Include="..\test_vector.cpp" />
@ -410,6 +427,9 @@
<ItemGroup>
<None Include="..\..\Doxyfile" />
<None Include="..\..\library.properties" />
<None Include="..\..\src\generate.bat" />
<None Include="..\..\src\generate_fsm.bat" />
<None Include="..\..\src\generate_message_router.bat" />
</ItemGroup>
<ItemGroup>
<Text Include="..\..\src\file_error_numbers.txt" />

View File

@ -38,7 +38,13 @@
<UniqueIdentifier>{7028012c-30c4-4993-b2d9-3b1521a610ae}</UniqueIdentifier>
</Filter>
<Filter Include="ETL\Frameworks">
<UniqueIdentifier>{5de50c3d-4679-4eb3-9b76-e43e1aad6a66}</UniqueIdentifier>
<UniqueIdentifier>{6be3bc76-e17c-4be0-8b0b-d1053e1a1761}</UniqueIdentifier>
</Filter>
<Filter Include="ETL\Frameworks\Generators">
<UniqueIdentifier>{c1264f38-22fa-4fcb-8cab-f254b1290eab}</UniqueIdentifier>
</Filter>
<Filter Include="ETL\Utilities\Generators">
<UniqueIdentifier>{39015d44-a7cb-47f0-a7dd-27714f852363}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
@ -261,12 +267,6 @@
<ClInclude Include="..\..\src\icache.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\src\mru_cache.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\src\rr_cache.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\src\intrusive_links.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
@ -438,6 +438,45 @@
<ClInclude Include="..\..\unittest-cpp\UnitTest++\XmlTestReporter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\fsm.h">
<Filter>ETL\Frameworks</Filter>
</ClInclude>
<ClInclude Include="..\..\src\message_router.h">
<Filter>ETL\Frameworks</Filter>
</ClInclude>
<ClInclude Include="..\..\src\packet.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\src\fsm_generator.h">
<Filter>ETL\Frameworks\Generators</Filter>
</ClInclude>
<ClInclude Include="..\..\src\message_router_generator.h">
<Filter>ETL\Frameworks\Generators</Filter>
</ClInclude>
<ClInclude Include="..\..\src\largest_generator.h">
<Filter>ETL\Utilities\Generators</Filter>
</ClInclude>
<ClInclude Include="..\..\src\type_traits_generator.h">
<Filter>ETL\Utilities\Generators</Filter>
</ClInclude>
<ClInclude Include="..\..\src\smallest_generator.h">
<Filter>ETL\Utilities\Generators</Filter>
</ClInclude>
<ClInclude Include="..\..\src\message.h">
<Filter>ETL\Frameworks</Filter>
</ClInclude>
<ClInclude Include="..\..\src\message_bus.h">
<Filter>ETL\Frameworks</Filter>
</ClInclude>
<ClInclude Include="..\..\src\message_types.h">
<Filter>ETL\Frameworks</Filter>
</ClInclude>
<ClInclude Include="..\..\src\scheduler.h">
<Filter>ETL\Frameworks</Filter>
</ClInclude>
<ClInclude Include="..\..\src\task.h">
<Filter>ETL\Frameworks</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\main.cpp">
@ -761,6 +800,24 @@
<ClCompile Include="..\..\unittest-cpp\UnitTest++\XmlTestReporter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\test_fsm.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\test_message_router.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\test_packet.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\test_task_scheduler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\test_message_bus.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\test_user_type.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\Doxyfile">
@ -769,8 +826,14 @@
<None Include="..\..\library.properties">
<Filter>Resource Files</Filter>
</None>
<None Include="..\..\src\CreateMessageProcessor.bat">
<Filter>Source Files</Filter>
<None Include="..\..\src\generate.bat">
<Filter>Resource Files</Filter>
</None>
<None Include="..\..\src\generate_message_router.bat">
<Filter>Resource Files</Filter>
</None>
<None Include="..\..\src\generate_fsm.bat">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>

BIN
uml/FSM example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
uml/Framework.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
uml/MessageFramework.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Binary file not shown.