8000 Ticker with Delegate by dok-net · Pull Request #6918 · esp8266/Arduino · GitHub
[go: up one dir, main page]

Skip to content

Ticker with Delegate #6918

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 55 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
8000 55 commits
Select commit Hold shift + click to select a range
0f00454
Delegate class template.
dok-net Nov 28, 2019
4b6020c
Solves problems with lambdas and std::bind
dok-net Nov 28, 2019
4363ce9
MSVC compiler picked up missing std::forward
dok-net Nov 28, 2019
d133e30
Circular include issue fixed
dok-net Nov 29, 2019
c56fa87
Use function declaration syntax in template type specification
dok-net Nov 29, 2019
48ed02b
Use terse function notation - match std::function, the optional 1st a…
dok-net Nov 29, 2019
bc8a0e6
Performance improvement for Delegate specialization without additiona…
dok-net Dec 4, 2019
05e1811
Updated Delegate and new MultiDelegate template.
dok-net Dec 7, 2019
a5ee065
MultiDelegate template argument to switch queue/event behavior.
dok-net Dec 8, 2019
79c3816
Fix deletion of argument value caused by forwarding to Delegate.
dok-net Dec 8, 2019
edbeeab
Readied MultiDelegate for ESP32 ISR safeness.
dok-net Dec 8, 2019
cda54ff
Completed port of Delegate and MultiDelegate to Non-Arduino platforms
dok-net Dec 9, 2019
c6fb8bc
Add missing LGPL license header.
dok-net Dec 9, 2019
da5f0d4
Directly derive from std::function for DelegateImpl<void, R>, too.
dok-net Dec 10, 2019
15bbc1c
Fixed queue and event multiplexer modes (ISQUEUE template argument) f…
dok-net Dec 11, 2019
e1c3d22
Signed-unsigned mismatch caught by ESP2866 Arduino CI.
dok-net Dec 12, 2019
534d016
Performance and ease of use, more comprehensible ctor and operator=: …
dok-net Dec 13, 2019
ee86f2e
Interface full lockdown: mark implementation details private instead …
dok-net Dec 14, 2019
0db6c95
For use of Delegate as callback in functions that take C-fun ptr and …
dok-net Dec 15, 2019
c5d738c
Optimize casting to fun ptr and argument for "attachInterruptArg"-lik…
dok-net Dec 16, 2019
18f497e
Bug fix: must reinterpret_cast for R() as R(void*) cast (extra argume…
dok-net Dec 16, 2019
e6e60e7
using operator= is required to suppress auto generation.
dok-net Dec 17, 2019
d855cbd
Delegate to fptr helpers must be in IRAM
dok-net Dec 17, 2019
6b3e87b
Delegate refactoring for same ordering of member functions between sp…
dok-net Dec 20, 2019
af76e5f
Bug fix Delegate, custom type converter.
dok-net Dec 22, 2019
2b4a08d
Use explicit initialization in ctor for kind member.
dok-net Dec 23, 2019
c19456c
Fix ctor overloads competing with ctor templates.
dok-net Dec 23, 2019
6bac522
Assignment operator template caused ambiguity error in MSVC build - d…
dok-net Dec 24, 2019
ae7b4f6
Delegate template programming for > 3 platforms is interesting.
dok-net Jan 18, 2020
c25965d
unsigned/int instead of (u)int32_t gives lower memory footprint on 8b…
dok-net Jan 17, 2020
188c3f0
Refactor uses of unsigned for buffer sizes and item counts to size_t.
dok-net Jan 19, 2020
07e52a1
It was found that internal linkage suppresses the effect of the IRAM_…
dok-net Jan 21, 2020
e78885c
std::bind is IRAM cache save, lambda is not.
dok-net Jan 22, 2020
e3888ca
Enhancements to MultiDelegate: event multiplexer mode no longer has a…
dok-net Feb 12, 2020
680abe1
Added forward iterator and begin() and end() functions to MultiDelegate.
dok-net Feb 12, 2020
1f193ab
Change to make MultiDelegate invoke and erase work off iterators.
dok-net Feb 13, 2020
57a87ca
Constness fix for iterator dereference
dok-net Feb 13, 2020
960c8f5
constness on return type warning fix.
dok-net Feb 13, 2020
3cd6b91
Conform to C++ 17 and later.
dok-net Feb 25, 2020
64b06ec
Resolve g++ 9's c++17 deprecation warnings.
dok-net Feb 25, 2020
3b7f2c7
gcc 9.2 is very strict about template inheritance of ctor and assignm…
dok-net Feb 28, 2020
6e17563
Fix both ambiguous operator= and infinite ctor recursion.
dok-net Mar 1, 2020
df02bac
don't cast to rvalue ref if also move'ing
dok-net Mar 23, 2020
81ceebd
Add assignment operators.
dok-net Jan 4, 2021
4fa0dbb
Example as performance test for Delegate vs. std::function
dok-net Jan 27, 2021
6b6dbee
Revert "Add assignment operators."
dok-net Jan 27, 2021
099fc86
Re-apply std::forwards and minor identifier rename.
dok-net Jan 27, 2021
0fd063c
More hints for proper use of Delegate to optimize performance.
dok-net Jan 27, 2021
66d1704
Apply astyle
dok-net Jan 27, 2021
6aa1102
Added preprocessor define NODELEGATE. Use it for side-by-side compari…
dok-net Jan 28, 2021
9644606
Field padding improved
dok-net Jan 30, 2021
8e75ef9
Remove the now-deprecated ICACHE_RAM_ATTR.
dok-net Mar 15, 2021
12c27a4
Ticker ported to Delegate
dok-net Dec 17, 2019
c55ffe6
std::bind is IRAM cache safe, but lambdas are not.
dok-net Jan 22, 2020
1878d6f
Review has proven that Ticker callbacks are documented to occur in SY…
dok-net Apr 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fixed queue and event multiplexer modes (ISQUEUE template argument) f…
…or performance.

Added documentation to the MultiDelegate class template.
  • Loading branch information
dok-net committed Jun 28, 2021
commit 15bbc1c9b5c78d3edab11b0b294ee1a81c80f502
86 changes: 60 additions & 26 deletions cores/esp8266/MultiDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ namespace detail
};
};

