mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Merge remote-tracking branch 'origin/feature/delegates' into development
# Conflicts: # include/etl/type_traits.h # include/etl/type_traits_generator.h # test/test_type_traits.cpp
This commit is contained in:
parent
d2719cb63d
commit
d2d3db1659
@ -0,0 +1,149 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "etl/delegate.h"
|
||||
#include "etl/delegate_service.h"
|
||||
|
||||
enum VectorId
|
||||
{
|
||||
TIM1_CC_IRQ_HANDLER = 42,
|
||||
TIM2_IRQ_HANDLER = 43,
|
||||
TIM3_IRQ_HANDLER = 44,
|
||||
USART1_IRQ_HANDLER = 52,
|
||||
USART2_IRQ_HANDLER = 53,
|
||||
VECTOR_ID_END,
|
||||
VECTOR_ID_OFFSET = TIM1_CC_IRQ_HANDLER,
|
||||
VECTOR_ID_RANGE = VECTOR_ID_END - VECTOR_ID_OFFSET
|
||||
};
|
||||
|
||||
typedef etl::delegate_service<VECTOR_ID_RANGE, VECTOR_ID_OFFSET> InterruptVectors;
|
||||
|
||||
// Ensure that the callback service is initialised before use.
|
||||
InterruptVectors& GetInterruptVectorsInstance()
|
||||
{
|
||||
static InterruptVectors interruptVectors;
|
||||
|
||||
return interruptVectors;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
InterruptVectors& interruptVectors = GetInterruptVectorsInstance();
|
||||
|
||||
// Function called from the timer1 interrupt vector.
|
||||
void TIM1_CC_IRQHandler()
|
||||
{
|
||||
interruptVectors.call<TIM1_CC_IRQ_HANDLER>();
|
||||
}
|
||||
|
||||
// Function called from the timer2 interrupt vector.
|
||||
void TIM2_IRQHandler()
|
||||
{
|
||||
interruptVectors.call<TIM2_IRQ_HANDLER>();
|
||||
}
|
||||
|
||||
// Function called from the timer3 interrupt vector.
|
||||
void TIM3_IRQHandler()
|
||||
{
|
||||
interruptVectors.call<TIM3_IRQ_HANDLER>();
|
||||
}
|
||||
|
||||
// Function called from the usart1 interrupt vector.
|
||||
void USART1_IRQHandler()
|
||||
{
|
||||
interruptVectors.call<USART1_IRQ_HANDLER>();
|
||||
}
|
||||
|
||||
// Function called from the usart2 interrupt vector.
|
||||
void USART2_IRQHandler()
|
||||
{
|
||||
interruptVectors.call<USART2_IRQ_HANDLER>();
|
||||
}
|
||||
}
|
||||
|
||||
//********************************
|
||||
// Timer driver.
|
||||
//********************************
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
|
||||
// Handler for interrupts from the timer.
|
||||
void InterruptHandler(const size_t id)
|
||||
{
|
||||
std::cout << "Timer interrupt (member) : ID " << id << "\n";
|
||||
}
|
||||
};
|
||||
|
||||
//********************************
|
||||
// Free function timer driver.
|
||||
//********************************
|
||||
void FreeTimerInterruptHandler(const size_t id)
|
||||
{
|
||||
std::cout << "Timer interrupt (free) : ID " << id << "\n";
|
||||
}
|
||||
|
||||
//********************************
|
||||
// UART driver.
|
||||
//********************************
|
||||
class Uart
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructor.
|
||||
Uart(int port_id, size_t interruptId)
|
||||
: port_id(port_id),
|
||||
callback(etl::delegate<void(size_t)>::create<Uart, &Uart::InterruptHandler>(*this))
|
||||
{
|
||||
GetInterruptVectorsInstance().register_delegate(interruptId, callback);
|
||||
}
|
||||
|
||||
// Handler for interrupts from the UART.
|
||||
void InterruptHandler(const size_t id)
|
||||
{
|
||||
std::cout << "UART" << port_id << " : ID " << id << "\n";
|
||||
}
|
||||
|
||||
etl::delegate<void(size_t)> callback;
|
||||
|
||||
int port_id;
|
||||
};
|
||||
|
||||
void UnhandledInterrupt(const size_t id)
|
||||
{
|
||||
std::cout << "Unhandled Interrupt : ID " << id << "\n";
|
||||
}
|
||||
|
||||
// Declare the driver instances.
|
||||
Timer timer;
|
||||
Uart uart1(0, USART1_IRQ_HANDLER);
|
||||
Uart uart2(1, USART2_IRQ_HANDLER);
|
||||
|
||||
// Declare a global callback for the timer.
|
||||
// Uses the most efficient callback type for a class, as everthing is known at compile time.
|
||||
etl::delegate<void(size_t)> timer_member_callback = etl::delegate<void(size_t)>::create<Timer, timer, &Timer::InterruptHandler>();
|
||||
|
||||
// Declare the callbacks for the free functions.
|
||||
etl::delegate<void(size_t)> timer_free_callback = etl::delegate<void(size_t)>::create<FreeTimerInterruptHandler>();
|
||||
etl::delegate<void(size_t)> unhandled_callback = etl::delegate<void(size_t)>::create<UnhandledInterrupt>();
|
||||
|
||||
//********************************
|
||||
// Test it out.
|
||||
//********************************
|
||||
int main()
|
||||
{
|
||||
// Setup the callbacks.
|
||||
InterruptVectors& interruptVectors = GetInterruptVectorsInstance();
|
||||
|
||||
interruptVectors.register_delegate<TIM1_CC_IRQ_HANDLER>(timer_member_callback);
|
||||
interruptVectors.register_delegate<TIM2_IRQ_HANDLER>(timer_free_callback);
|
||||
interruptVectors.register_unhandled_delegate(unhandled_callback);
|
||||
|
||||
// Simulate the interrupts.
|
||||
TIM1_CC_IRQHandler();
|
||||
TIM2_IRQHandler();
|
||||
USART1_IRQHandler();
|
||||
USART2_IRQHandler();
|
||||
TIM3_IRQHandler(); // Unhandled!
|
||||
|
||||
return 0;
|
||||
}
|
||||
48
examples/FunctionInterruptSimulation-Delegates/etl_profile.h
Normal file
48
examples/FunctionInterruptSimulation-Delegates/etl_profile.h
Normal file
@ -0,0 +1,48 @@
|
||||
///\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_PROFILE_H__
|
||||
#define __ETL_PROFILE_H__
|
||||
|
||||
#define ETL_THROW_EXCEPTIONS
|
||||
#define ETL_VERBOSE_ERRORS
|
||||
#define ETL_CHECK_PUSH_POP
|
||||
#define ETL_ISTRING_REPAIR_ENABLE
|
||||
#define ETL_IVECTOR_REPAIR_ENABLE
|
||||
#define ETL_IDEQUE_REPAIR_ENABLE
|
||||
#define ETL_IN_UNIT_TEST
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "profiles/msvc_x86.h"
|
||||
#else
|
||||
#include "profiles/gcc_windows_x86.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -0,0 +1 @@
|
||||
*.VC.opendb
|
||||
@ -0,0 +1 @@
|
||||
*.VC.opendb
|
||||
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26730.16
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FunctionInterruptSimulation-Delegates", "FunctionInterruptSimulation-Delegates.vcxproj", "{5157DB15-C255-4E47-9FB1-AF388437F90F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{5157DB15-C255-4E47-9FB1-AF388437F90F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5157DB15-C255-4E47-9FB1-AF388437F90F}.Debug|x64.Build.0 = Debug|x64
|
||||
{5157DB15-C255-4E47-9FB1-AF388437F90F}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{5157DB15-C255-4E47-9FB1-AF388437F90F}.Debug|x86.Build.0 = Debug|Win32
|
||||
{5157DB15-C255-4E47-9FB1-AF388437F90F}.Release|x64.ActiveCfg = Release|x64
|
||||
{5157DB15-C255-4E47-9FB1-AF388437F90F}.Release|x64.Build.0 = Release|x64
|
||||
{5157DB15-C255-4E47-9FB1-AF388437F90F}.Release|x86.ActiveCfg = Release|Win32
|
||||
{5157DB15-C255-4E47-9FB1-AF388437F90F}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {260225EB-60CB-44CC-A60C-16A23BBC10EB}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@ -0,0 +1,156 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\FunctionInterruptSimulation.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\etl_profile.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{5157DB15-C255-4E47-9FB1-AF388437F90F}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>FunctionInterruptSimulation</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>../../../src</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
334
include/etl/delegate.h
Normal file
334
include/etl/delegate.h
Normal file
@ -0,0 +1,334 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2019 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.
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
Copyright (C) 2017 by Sergey A Kryukov: derived work
|
||||
http://www.SAKryukov.org
|
||||
http://www.codeproject.com/Members/SAKryukov
|
||||
|
||||
Based on original work by Sergey Ryazanov:
|
||||
"The Impossibly Fast C++ Delegates", 18 Jul 2005
|
||||
https://www.codeproject.com/articles/11015/the-impossibly-fast-c-delegates
|
||||
|
||||
MIT license:
|
||||
http://en.wikipedia.org/wiki/MIT_License
|
||||
|
||||
Original publication: https://www.codeproject.com/Articles/1170503/The-Impossibly-Fast-Cplusplus-Delegates-Fixed
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_DELEGATE_INCLUDED
|
||||
#define ETL_DELEGATE_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#if ETL_CPP11_SUPPORTED == 0
|
||||
#error NOT SUPPORTED FOR C++03 OR BELOW
|
||||
#endif
|
||||
|
||||
namespace etl
|
||||
{
|
||||
template <typename T> class delegate;
|
||||
|
||||
template <typename TReturn, typename... TParams>
|
||||
class delegate<TReturn(TParams...)> final
|
||||
{
|
||||
public:
|
||||
|
||||
//*************************************************************************
|
||||
/// Default constructor.
|
||||
//*************************************************************************
|
||||
delegate() = default;
|
||||
|
||||
//*************************************************************************
|
||||
// Copy constructor.
|
||||
//*************************************************************************
|
||||
delegate(const delegate& other)
|
||||
{
|
||||
other.invocation.clone(invocation);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
// Constructor from lambda or functor.
|
||||
//*************************************************************************
|
||||
template <typename TLambda>
|
||||
delegate(const TLambda& instance)
|
||||
{
|
||||
assign((void*)(&instance), lambda_stub<TLambda>);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from function (Compile time).
|
||||
//*************************************************************************
|
||||
template <TReturn(*Method)(TParams...)>
|
||||
static delegate create()
|
||||
{
|
||||
return delegate(nullptr, function_stub<Method>);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from Lambda or Functor.
|
||||
//*************************************************************************
|
||||
template <typename TLambda>
|
||||
static delegate create(const TLambda& instance)
|
||||
{
|
||||
return delegate((void*)(&instance), lambda_stub<TLambda>);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from instance method (Run time).
|
||||
//*************************************************************************
|
||||
template <typename T, TReturn(T::*Method)(TParams...)>
|
||||
static delegate create(T& instance)
|
||||
{
|
||||
return delegate((void*)(&instance), method_stub<T, Method>);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from const instance method (Run time).
|
||||
//*************************************************************************
|
||||
template <typename T, TReturn(T::*Method)(TParams...) const>
|
||||
static delegate create(const T& instance)
|
||||
{
|
||||
return delegate((void*)(&instance), const_method_stub<T, Method>);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from instance method (Compile time).
|
||||
//*************************************************************************
|
||||
template <typename T, T& Instance, TReturn(T::*Method)(TParams...)>
|
||||
static delegate create()
|
||||
{
|
||||
return delegate(method_instance_stub<T, Instance, Method>);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from const instance method (Compile time).
|
||||
//*************************************************************************
|
||||
template <typename T, T const& Instance, TReturn(T::*Method)(TParams...) const>
|
||||
static delegate create()
|
||||
{
|
||||
return delegate(const_method_instance_stub<T, Instance, Method>);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Execute the delegate.
|
||||
//*************************************************************************
|
||||
TReturn operator()(TParams... args) const
|
||||
{
|
||||
return (*invocation.stub)(invocation.object, args...);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from function (Compile time).
|
||||
//*************************************************************************
|
||||
delegate& operator =(const delegate& other)
|
||||
{
|
||||
other.invocation.clone(invocation);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Create from Lambda or Functor.
|
||||
//*************************************************************************
|
||||
template <typename TLambda>
|
||||
delegate& operator =(const TLambda& instance)
|
||||
{
|
||||
assign((void*)(&instance), lambda_stub<TLambda>);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Checks equality.
|
||||
//*************************************************************************
|
||||
bool operator == (const delegate& other) const
|
||||
{
|
||||
return invocation == other.invocation;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns <b>true</b> if the delegate is valid.
|
||||
//*************************************************************************
|
||||
bool operator != (const delegate& other) const
|
||||
{
|
||||
return invocation != other.invocation;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns <b>true</b> if the delegate is valid.
|
||||
//*************************************************************************
|
||||
bool is_valid() const
|
||||
{
|
||||
return invocation.stub != nullptr;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns <b>true</b> if the delegate is valid.
|
||||
//*************************************************************************
|
||||
operator bool() const
|
||||
{
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
using stub_type = TReturn(*)(void* object, TParams...);
|
||||
|
||||
//*************************************************************************
|
||||
/// The internal invocation object.
|
||||
//*************************************************************************
|
||||
struct invocation_element
|
||||
{
|
||||
invocation_element() = default;
|
||||
|
||||
//***********************************************************************
|
||||
invocation_element(void* object_, stub_type stub_)
|
||||
: object(object_)
|
||||
, stub(stub_)
|
||||
{
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
void clone(invocation_element& target) const
|
||||
{
|
||||
target.stub = stub;
|
||||
target.object = object;
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
bool operator ==(const invocation_element& another) const
|
||||
{
|
||||
return (another.stub == stub) && (another.object == object);
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
bool operator !=(const invocation_element& another) const
|
||||
{
|
||||
return (another.stub != stub) || (another.object != object);
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
void* object = nullptr;
|
||||
stub_type stub = nullptr;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructs a delegate from an object and stub.
|
||||
//*************************************************************************
|
||||
delegate(void* object, stub_type stub)
|
||||
{
|
||||
invocation.object = object;
|
||||
invocation.stub = stub;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructs a delegate from a stub.
|
||||
//*************************************************************************
|
||||
delegate(stub_type stub)
|
||||
{
|
||||
invocation.object = nullptr;
|
||||
invocation.stub = stub;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Assign from an object and stub.
|
||||
//*************************************************************************
|
||||
void assign(void* object, stub_type stub)
|
||||
{
|
||||
invocation.object = object;
|
||||
invocation.stub = stub;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a member function. Run time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, TReturn(T::*Method)(TParams...)>
|
||||
static TReturn method_stub(void* object, TParams... params)
|
||||
{
|
||||
T* p = static_cast<T*>(object);
|
||||
return (p->*Method)(params...);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a const member function. Run time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, TReturn(T::*Method)(TParams...) const>
|
||||
static TReturn const_method_stub(void* object, TParams... params)
|
||||
{
|
||||
T* const p = static_cast<T*>(object);
|
||||
return (p->*Method)(params...);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a member function. Compile time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, T& Instance, TReturn(T::*Method)(TParams...)>
|
||||
static TReturn method_instance_stub(void*, TParams... params)
|
||||
{
|
||||
return (Instance.*Method)(params...);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a const member function. Compile time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, const T& Instance, TReturn(T::*Method)(TParams...) const>
|
||||
static TReturn const_method_instance_stub(void*, TParams... params)
|
||||
{
|
||||
return (Instance.*Method)(params...);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a free function.
|
||||
//*************************************************************************
|
||||
template <TReturn(*Method)(TParams...)>
|
||||
static TReturn function_stub(void*, TParams... params)
|
||||
{
|
||||
return (Method)(params...);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Stub call for a lambda or functor function.
|
||||
//*************************************************************************
|
||||
template <typename TLambda>
|
||||
static TReturn lambda_stub(void* object, TParams... arg)
|
||||
{
|
||||
TLambda* p = static_cast<TLambda*>(object);
|
||||
return (p->operator())(arg...);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// The invocation object.
|
||||
//*************************************************************************
|
||||
invocation_element invocation;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
157
include/etl/delegate_service.h
Normal file
157
include/etl/delegate_service.h
Normal file
@ -0,0 +1,157 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2019 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_DELEGATE_SERVICE_INCLUDED
|
||||
#define ETL_DELEGATE_SERVICE_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "nullptr.h"
|
||||
#include "static_assert.h"
|
||||
#include "delegate.h"
|
||||
#include "array.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// An indexed delegate service.
|
||||
/// \tparam RANGE The number of delegates to handle.
|
||||
/// \tparam OFFSET The lowest delegate id value.
|
||||
/// The delegate ids must range between OFFSET and OFFSET + RANGE - 1.
|
||||
//***************************************************************************
|
||||
template <const size_t RANGE, const size_t OFFSET = 0U>
|
||||
class delegate_service
|
||||
{
|
||||
public:
|
||||
|
||||
//*************************************************************************
|
||||
/// Reset the delegate service.
|
||||
/// Sets all delegates to the internal default.
|
||||
//*************************************************************************
|
||||
delegate_service()
|
||||
{
|
||||
etl::delegate<void(size_t)> default_delegate = etl::delegate<void(size_t)>::create<delegate_service<RANGE, OFFSET>, &delegate_service<RANGE, OFFSET>::unhandled>(*this);
|
||||
|
||||
lookup.fill(default_delegate);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Registers a delegate for the specified id.
|
||||
/// Compile time assert if the id is out of range.
|
||||
/// \tparam ID The id of the delegate.
|
||||
/// \param delegate Reference to the delegate.
|
||||
//*************************************************************************
|
||||
template <const size_t ID>
|
||||
void register_delegate(etl::delegate<void(size_t)> callback)
|
||||
{
|
||||
ETL_STATIC_ASSERT(ID < (OFFSET + RANGE), "Callback Id out of range");
|
||||
ETL_STATIC_ASSERT(ID >= OFFSET, "Callback Id out of range");
|
||||
|
||||
lookup[ID - OFFSET] = callback;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Registers a delegate for the specified id.
|
||||
/// No action if the id is out of range.
|
||||
/// \param id Id of the delegate.
|
||||
/// \param delegate Reference to the delegate.
|
||||
//*************************************************************************
|
||||
void register_delegate(const size_t id, etl::delegate<void(size_t)> callback)
|
||||
{
|
||||
if ((id >= OFFSET) && (id < (OFFSET + RANGE)))
|
||||
{
|
||||
lookup[id - OFFSET] = callback;
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Registers an alternative delegate for unhandled ids.
|
||||
/// \param delegate A reference to the user supplied 'unhandled' delegate.
|
||||
//*************************************************************************
|
||||
void register_unhandled_delegate(etl::delegate<void(size_t)> callback)
|
||||
{
|
||||
unhandled_delegate = callback;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Executes the delegate function for the index.
|
||||
/// Compile time assert if the id is out of range.
|
||||
/// \tparam ID The id of the delegate.
|
||||
//*************************************************************************
|
||||
template <const size_t ID>
|
||||
void call()
|
||||
{
|
||||
ETL_STATIC_ASSERT(ID < (OFFSET + RANGE), "Callback Id out of range");
|
||||
ETL_STATIC_ASSERT(ID >= OFFSET, "Callback Id out of range");
|
||||
|
||||
lookup[ID - OFFSET](ID);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Executes the delegate function for the index.
|
||||
/// \param id Id of the delegate.
|
||||
//*************************************************************************
|
||||
void call(const size_t id)
|
||||
{
|
||||
if ((id >= OFFSET) && (id < (OFFSET + RANGE)))
|
||||
{
|
||||
lookup[id - OFFSET](id);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unhandled_delegate.is_valid())
|
||||
{
|
||||
unhandled_delegate(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//*************************************************************************
|
||||
/// The default callback function.
|
||||
/// Calls the user defined 'unhandled' callback if it exists.
|
||||
//*************************************************************************
|
||||
void unhandled(size_t id)
|
||||
{
|
||||
if (unhandled_delegate.is_valid())
|
||||
{
|
||||
unhandled_delegate(id);
|
||||
}
|
||||
}
|
||||
|
||||
/// The default delegate for unhandled ids.
|
||||
etl::delegate<void(size_t)> unhandled_delegate;
|
||||
|
||||
/// Lookup table of delegates.
|
||||
etl::array<etl::delegate<void(size_t)>, RANGE> lookup;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
143
include/etl/multicast_delegate.h
Normal file
143
include/etl/multicast_delegate.h
Normal file
@ -0,0 +1,143 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2019 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.
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
Copyright (C) 2017 by Sergey A Kryukov: derived work
|
||||
http://www.SAKryukov.org
|
||||
http://www.codeproject.com/Members/SAKryukov
|
||||
|
||||
Based on original work by Sergey Ryazanov:
|
||||
"The Impossibly Fast C++ Delegates", 18 Jul 2005
|
||||
https://www.codeproject.com/articles/11015/the-impossibly-fast-c-delegates
|
||||
|
||||
MIT license:
|
||||
http://en.wikipedia.org/wiki/MIT_License
|
||||
|
||||
Original publication: https://www.codeproject.com/Articles/1170503/The-Impossibly-Fast-Cplusplus-Delegates-Fixed
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
//#pragma once
|
||||
//#include "delegate.h"
|
||||
//#include <list>
|
||||
//#include <functional>
|
||||
//
|
||||
//namespace SA {
|
||||
//
|
||||
// template<typename RET, typename ...PARAMS>
|
||||
// class multicast_delegate<RET(PARAMS...)> final : private delegate_base<RET(PARAMS...)> {
|
||||
// public:
|
||||
//
|
||||
// multicast_delegate() = default;
|
||||
// ~multicast_delegate() {
|
||||
// for (auto& element : invocationList) delete element;
|
||||
// invocationList.clear();
|
||||
// } //~multicast_delegate
|
||||
//
|
||||
// bool isNull() const { return invocationList.size() < 1; }
|
||||
// bool operator ==(void* ptr) const {
|
||||
// return (ptr == nullptr) && this->isNull();
|
||||
// } //operator ==
|
||||
// bool operator !=(void* ptr) const {
|
||||
// return (ptr != nullptr) || (!this->isNull());
|
||||
// } //operator !=
|
||||
//
|
||||
// size_t size() const { return invocationList.size(); }
|
||||
//
|
||||
// multicast_delegate& operator =(const multicast_delegate&) = delete;
|
||||
// multicast_delegate(const multicast_delegate&) = delete;
|
||||
//
|
||||
// bool operator ==(const multicast_delegate& another) const {
|
||||
// if (invocationList.size() != another.invocationList.size()) return false;
|
||||
// auto anotherIt = another.invocationList.begin();
|
||||
// for (auto it = invocationList.begin(); it != invocationList.end(); ++it)
|
||||
// if (**it != **anotherIt) return false;
|
||||
// return true;
|
||||
// } //==
|
||||
// bool operator !=(const multicast_delegate& another) const { return !(*this == another); }
|
||||
//
|
||||
// bool operator ==(const delegate<RET(PARAMS...)>& another) const {
|
||||
// if (isNull() && another.isNull()) return true;
|
||||
// if (another.isNull() || (size() != 1)) return false;
|
||||
// return (another.invocation == **invocationList.begin());
|
||||
// } //==
|
||||
// bool operator !=(const delegate<RET(PARAMS...)>& another) const { return !(*this == another); }
|
||||
//
|
||||
// multicast_delegate& operator +=(const multicast_delegate& another) {
|
||||
// for (auto& item : another.invocationList) // clone, not copy; flattens hierarchy:
|
||||
// this->invocationList.push_back(new typename delegate_base<RET(PARAMS...)>::InvocationElement(item->object, item->stub));
|
||||
// return *this;
|
||||
// } //operator +=
|
||||
//
|
||||
// template <typename LAMBDA> // template instantiation is not neededm, will be deduced/inferred:
|
||||
// multicast_delegate& operator +=(const LAMBDA & lambda) {
|
||||
// delegate<RET(PARAMS...)> d = delegate<RET(PARAMS...)>::template create<LAMBDA>(lambda);
|
||||
// return *this += d;
|
||||
// } //operator +=
|
||||
//
|
||||
// multicast_delegate& operator +=(const delegate<RET(PARAMS...)>& another) {
|
||||
// if (another.isNull()) return *this;
|
||||
// this->invocationList.push_back(new typename delegate_base<RET(PARAMS...)>::InvocationElement(another.invocation.object, another.invocation.stub));
|
||||
// return *this;
|
||||
// } //operator +=
|
||||
//
|
||||
// // will work even if RET is void, return values are ignored:
|
||||
// // (for handling return values, see operator(..., handler))
|
||||
// void operator()(PARAMS... arg) const {
|
||||
// for (auto& item : invocationList)
|
||||
// (*(item->stub))(item->object, arg...);
|
||||
// } //operator()
|
||||
//
|
||||
// template<typename HANDLER>
|
||||
// void operator()(PARAMS... arg, HANDLER handler) const {
|
||||
// size_t index = 0;
|
||||
// for (auto& item : invocationList) {
|
||||
// RET value = (*(item->stub))(item->object, arg...);
|
||||
// handler(index, &value);
|
||||
// ++index;
|
||||
// } //loop
|
||||
// } //operator()
|
||||
//
|
||||
// void operator()(PARAMS... arg, delegate<void(size_t, RET*)> handler) const {
|
||||
// operator()<decltype(handler)>(arg..., handler);
|
||||
// } //operator()
|
||||
// void operator()(PARAMS... arg, std::function<void(size_t, RET*)> handler) const {
|
||||
// operator()<decltype(handler)>(arg..., handler);
|
||||
// } //operator()
|
||||
//
|
||||
// private:
|
||||
//
|
||||
// std::list<typename delegate_base<RET(PARAMS...)>::InvocationElement *> invocationList;
|
||||
//
|
||||
// }; //class multicast_delegate
|
||||
//
|
||||
//} /* namespace SA */
|
||||
//
|
||||
@ -492,14 +492,14 @@ namespace etl
|
||||
///\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,
|
||||
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,
|
||||
typename T17 = void>
|
||||
struct is_one_of
|
||||
{
|
||||
static const bool value =
|
||||
static const bool value =
|
||||
etl::is_same<T, T1>::value ||
|
||||
etl::is_same<T, T2>::value ||
|
||||
etl::is_same<T, T3>::value ||
|
||||
@ -600,13 +600,19 @@ namespace etl
|
||||
template <typename T>
|
||||
struct size_of
|
||||
{
|
||||
static const size_t size = sizeof(T);
|
||||
enum
|
||||
{
|
||||
size = sizeof(T)
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct size_of<void>
|
||||
{
|
||||
static const size_t size = 1;
|
||||
enum
|
||||
{
|
||||
size = 1
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -605,13 +605,19 @@ namespace etl
|
||||
template <typename T>
|
||||
struct size_of
|
||||
{
|
||||
static const size_t size = sizeof(T);
|
||||
enum
|
||||
{
|
||||
size = sizeof(T)
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct size_of<void>
|
||||
{
|
||||
static const size_t size = 1;
|
||||
enum
|
||||
{
|
||||
size = 1
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -181,6 +181,8 @@
|
||||
<Unit filename="../../include/etl/cyclic_value.h" />
|
||||
<Unit filename="../../include/etl/debounce.h" />
|
||||
<Unit filename="../../include/etl/debug_count.h" />
|
||||
<Unit filename="../../include/etl/delegate.h" />
|
||||
<Unit filename="../../include/etl/delegate_service.h" />
|
||||
<Unit filename="../../include/etl/deque.h" />
|
||||
<Unit filename="../../include/etl/doxygen.h" />
|
||||
<Unit filename="../../include/etl/endianness.h" />
|
||||
@ -248,6 +250,9 @@
|
||||
<Unit filename="../../include/etl/pool.h" />
|
||||
<Unit filename="../../include/etl/power.h" />
|
||||
<Unit filename="../../include/etl/priority_queue.h" />
|
||||
<Unit filename="../../include/etl/private/delegate_base.h" />
|
||||
<Unit filename="../../include/etl/private/delegate_base_cpp03.h" />
|
||||
<Unit filename="../../include/etl/private/delegate_cpp03.h" />
|
||||
<Unit filename="../../include/etl/private/ivectorpointer.h" />
|
||||
<Unit filename="../../include/etl/private/pvoidvector.h" />
|
||||
<Unit filename="../../include/etl/private/to_string_helper.h" />
|
||||
@ -362,6 +367,8 @@
|
||||
<Unit filename="../test_crc.cpp" />
|
||||
<Unit filename="../test_cyclic_value.cpp" />
|
||||
<Unit filename="../test_debounce.cpp" />
|
||||
<Unit filename="../test_delegate.cpp" />
|
||||
<Unit filename="../test_delegate_service.cpp" />
|
||||
<Unit filename="../test_deque.cpp" />
|
||||
<Unit filename="../test_endian.cpp" />
|
||||
<Unit filename="../test_enum_type.cpp" />
|
||||
|
||||
@ -101,22 +101,22 @@ namespace
|
||||
|
||||
// Callback for 'unhandled'.
|
||||
etl::function_fp<size_t, unhandled> unhandled_callback;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Initialises the test results.
|
||||
//*****************************************************************************
|
||||
struct SetupFixture
|
||||
{
|
||||
SetupFixture()
|
||||
//*****************************************************************************
|
||||
// Initialises the test results.
|
||||
//*****************************************************************************
|
||||
struct SetupFixture
|
||||
{
|
||||
called_id = UINT_MAX;
|
||||
global_called = false;
|
||||
member1_called = false;
|
||||
member2_called = false;
|
||||
unhandled_called = false;
|
||||
}
|
||||
};
|
||||
SetupFixture()
|
||||
{
|
||||
called_id = UINT_MAX;
|
||||
global_called = false;
|
||||
member1_called = false;
|
||||
member2_called = false;
|
||||
unhandled_called = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
506
test/test_delegate.cpp
Normal file
506
test/test_delegate.cpp
Normal file
@ -0,0 +1,506 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
http://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.
|
||||
******************************************************************************/
|
||||
|
||||
#include "UnitTest++.h"
|
||||
|
||||
#include "etl/delegate.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
//*****************************************************************************
|
||||
const int VALUE1 = 1;
|
||||
const int VALUE2 = 2;
|
||||
bool function_called = false;
|
||||
bool parameter_correct = false;
|
||||
|
||||
//*****************************************************************************
|
||||
// Test data structure.
|
||||
//*****************************************************************************
|
||||
struct Data
|
||||
{
|
||||
int d;
|
||||
};
|
||||
|
||||
Data data;
|
||||
|
||||
//*****************************************************************************
|
||||
// The free function taking no parameters.
|
||||
//*****************************************************************************
|
||||
void free_void()
|
||||
{
|
||||
function_called = true;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// The free function taking an int parameter.
|
||||
//*****************************************************************************
|
||||
void free_int(int i, int j)
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (i == VALUE1) && (j == VALUE2);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// The free function taking a Data reference parameter.
|
||||
//*****************************************************************************
|
||||
void free_reference(const Data& data, int j)
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (data.d == VALUE1) && (j = VALUE2);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// The test class with member functions.
|
||||
//*****************************************************************************
|
||||
class Test
|
||||
{
|
||||
public:
|
||||
|
||||
//*******************************************
|
||||
// void
|
||||
void member_void()
|
||||
{
|
||||
function_called = true;
|
||||
}
|
||||
|
||||
void member_void_const() const
|
||||
{
|
||||
function_called = true;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
// int
|
||||
void member_int(int i, int j)
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (i == VALUE1) && (j == VALUE2);
|
||||
}
|
||||
|
||||
void member_int_const(int i, int j) const
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (i == VALUE1) && (j == VALUE2);
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
// reference
|
||||
void member_reference(const Data& data, int j)
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (data.d == VALUE1) && (j = VALUE2);
|
||||
}
|
||||
|
||||
void member_reference_const(const Data& data, int j) const
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (data.d == VALUE1) && (j = VALUE2);
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
// static
|
||||
static void member_static(const Data& data, int j)
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (data.d == VALUE1) && (j = VALUE2);
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
// operator()
|
||||
void operator()()
|
||||
{
|
||||
function_called = true;
|
||||
}
|
||||
|
||||
void operator()() const
|
||||
{
|
||||
function_called = true;
|
||||
}
|
||||
};
|
||||
|
||||
Test test_static;
|
||||
const Test const_test_static;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Initialises the test results.
|
||||
//*****************************************************************************
|
||||
struct SetupFixture
|
||||
{
|
||||
SetupFixture()
|
||||
{
|
||||
function_called = false;
|
||||
parameter_correct = false;
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
SUITE(test_delegate)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_is_valid_false)
|
||||
{
|
||||
etl::delegate<void(void)> d;
|
||||
|
||||
CHECK(!d.is_valid());
|
||||
CHECK(!d);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_is_valid_true)
|
||||
{
|
||||
etl::delegate<void(void)> d([] {});
|
||||
|
||||
CHECK(d.is_valid());
|
||||
CHECK(d);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_free_void)
|
||||
{
|
||||
etl::delegate<void(void)> d = etl::delegate<void(void)>::create<free_void>();
|
||||
|
||||
d();
|
||||
|
||||
CHECK(function_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_free_int)
|
||||
{
|
||||
etl::delegate<void(int, int)> d = etl::delegate<void(int, int)>::create<free_int>();
|
||||
|
||||
d(VALUE1, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_free_reference)
|
||||
{
|
||||
etl::delegate<void(const Data&, int)> d = etl::delegate<void(const Data&, int)>::create<free_reference>();
|
||||
|
||||
Data data;
|
||||
data.d = VALUE1;
|
||||
|
||||
d(data, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_lambda_int)
|
||||
{
|
||||
etl::delegate<void(int, int)> d([](int i, int j) { function_called = true; parameter_correct = (i == VALUE1) && (j == VALUE2); });
|
||||
|
||||
d(VALUE1, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_lambda_int_create)
|
||||
{
|
||||
auto lambda = [](int i, int j) { function_called = true; parameter_correct = (i == VALUE1) && (j == VALUE2); };
|
||||
|
||||
etl::delegate<void(int, int)> d(lambda);
|
||||
|
||||
d(VALUE1, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_operator_void)
|
||||
{
|
||||
Test test;
|
||||
|
||||
etl::delegate<void(void)> d(test);
|
||||
|
||||
d();
|
||||
|
||||
CHECK(function_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_operator_void_create)
|
||||
{
|
||||
Test test;
|
||||
|
||||
etl::delegate<void(void)> d = etl::delegate<void(void)>::create(test);
|
||||
|
||||
d();
|
||||
|
||||
CHECK(function_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_operator_void_const)
|
||||
{
|
||||
const Test test;
|
||||
|
||||
etl::delegate<void(void)> d(test);
|
||||
|
||||
d();
|
||||
|
||||
CHECK(function_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_assignment_member_operator_void)
|
||||
{
|
||||
Test test;
|
||||
|
||||
etl::delegate<void(void)> d;
|
||||
|
||||
d = test;
|
||||
|
||||
d();
|
||||
|
||||
CHECK(function_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_void)
|
||||
{
|
||||
Test test;
|
||||
|
||||
etl::delegate<void(void)> d = etl::delegate<void(void)>::create<Test, &Test::member_void>(test);
|
||||
|
||||
d();
|
||||
|
||||
CHECK(function_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_void_const)
|
||||
{
|
||||
const Test test;
|
||||
|
||||
etl::delegate<void(void)> d = etl::delegate<void(void)>::create<Test, &Test::member_void_const>(test);
|
||||
|
||||
d();
|
||||
|
||||
CHECK(function_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_int)
|
||||
{
|
||||
Test test;
|
||||
|
||||
etl::delegate<void(int, int)> d = etl::delegate<void(int, int)>::create<Test, &Test::member_int>(test);
|
||||
|
||||
d(VALUE1, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_int_const)
|
||||
{
|
||||
const Test test;
|
||||
|
||||
etl::delegate<void(int, int)> d = etl::delegate<void(int, int)>::create<Test, &Test::member_int_const>(test);
|
||||
|
||||
d(VALUE1, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_reference)
|
||||
{
|
||||
Test test;
|
||||
etl::delegate<void(const Data&, int)> d = etl::delegate<void(const Data&, int)>::create<Test, &Test::member_reference>(test);
|
||||
|
||||
Data data;
|
||||
data.d = VALUE1;
|
||||
|
||||
d(data, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_reference_const)
|
||||
{
|
||||
const Test test;
|
||||
etl::delegate<void(const Data&, int)> d = etl::delegate<void(const Data&, int)>::create<Test, &Test::member_reference_const>(test);
|
||||
|
||||
Data data;
|
||||
data.d = VALUE1;
|
||||
|
||||
d(data, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_static)
|
||||
{
|
||||
etl::delegate<void(const Data&, int)> d = etl::delegate<void(const Data&, int)>::create<Test::member_static>();
|
||||
|
||||
Data data;
|
||||
data.d = VALUE1;
|
||||
|
||||
d(data, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_void_compile_time)
|
||||
{
|
||||
etl::delegate<void(void)> d = etl::delegate<void(void)>::create<Test, test_static, &Test::member_void>();
|
||||
|
||||
d();
|
||||
|
||||
CHECK(function_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_void_const_compile_time)
|
||||
{
|
||||
etl::delegate<void(void)> d = etl::delegate<void(void)>::create<Test, const_test_static, &Test::member_void_const>();
|
||||
|
||||
d();
|
||||
|
||||
CHECK(function_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_int_compile_time)
|
||||
{
|
||||
etl::delegate<void(int, int)> d = etl::delegate<void(int, int)>::create<Test, test_static, &Test::member_int>();
|
||||
|
||||
d(VALUE1, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_int_const_compile_time)
|
||||
{
|
||||
etl::delegate<void(int, int)> d = etl::delegate<void(int, int)>::create<Test, const_test_static, &Test::member_int_const>();
|
||||
|
||||
d(VALUE1, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_reference_compile_time)
|
||||
{
|
||||
etl::delegate<void(const Data&, int)> d = etl::delegate<void(const Data&, int)>::create<Test, test_static, &Test::member_reference>();
|
||||
|
||||
Data data;
|
||||
data.d = VALUE1;
|
||||
|
||||
d(data, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_member_reference_const_compile_time)
|
||||
{
|
||||
etl::delegate<void(const Data&, int)> d = etl::delegate<void(const Data&, int)>::create<Test, const_test_static, &Test::member_reference_const>();
|
||||
|
||||
Data data;
|
||||
data.d = VALUE1;
|
||||
|
||||
d(data, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_copy_construct)
|
||||
{
|
||||
Test test;
|
||||
|
||||
etl::delegate<void(int, int)> d1 = etl::delegate<void(int, int)>::create<Test, &Test::member_int>(test);
|
||||
etl::delegate<void(int, int)> d2(d1);
|
||||
|
||||
d2(VALUE1, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_assignment)
|
||||
{
|
||||
Test test;
|
||||
|
||||
etl::delegate<void(int, int)> d1 = etl::delegate<void(int, int)>::create<Test, &Test::member_int>(test);
|
||||
etl::delegate<void(int, int)> d2;
|
||||
|
||||
d2 = d1;
|
||||
|
||||
d2(VALUE1, VALUE2);
|
||||
|
||||
CHECK(function_called);
|
||||
CHECK(parameter_correct);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_equal)
|
||||
{
|
||||
Test test;
|
||||
|
||||
etl::delegate<void(int, int)> d1 = etl::delegate<void(int, int)>::create<Test, &Test::member_int>(test);
|
||||
etl::delegate<void(int, int)> d2 = d1;
|
||||
|
||||
CHECK(d1 == d2);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_not_equal)
|
||||
{
|
||||
Test test;
|
||||
|
||||
etl::delegate<void(int, int)> d1 = etl::delegate<void(int, int)>::create<Test, &Test::member_int>(test);
|
||||
etl::delegate<void(int, int)> d2 = etl::delegate<void(int, int)>::create<Test, &Test::member_int_const>(test);;
|
||||
|
||||
CHECK(d1 != d2);
|
||||
}
|
||||
};
|
||||
}
|
||||
333
test/test_delegate_service.cpp
Normal file
333
test/test_delegate_service.cpp
Normal file
@ -0,0 +1,333 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2019 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 "etl/delegate.h"
|
||||
#include "etl/delegate_service.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
const size_t SIZE = 3U;
|
||||
const size_t OFFSET = 5U;
|
||||
|
||||
using Service = etl::delegate_service<SIZE, OFFSET>;
|
||||
|
||||
//*****************************************************************************
|
||||
bool global_called = false;
|
||||
bool member1_called = false;
|
||||
bool member2_called = false;
|
||||
bool unhandled_called = false;
|
||||
size_t called_id = UINT_MAX;
|
||||
|
||||
//*****************************************************************************
|
||||
// The global function taking no parameters.
|
||||
//*****************************************************************************
|
||||
void global(size_t id)
|
||||
{
|
||||
global_called = true;
|
||||
called_id = id;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// The external unhandled callback.
|
||||
//*****************************************************************************
|
||||
void unhandled(size_t id)
|
||||
{
|
||||
unhandled_called = true;
|
||||
called_id = id;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// The test class with member functions.
|
||||
//*****************************************************************************
|
||||
class Test
|
||||
{
|
||||
public:
|
||||
|
||||
Test()
|
||||
: callback(etl::delegate<void(size_t)>::create<Test, &Test::member1>(*this))
|
||||
{
|
||||
}
|
||||
|
||||
void member1(size_t id)
|
||||
{
|
||||
member1_called = true;
|
||||
called_id = id;
|
||||
}
|
||||
|
||||
void member2(size_t id)
|
||||
{
|
||||
member2_called = true;
|
||||
called_id = id;
|
||||
}
|
||||
|
||||
// Callback for 'member1'.
|
||||
etl::delegate<void(size_t)> callback;
|
||||
};
|
||||
|
||||
Test test;
|
||||
|
||||
// Callback for 'member2'.
|
||||
etl::delegate<void(size_t)> member_callback = etl::delegate<void(size_t)>::create<Test, test, &Test::member2>();
|
||||
|
||||
// Callback for 'global'.
|
||||
etl::delegate<void(size_t)> global_callback = etl::delegate<void(size_t)>::create<global>();
|
||||
|
||||
// Callback for 'unhandled'.
|
||||
etl::delegate<void(size_t)> unhandled_callback = etl::delegate<void(size_t)>::create<unhandled>();
|
||||
|
||||
//*****************************************************************************
|
||||
// Initialises the test results.
|
||||
//*****************************************************************************
|
||||
struct SetupFixture
|
||||
{
|
||||
SetupFixture()
|
||||
{
|
||||
called_id = UINT_MAX;
|
||||
global_called = false;
|
||||
member1_called = false;
|
||||
member2_called = false;
|
||||
unhandled_called = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
enum
|
||||
{
|
||||
GLOBAL = OFFSET,
|
||||
MEMBER1,
|
||||
MEMBER2,
|
||||
OUT_OF_RANGE
|
||||
};
|
||||
|
||||
SUITE(test_delegate_service)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_global_compile_time)
|
||||
{
|
||||
Service service;
|
||||
|
||||
service.register_delegate<GLOBAL>(global_callback);
|
||||
service.register_delegate<MEMBER1>(test.callback);
|
||||
service.register_delegate<MEMBER2>(member_callback);
|
||||
|
||||
service.call<GLOBAL>();
|
||||
|
||||
CHECK_EQUAL(GLOBAL, called_id);
|
||||
CHECK(global_called);
|
||||
CHECK(!member1_called);
|
||||
CHECK(!member2_called);
|
||||
CHECK(!unhandled_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_global_run_time)
|
||||
{
|
||||
Service service;
|
||||
|
||||
service.register_delegate(GLOBAL, global_callback);
|
||||
service.register_delegate(MEMBER1, test.callback);
|
||||
service.register_delegate(MEMBER2, member_callback);
|
||||
|
||||
service.call(GLOBAL);
|
||||
|
||||
CHECK_EQUAL(GLOBAL, called_id);
|
||||
CHECK(global_called);
|
||||
CHECK(!member1_called);
|
||||
CHECK(!member2_called);
|
||||
CHECK(!unhandled_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_member1_compile_time)
|
||||
{
|
||||
Service service;
|
||||
|
||||
service.register_delegate<GLOBAL>(global_callback);
|
||||
service.register_delegate<MEMBER1>(test.callback);
|
||||
service.register_delegate<MEMBER2>(member_callback);
|
||||
|
||||
service.call<MEMBER1>();
|
||||
|
||||
CHECK_EQUAL(MEMBER1, called_id);
|
||||
CHECK(!global_called);
|
||||
CHECK(member1_called);
|
||||
CHECK(!member2_called);
|
||||
CHECK(!unhandled_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_member1_run_time)
|
||||
{
|
||||
Service service;
|
||||
|
||||
service.register_delegate(GLOBAL, global_callback);
|
||||
service.register_delegate(MEMBER1, test.callback);
|
||||
service.register_delegate(MEMBER2, member_callback);
|
||||
|
||||
service.call(MEMBER1);
|
||||
|
||||
CHECK_EQUAL(MEMBER1, called_id);
|
||||
CHECK(!global_called);
|
||||
CHECK(member1_called);
|
||||
CHECK(!member2_called);
|
||||
CHECK(!unhandled_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_member2_compile_time)
|
||||
{
|
||||
Service service;
|
||||
|
||||
service.register_delegate<GLOBAL>(global_callback);
|
||||
service.register_delegate<MEMBER1>(test.callback);
|
||||
service.register_delegate<MEMBER2>(member_callback);
|
||||
|
||||
service.call<MEMBER2>();
|
||||
|
||||
CHECK_EQUAL(MEMBER2, called_id);
|
||||
CHECK(!global_called);
|
||||
CHECK(!member1_called);
|
||||
CHECK(member2_called);
|
||||
CHECK(!unhandled_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_unhandled_out_of_range_run_time_default)
|
||||
{
|
||||
Service service;
|
||||
|
||||
service.register_delegate<GLOBAL>(global_callback);
|
||||
service.register_delegate<MEMBER1>(test.callback);
|
||||
service.register_delegate<MEMBER2>(member_callback);
|
||||
|
||||
service.call(OUT_OF_RANGE);
|
||||
|
||||
CHECK_EQUAL(UINT_MAX, called_id);
|
||||
CHECK(!global_called);
|
||||
CHECK(!member1_called);
|
||||
CHECK(!member2_called);
|
||||
CHECK(!unhandled_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_unhandled_out_of_range_run_time_user_supplied)
|
||||
{
|
||||
Service service;
|
||||
|
||||
service.register_delegate<GLOBAL>(global_callback);
|
||||
service.register_delegate<MEMBER1>(test.callback);
|
||||
service.register_delegate<MEMBER2>(member_callback);
|
||||
|
||||
service.register_unhandled_delegate(unhandled_callback);
|
||||
|
||||
service.call(OUT_OF_RANGE);
|
||||
|
||||
CHECK_EQUAL(OUT_OF_RANGE, called_id);
|
||||
CHECK(!global_called);
|
||||
CHECK(!member1_called);
|
||||
CHECK(!member2_called);
|
||||
CHECK(unhandled_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_unhandled_not_registered_compile_time_default)
|
||||
{
|
||||
Service service;
|
||||
|
||||
service.register_delegate<GLOBAL>(global_callback);
|
||||
service.register_delegate<MEMBER2>(member_callback);
|
||||
|
||||
service.call<MEMBER1>();
|
||||
|
||||
CHECK_EQUAL(UINT_MAX, called_id);
|
||||
CHECK(!global_called);
|
||||
CHECK(!member1_called);
|
||||
CHECK(!member2_called);
|
||||
CHECK(!unhandled_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_unhandled_not_registered_run_time_default)
|
||||
{
|
||||
Service service;
|
||||
|
||||
service.register_delegate(GLOBAL, global_callback);
|
||||
service.register_delegate(MEMBER2, member_callback);
|
||||
|
||||
service.call(MEMBER1);
|
||||
|
||||
CHECK_EQUAL(UINT_MAX, called_id);
|
||||
CHECK(!global_called);
|
||||
CHECK(!member1_called);
|
||||
CHECK(!member2_called);
|
||||
CHECK(!unhandled_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_not_registered_compile_time_user_supplied)
|
||||
{
|
||||
Service service;
|
||||
|
||||
service.register_delegate<GLOBAL>(global_callback);
|
||||
service.register_delegate<MEMBER2>(member_callback);
|
||||
|
||||
service.register_unhandled_delegate(unhandled_callback);
|
||||
|
||||
service.call<MEMBER1>();
|
||||
|
||||
CHECK_EQUAL(MEMBER1, called_id);
|
||||
CHECK(!global_called);
|
||||
CHECK(!member1_called);
|
||||
CHECK(!member2_called);
|
||||
CHECK(unhandled_called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_delegate_unhandled_run_time_user_supplied)
|
||||
{
|
||||
Service service;
|
||||
|
||||
service.register_delegate(GLOBAL, global_callback);
|
||||
service.register_delegate(MEMBER2, member_callback);
|
||||
|
||||
service.register_unhandled_delegate(unhandled_callback);
|
||||
|
||||
service.call(MEMBER1);
|
||||
|
||||
CHECK_EQUAL(MEMBER1, called_id);
|
||||
CHECK(!global_called);
|
||||
CHECK(!member1_called);
|
||||
CHECK(!member2_called);
|
||||
CHECK(unhandled_called);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -30,123 +30,126 @@ SOFTWARE.
|
||||
|
||||
#include "etl/function.h"
|
||||
|
||||
//*****************************************************************************
|
||||
const int VALUE = 1;
|
||||
bool function_called = false;
|
||||
bool parameter_correct = false;
|
||||
|
||||
//*****************************************************************************
|
||||
// Test data structure.
|
||||
//*****************************************************************************
|
||||
struct Data
|
||||
namespace
|
||||
{
|
||||
int d;
|
||||
};
|
||||
//*****************************************************************************
|
||||
const int VALUE = 1;
|
||||
bool function_called = false;
|
||||
bool parameter_correct = false;
|
||||
|
||||
//*****************************************************************************
|
||||
// Call the function taking no parameters.
|
||||
//*****************************************************************************
|
||||
void call(etl::ifunction<void>& function)
|
||||
{
|
||||
function();
|
||||
}
|
||||
//*****************************************************************************
|
||||
// Test data structure.
|
||||
//*****************************************************************************
|
||||
struct Data
|
||||
{
|
||||
int d;
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
// Call the const function taking no parameters.
|
||||
//*****************************************************************************
|
||||
void call(const etl::ifunction<void>& function)
|
||||
{
|
||||
function();
|
||||
}
|
||||
//*****************************************************************************
|
||||
// Call the function taking no parameters.
|
||||
//*****************************************************************************
|
||||
void call(etl::ifunction<void>& function)
|
||||
{
|
||||
function();
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Call the function taking an int parameter.
|
||||
//*****************************************************************************
|
||||
void call(etl::ifunction<int>& function)
|
||||
{
|
||||
function(VALUE);
|
||||
}
|
||||
//*****************************************************************************
|
||||
// Call the const function taking no parameters.
|
||||
//*****************************************************************************
|
||||
void call(const etl::ifunction<void>& function)
|
||||
{
|
||||
function();
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Call the const function taking an int parameter.
|
||||
//*****************************************************************************
|
||||
void call(const etl::ifunction<int>& function)
|
||||
{
|
||||
function(VALUE);
|
||||
}
|
||||
//*****************************************************************************
|
||||
// Call the function taking an int parameter.
|
||||
//*****************************************************************************
|
||||
void call(etl::ifunction<int>& function)
|
||||
{
|
||||
function(VALUE);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Call the function taking a Data parameter.
|
||||
//*****************************************************************************
|
||||
void call(etl::ifunction<const Data&>& function)
|
||||
{
|
||||
Data data;
|
||||
data.d = VALUE;
|
||||
function(data);
|
||||
}
|
||||
//*****************************************************************************
|
||||
// Call the const function taking an int parameter.
|
||||
//*****************************************************************************
|
||||
void call(const etl::ifunction<int>& function)
|
||||
{
|
||||
function(VALUE);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Call the const function taking a Data parameter.
|
||||
//*****************************************************************************
|
||||
void call(const etl::ifunction<const Data&>& function)
|
||||
{
|
||||
Data data;
|
||||
data.d = VALUE;
|
||||
function(data);
|
||||
}
|
||||
//*****************************************************************************
|
||||
// Call the function taking a Data parameter.
|
||||
//*****************************************************************************
|
||||
void call(etl::ifunction<const Data&>& function)
|
||||
{
|
||||
Data data;
|
||||
data.d = VALUE;
|
||||
function(data);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// The free function taking no parameters.
|
||||
//*****************************************************************************
|
||||
void free_void()
|
||||
{
|
||||
function_called = true;
|
||||
}
|
||||
//*****************************************************************************
|
||||
// Call the const function taking a Data parameter.
|
||||
//*****************************************************************************
|
||||
void call(const etl::ifunction<const Data&>& function)
|
||||
{
|
||||
Data data;
|
||||
data.d = VALUE;
|
||||
function(data);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// The free function taking an int parameter.
|
||||
//*****************************************************************************
|
||||
void free_int(int i)
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (i == VALUE);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// The free function taking a Data reference parameter.
|
||||
//*****************************************************************************
|
||||
void free_reference(const Data& data)
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (data.d == VALUE);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// The test class with member functions.
|
||||
//*****************************************************************************
|
||||
class Test
|
||||
{
|
||||
public:
|
||||
|
||||
void member_void()
|
||||
//*****************************************************************************
|
||||
// The free function taking no parameters.
|
||||
//*****************************************************************************
|
||||
void free_void()
|
||||
{
|
||||
function_called = true;
|
||||
}
|
||||
|
||||
void member_int(int i)
|
||||
//*****************************************************************************
|
||||
// The free function taking an int parameter.
|
||||
//*****************************************************************************
|
||||
void free_int(int i)
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (i == VALUE);
|
||||
}
|
||||
|
||||
void member_reference(const Data& data)
|
||||
//*****************************************************************************
|
||||
// The free function taking a Data reference parameter.
|
||||
//*****************************************************************************
|
||||
void free_reference(const Data& data)
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (data.d == VALUE);
|
||||
}
|
||||
};
|
||||
|
||||
Test test_static;
|
||||
//*****************************************************************************
|
||||
// The test class with member functions.
|
||||
//*****************************************************************************
|
||||
class Test
|
||||
{
|
||||
public:
|
||||
|
||||
void member_void()
|
||||
{
|
||||
function_called = true;
|
||||
}
|
||||
|
||||
void member_int(int i)
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (i == VALUE);
|
||||
}
|
||||
|
||||
void member_reference(const Data& data)
|
||||
{
|
||||
function_called = true;
|
||||
parameter_correct = (data.d == VALUE);
|
||||
}
|
||||
};
|
||||
|
||||
Test test_static;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Initialises the test results.
|
||||
@ -504,4 +507,4 @@ namespace
|
||||
CHECK(function_called);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -3688,6 +3688,20 @@ namespace
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_resize_down)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.resize(text.size() - 3U);
|
||||
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_erase)
|
||||
{
|
||||
|
||||
@ -3688,6 +3688,20 @@ namespace
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_resize_down)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.resize(text.size() - 3U);
|
||||
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_erase)
|
||||
{
|
||||
|
||||
@ -3688,6 +3688,20 @@ namespace
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_resize_down)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.resize(text.size() - 3U);
|
||||
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_erase)
|
||||
{
|
||||
|
||||
@ -49,9 +49,12 @@ namespace
|
||||
namespace etl
|
||||
{
|
||||
template <>
|
||||
struct etl::size_of<TestData>
|
||||
struct size_of<TestData>
|
||||
{
|
||||
static const size_t size = 20;
|
||||
enum
|
||||
{
|
||||
size = 20
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -372,6 +372,8 @@
|
||||
<ClInclude Include="..\..\include\etl\crc32_c.h" />
|
||||
<ClInclude Include="..\..\include\etl\cumulative_moving_average.h" />
|
||||
<ClInclude Include="..\..\include\etl\c\ecl_timer.h" />
|
||||
<ClInclude Include="..\..\include\etl\delegate.h" />
|
||||
<ClInclude Include="..\..\include\etl\delegate_service.h" />
|
||||
<ClInclude Include="..\..\include\etl\format_spec.h" />
|
||||
<ClInclude Include="..\..\include\etl\frame_check_sequence.h" />
|
||||
<ClInclude Include="..\..\include\etl\fsm.h" />
|
||||
@ -582,6 +584,8 @@
|
||||
<ClCompile Include="..\test_alignment.cpp" />
|
||||
<ClCompile Include="..\test_callback_service.cpp" />
|
||||
<ClCompile Include="..\test_cumulative_moving_average.cpp" />
|
||||
<ClCompile Include="..\test_delegate.cpp" />
|
||||
<ClCompile Include="..\test_delegate_service.cpp" />
|
||||
<ClCompile Include="..\test_forward_list_shared_pool.cpp" />
|
||||
<ClCompile Include="..\test_bit_stream.cpp" />
|
||||
<ClCompile Include="..\test_list_shared_pool.cpp" />
|
||||
|
||||
@ -768,6 +768,12 @@
|
||||
<ClInclude Include="..\..\include\etl\multi_array.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\delegate.h">
|
||||
<Filter>ETL\Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\delegate_service.h">
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\main.cpp">
|
||||
@ -1220,6 +1226,12 @@
|
||||
<ClCompile Include="..\test_multi_array.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_delegate.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_delegate_service.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\library.properties">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user