mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Refactored etl::error_handler to use etl::delegate style implementation.
Allows set_callback() function to be given run-time and compile-time pointers to free and member functions without using etl::ifunction.
This commit is contained in:
parent
eabe328398
commit
a27508ca96
@ -47,14 +47,34 @@ namespace etl
|
||||
{
|
||||
namespace private_error_handler
|
||||
{
|
||||
template <class dummy>
|
||||
// A wrapper template to allow static definition in header.
|
||||
template <typename TDummy>
|
||||
struct wrapper
|
||||
{
|
||||
static etl::ifunction<const etl::exception&>* p_ifunction;
|
||||
using stub_type = void(*)(void* object, const etl::exception&);
|
||||
|
||||
//*************************************************************************
|
||||
/// The internal invocation object.
|
||||
//*************************************************************************
|
||||
struct invocation_element
|
||||
{
|
||||
//***********************************************************************
|
||||
invocation_element()
|
||||
: object(ETL_NULLPTR)
|
||||
, stub(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
void* object;
|
||||
stub_type stub;
|
||||
};
|
||||
|
||||
static invocation_element invocation;
|
||||
};
|
||||
|
||||
template <class dummy>
|
||||
etl::ifunction<const etl::exception&>* wrapper<dummy>::p_ifunction = ETL_NULLPTR;
|
||||
template <typename TDummy>
|
||||
typename wrapper<TDummy>::invocation_element wrapper<TDummy>::invocation;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
@ -94,7 +114,52 @@ namespace etl
|
||||
//*****************************************************************************
|
||||
static void set_callback(ifunction<const etl::exception&>& f)
|
||||
{
|
||||
private_error_handler::wrapper<void>::p_ifunction = &f;
|
||||
create((void*)(&f), ifunction_stub);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from function (Compile time).
|
||||
//*************************************************************************
|
||||
template <void(*Method)(const etl::exception&)>
|
||||
static void set_callback()
|
||||
{
|
||||
create(ETL_NULLPTR, function_stub<Method>);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from instance method (Run time).
|
||||
//*************************************************************************
|
||||
template <typename T, void(T::* Method)(const etl::exception&)>
|
||||
static void set_callback(T& instance)
|
||||
{
|
||||
create((void*)(&instance), method_stub<T, Method>);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from const instance method (Run time).
|
||||
//*************************************************************************
|
||||
template <typename T, void(T::* Method)(const etl::exception&) const>
|
||||
static void set_callback(const T& instance)
|
||||
{
|
||||
create((void*)(&instance), const_method_stub<T, Method>);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from instance method (Compile time).
|
||||
//*************************************************************************
|
||||
template <typename T, T& Instance, void(T::* Method)(const etl::exception&)>
|
||||
static void set_callback()
|
||||
{
|
||||
create(method_instance_stub<T, Instance, Method>);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from const instance method (Compile time).
|
||||
//*************************************************************************
|
||||
template <typename T, T const& Instance, void(T::* Method)(const etl::exception&) const>
|
||||
static void set_callback()
|
||||
{
|
||||
create(const_method_instance_stub<T, Instance, Method>);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
@ -103,11 +168,99 @@ namespace etl
|
||||
//*****************************************************************************
|
||||
static void error(const etl::exception& e)
|
||||
{
|
||||
if (private_error_handler::wrapper<void>::p_ifunction != ETL_NULLPTR)
|
||||
if (private_error_handler::wrapper<void>::invocation.stub != ETL_NULLPTR)
|
||||
{
|
||||
(*private_error_handler::wrapper<void>::p_ifunction)(e);
|
||||
(*private_error_handler::wrapper<void>::invocation.stub)(private_error_handler::wrapper<void>::invocation.object, e);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
using stub_type = void(*)(void* object, const etl::exception&);
|
||||
|
||||
//*************************************************************************
|
||||
/// The internal invocation object.
|
||||
//*************************************************************************
|
||||
struct invocation_element
|
||||
{
|
||||
//***********************************************************************
|
||||
void* object = ETL_NULLPTR;
|
||||
stub_type stub = ETL_NULLPTR;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructs a callback from an object and stub.
|
||||
//*************************************************************************
|
||||
static void create(void* object, stub_type stub)
|
||||
{
|
||||
private_error_handler::wrapper<void>::invocation.object = object;
|
||||
private_error_handler::wrapper<void>::invocation.stub = stub;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructs a callback from a stub.
|
||||
//*************************************************************************
|
||||
static void create(stub_type stub)
|
||||
{
|
||||
private_error_handler::wrapper<void>::invocation.object = ETL_NULLPTR;
|
||||
private_error_handler::wrapper<void>::invocation.stub = stub;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a member function. Run time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, void(T::* Method)(const etl::exception&)>
|
||||
static void method_stub(void* object, const etl::exception& e)
|
||||
{
|
||||
T* p = static_cast<T*>(object);
|
||||
return (p->*Method)(e);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a const member function. Run time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, void(T::* Method)(const etl::exception&) const>
|
||||
static void const_method_stub(void* object, const etl::exception& e)
|
||||
{
|
||||
T* const p = static_cast<T*>(object);
|
||||
return (p->*Method)(e);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a member function. Compile time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, T& Instance, void(T::* Method)(const etl::exception&)>
|
||||
static void method_instance_stub(void*, const etl::exception& e)
|
||||
{
|
||||
return (Instance.*Method)(e);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a const member function. Compile time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, const T& Instance, void(T::* Method)(const etl::exception&) const>
|
||||
static void const_method_instance_stub(void*, const etl::exception& e)
|
||||
{
|
||||
(Instance.*Method)(e);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a free function.
|
||||
//*************************************************************************
|
||||
template <void(*Method)(const etl::exception&)>
|
||||
static void function_stub(void*, const etl::exception& e)
|
||||
{
|
||||
(Method)(e);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a ifunction. Run time instance.
|
||||
//*************************************************************************
|
||||
static void ifunction_stub(void* object, const etl::exception& e)
|
||||
{
|
||||
etl::ifunction<const etl::exception&>* p = static_cast<etl::ifunction<const etl::exception&>*>(object);
|
||||
p->operator()(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -134,13 +287,8 @@ namespace etl
|
||||
#endif
|
||||
#else
|
||||
#if defined(ETL_LOG_ERRORS)
|
||||
#if defined(NDEBUG)
|
||||
#define ETL_ASSERT(b, e) {if(!(b)) {etl::error_handler::error((e));}} // If the condition fails, calls the error handler
|
||||
#define ETL_ALWAYS_ASSERT(e) {etl::error_handler::error((e));} // Calls the error handler
|
||||
#else
|
||||
#define ETL_ASSERT(b, e) {if(!(b)) {etl::error_handler::error((e)); assert(false);}} // If the condition fails, calls the error handler then asserts.
|
||||
#define ETL_ALWAYS_ASSERT(e) {etl::error_handler::error((e)); assert(false);} // Calls the error handler then asserts.
|
||||
#endif
|
||||
#define ETL_ASSERT(b, e) {if(!(b)) {etl::error_handler::error((e));}} // If the condition fails, calls the error handler
|
||||
#define ETL_ALWAYS_ASSERT(e) {etl::error_handler::error((e));} // Calls the error handler
|
||||
#else
|
||||
#if defined(NDEBUG)
|
||||
#define ETL_ASSERT(b, e) // Does nothing.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Embedded Template Library",
|
||||
"version": "18.3.4",
|
||||
"version": "18.4.0",
|
||||
"authors": {
|
||||
"name": "John Wellbelove",
|
||||
"email": "john.wellbelove@etlcpp.com"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
name=Embedded Template Library
|
||||
version=18.3.4
|
||||
version=18.4.0
|
||||
author= John Wellbelove <john.wellbelove@etlcpp.com>
|
||||
maintainer=John Wellbelove <john.wellbelove@etlcpp.com>
|
||||
license=MIT
|
||||
|
||||
@ -1,3 +1,8 @@
|
||||
===============================================================================
|
||||
18.4.0
|
||||
Refactored etl::error_handler to use etl::delegate style implementation.
|
||||
Allows set_callback() function to be given run-time and compile-time pointers to free and member functions without using etl::ifunction.
|
||||
|
||||
===============================================================================
|
||||
18.3.4
|
||||
Changed std::move to etl::move in std::optional and std::queue
|
||||
|
||||
@ -34,52 +34,66 @@ SOFTWARE.
|
||||
#include "etl/error_handler.h"
|
||||
#include "etl/exception.h"
|
||||
|
||||
bool error_received;
|
||||
|
||||
//*****************************************************************************
|
||||
// An exception.
|
||||
//*****************************************************************************
|
||||
class test_exception : public etl::exception
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
bool error_received;
|
||||
|
||||
test_exception(string_type file_name_, numeric_type line_number_)
|
||||
: exception(ETL_ERROR_TEXT("test_exception", "123"), file_name_, line_number_)
|
||||
//*****************************************************************************
|
||||
// An exception.
|
||||
//*****************************************************************************
|
||||
class test_exception : public etl::exception
|
||||
{
|
||||
error_received = false;
|
||||
}
|
||||
};
|
||||
public:
|
||||
|
||||
//*****************************************************************************
|
||||
// A free error handler function.
|
||||
//*****************************************************************************
|
||||
void receive_error(const etl::exception& e)
|
||||
{
|
||||
error_received = true;
|
||||
CHECK(strcmp(e.what(), "test_exception") == 0);
|
||||
}
|
||||
test_exception(string_type file_name_, numeric_type line_number_)
|
||||
: exception(ETL_ERROR_TEXT("test_exception", "123"), file_name_, line_number_)
|
||||
{
|
||||
error_received = false;
|
||||
}
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
class test_class
|
||||
{
|
||||
public:
|
||||
|
||||
//***************************************************************************
|
||||
// A member error handler function.
|
||||
//***************************************************************************
|
||||
//*****************************************************************************
|
||||
// A free error handler function.
|
||||
//*****************************************************************************
|
||||
void receive_error(const etl::exception& e)
|
||||
{
|
||||
error_received = true;
|
||||
CHECK(strcmp(e.what(), "test_exception") == 0);
|
||||
}
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
class test_class
|
||||
{
|
||||
public:
|
||||
|
||||
//***************************************************************************
|
||||
// A member error handler function.
|
||||
//***************************************************************************
|
||||
void receive_error(const etl::exception& e)
|
||||
{
|
||||
error_received = true;
|
||||
CHECK(strcmp(e.what(), "test_exception") == 0);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
// A const member error handler function.
|
||||
//***************************************************************************
|
||||
void receive_error_const(const etl::exception& e) const
|
||||
{
|
||||
error_received = true;
|
||||
CHECK(strcmp(e.what(), "test_exception") == 0);
|
||||
}
|
||||
};
|
||||
|
||||
test_class static_test;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
SUITE(test_error_handler)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST(test_free_handler_function)
|
||||
TEST(test_free_handler_function_deprecated)
|
||||
{
|
||||
// Create the function callback object.
|
||||
etl::error_handler::free_function error_callback(receive_error);
|
||||
@ -94,7 +108,7 @@ namespace
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_member_handler_function)
|
||||
TEST(test_member_handler_function_deprecated)
|
||||
{
|
||||
// Create the class that contains the handler.
|
||||
test_class test;
|
||||
@ -110,5 +124,69 @@ namespace
|
||||
|
||||
CHECK(error_received);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_free_handler_function_compile_time)
|
||||
{
|
||||
// Tell the error handler about it.
|
||||
etl::error_handler::set_callback<receive_error>();
|
||||
|
||||
// Log an error.
|
||||
etl::error_handler::error(ETL_ERROR(test_exception));
|
||||
|
||||
CHECK(error_received);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_member_handler_function_run_time)
|
||||
{
|
||||
test_class test;
|
||||
|
||||
// Tell the error handler about it.
|
||||
etl::error_handler::set_callback<test_class, &test_class::receive_error>(test);
|
||||
|
||||
// Log an error.
|
||||
etl::error_handler::error(ETL_ERROR(test_exception));
|
||||
|
||||
CHECK(error_received);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_const_member_handler_function_run_time)
|
||||
{
|
||||
test_class test;
|
||||
|
||||
// Tell the error handler about it.
|
||||
etl::error_handler::set_callback<test_class, &test_class::receive_error_const>(test);
|
||||
|
||||
// Log an error.
|
||||
etl::error_handler::error(ETL_ERROR(test_exception));
|
||||
|
||||
CHECK(error_received);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_member_handler_function_compile_time)
|
||||
{
|
||||
// Tell the error handler about it.
|
||||
etl::error_handler::set_callback<test_class, static_test, &test_class::receive_error>();
|
||||
|
||||
// Log an error.
|
||||
etl::error_handler::error(ETL_ERROR(test_exception));
|
||||
|
||||
CHECK(error_received);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_const_member_handler_function_compile_time)
|
||||
{
|
||||
// Tell the error handler about it.
|
||||
etl::error_handler::set_callback<test_class, static_test, &test_class::receive_error_const>();
|
||||
|
||||
// Log an error.
|
||||
etl::error_handler::error(ETL_ERROR(test_exception));
|
||||
|
||||
CHECK(error_received);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user