template< typename Delegate, typename R = void, bool ISQUEUE = false, uint32_t MULTICALLBACK_MAX_COUNT = 32, typename... P>
template< typename Delegate, typename R = void, bool ISQUEUE = false, uint32_t QUEUE_CAPACITY = 32, typename... P>
class MultiDelegatePImpl
{
public:
Expand Down Expand Up @@ -191,7 +191,7 @@ namespace detail
unused = unused->mNext;
}
// if no unused items, and count not too high, allocate a new one
else if (nodeCount < MULTICALLBACK_MAX_COUNT)
else if (nodeCount < QUEUE_CAPACITY)
{
#if defined(ESP8266) || defined(ESP32)
result = new (std::nothrow) Node_t;
Expand Down Expand Up @@ -231,7 +231,12 @@ namespace detail
std::lock_guard<std::mutex> lock(mutex_unused);
#endif

Node_t* item = get_node_unsafe();
Node_t* item = ISQUEUE ? get_node_unsafe() :
#if defined(ESP8266) || defined(ESP32)
new (std::nothrow) Node_t;
#else
new Node_t;
#endif
if (!item)
return nullptr;

Expand Down Expand Up @@ -281,7 +286,10 @@ namespace detail
first = current;
}

recycle_node_unsafe(to_recycle);
if (ISQUEUE)
recycle_node_unsafe(to_recycle);
else
delete to_recycle;
return true;
}
else
Expand Down Expand Up @@ -341,7 +349,10 @@ namespace detail
first = current;
}

recycle_node_unsafe(to_recycle);
if (ISQUEUE)
recycle_node_unsafe(to_recycle);
else
delete to_recycle;
}
else
{
Expand All @@ -359,22 +370,22 @@ namespace detail
}
};

template< typename Delegate, typename R = void, bool ISQUEUE = false, uint32_t MULTICALLBACK_MAX_COUNT = 32>
class MultiDelegateImpl : public MultiDelegatePImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT>
template< typename Delegate, typename R = void, bool ISQUEUE = false, uint32_t QUEUE_CAPACITY = 32>
class MultiDelegateImpl : public MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>
{
protected:
using typename MultiDelegatePImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT>::Node_t;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT>::first;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT>::last;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT>::unused;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT>::nodeCount;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT>::recycle_node_unsafe;
using typename MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::Node_t;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::first;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::last;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::unused;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::nodeCount;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::recycle_node_unsafe;
#ifndef ARDUINO
using MultiDelegatePImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT>::mutex_unused;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::mutex_unused;
#endif

public:
using MultiDelegatePImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT>::MultiDelegatePImpl;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::MultiDelegatePImpl;

void operator()()
{
Expand Down Expand Up @@ -424,7 +435,10 @@ namespace detail
first = current;
}

recycle_node_unsafe(to_recycle);
if (ISQUEUE)
recycle_node_unsafe(to_recycle);
else
delete to_recycle;
}
else
{
Expand All @@ -442,28 +456,48 @@ namespace detail
}
};

template< typename Delegate, typename R, bool ISQUEUE, uint32_t MULTICALLBACK_MAX_COUNT, typename... P> class MultiDelegate;
template< typename Delegate, typename R, bool ISQUEUE, uint32_t QUEUE_CAPACITY, typename... P> class MultiDelegate;

template< typename Delegate, typename R, bool ISQUEUE, uint32_t MULTICALLBACK_MAX_COUNT, typename... P>
class MultiDelegate<Delegate, R(P...), ISQUEUE, MULTICALLBACK_MAX_COUNT> : public MultiDelegatePImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT, P...>
template< typename Delegate, typename R, bool ISQUEUE, uint32_t QUEUE_CAPACITY, typename... P>
class MultiDelegate<Delegate, R(P...), ISQUEUE, QUEUE_CAPACITY> : public MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY, P...>
{
public:
using MultiDelegatePImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT, P...>::MultiDelegatePImpl;
using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY, P...>::MultiDelegatePImpl;
};

template< typename Delegate, typename R, bool ISQUEUE, uint32_t MULTICALLBACK_MAX_COUNT>
class MultiDelegate<Delegate, R(), ISQUEUE, MULTICALLBACK_MAX_COUNT> : public MultiDelegateImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT>
template< typename Delegate, typename R, bool ISQUEUE, uint32_t QUEUE_CAPACITY>
class MultiDelegate<Delegate, R(), ISQUEUE, QUEUE_CAPACITY> : public MultiDelegateImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>
{
public:
using MultiDelegateImpl<Delegate, R, ISQUEUE, MULTICALLBACK_MAX_COUNT>::MultiDelegateImpl;
using MultiDelegateImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::MultiDelegateImpl;
};
};

template< typename Delegate, bool ISQUEUE = false, uint32_t MULTICALLBACK_MAX_COUNT = 32>
class MultiDelegate : public detail::MultiDelegate<Delegate, typename Delegate::target_type, ISQUEUE, MULTICALLBACK_MAX_COUNT>
/**
The MultiDelegate class template can be specialized to either a queue or an event multiplexer.
It is designed to be used with Delegate, the efficient runtime wrapper for C function ptr and C++ std::function.
@tparam Delegate specifies the concrete type that MultiDelegate bases the queue or event multiplexer on.
@tparam ISQUEUE modifies the generated MultiDelegate class in subtle ways. In queue mode (ISQUEUE == true),
the value of QUEUE_CAPACITY enforces the maximum number of simultaneous items the queue can contain.
This is exploited to minimize the use of new and delete by reusing already allocated items, thus
reducing heap fragmentation. In event multiplexer mode (ISQUEUE = false), new and delete are
used for allocation of the event handler items.
If the result type of the function call operator of Delegate is void, calling a MultiDelegate queue
removes each item after calling it; a Multidelegate event multiplexer keeps event handlers until
explicitly removed.
If the result type of the function call operator of Delegate is non-void, the type-conversion to bool
of that result determines if the item is immediately removed or kept after each call: a Multidelegate
queue removes an item only if true is returned, but a Multidelegate event multiplexer removes event
handlers that return false.
@tparam QUEUE_CAPACITY is only used if ISQUEUE == true. Then, it sets the maximum capacity that the queue dynamically
allocates from the heap. Unused items are not returned to the heap, but are managed by the MultiDelegate
instance during its own lifetime for efficiency.
*/
template< typename Delegate, bool ISQUEUE = false, uint32_t QUEUE_CAPACITY = 32>
class MultiDelegate : public detail::MultiDelegate<Delegate, typename Delegate::target_type, ISQUEUE, QUEUE_CAPACITY>
{
public:
using detail::MultiDelegate<Delegate, typename Delegate::target_type, ISQUEUE, MULTICALLBACK_MAX_COUNT>::MultiDelegate;
using detail::MultiDelegate<Delegate, typename Delegate::target_type, ISQUEUE, QUEUE_CAPACITY>::MultiDelegate;
};

#endif // __MULTIDELEGATE_H
0