43template <
typename T>
struct is_function_pointer {
44 static constexpr bool value =
false;
47template <
typename R,
typename... Args>
48struct is_function_pointer<R(*)(Args...)> {
49 static constexpr bool value =
true;
70template <
typename>
class function;
72template <
typename R,
typename... Args>
80 enum class Op :
fl::u8 { Destroy, Copy, Move };
83 using Invoker = R (*)(
const void* src, Args...);
92 using Manager = void (*)(
void* dst,
void* src, Op op);
103 template <
typename R2>
104 static typename enable_if<!is_void<R2>::value, R2>::type
107 template <
typename R2>
108 static typename enable_if<is_void<R2>::value, R2>::type
111 static R null_invoker(
const void* , Args... )
FL_NO_EXCEPT {
112 return null_return_impl<R>();
114 static void null_manager(
void* ,
void* , Op )
FL_NO_EXCEPT {}
120 template <
typename Func>
124 Func* f =
static_cast<Func*
>(
static_cast<void*
>(tmp));
125 return (*f)(
args...);
131 template <fl::size N>
132 static void trivial_manager(
void* dst,
void* src, Op op)
FL_NO_EXCEPT {
145 template <
typename Func>
146 static void non_trivial_manager(
void* dst,
void* src, Op op)
FL_NO_EXCEPT {
149 Func* f =
static_cast<Func*
>(dst);
154 const Func* sf =
static_cast<const Func*
>(
static_cast<const void*
>(src));
159 Func* sf =
static_cast<Func*
>(src);
173 template <
typename Func>
177 return (*ptr)(
args...);
185 template <
typename Func>
187 using FBare =
typename remove_reference<Func>::type;
189 "Callable requires stricter alignment than SBO provides.");
191 integral_constant<
bool, (
sizeof(FBare) <= kSboSize)>{});
194 template <
typename Func>
195 void init_with_impl(Func&& f, true_type )
FL_NO_EXCEPT {
196 using FBare =
typename remove_reference<Func>::type;
198 mInvoker = &functor_invoker<FBare>;
199 mManager = is_trivially_copyable<FBare>::value
200 ? &trivial_manager<
sizeof(FBare)>
201 : &non_trivial_manager<FBare>;
205 template <
typename Func>
206 void init_with_impl(Func&& f, false_type )
FL_NO_EXCEPT {
207 using FBare =
typename remove_reference<Func>::type;
208#ifdef FL_FUNCTION_NO_HEAP_FALLBACK
214 "fl::function: capture exceeds FASTLED_INLINE_LAMBDA_SIZE "
215 "and FL_FUNCTION_NO_HEAP_FALLBACK is defined. "
216 "Either reduce the captured state, or bump "
217 "FASTLED_INLINE_LAMBDA_SIZE for this build, or "
218 "undef FL_FUNCTION_NO_HEAP_FALLBACK to re-enable "
219 "the shared_ptr-backed heap fallback.");
221 using Holder = HeapHolder<FBare>;
223 "shared_ptr too large for SBO; bump FASTLED_INLINE_LAMBDA_SIZE.");
225 mInvoker = &functor_invoker<Holder>;
228 mManager = &non_trivial_manager<Holder>;
236 mManager(mBytes,
nullptr, Op::Destroy);
239 mInvoker = &null_invoker;
240 mManager = &null_manager;
247 template <
typename C>
248 struct NonConstMemberWrapper {
252 return (obj->*mf)(
args...);
256 template <
typename C>
257 struct ConstMemberWrapper {
259 R (C::*mf)(Args...)
const;
261 return (obj->*mf)(
args...);
267 : mInvoker(&null_invoker), mManager(&null_manager), mHasValue(
false) {
275 : mInvoker(other.mInvoker), mManager(other.mManager), mHasValue(other.mHasValue) {
281 mManager(mBytes,
const_cast<char*
>(other.mBytes), Op::Copy);
287 : mInvoker(other.mInvoker), mManager(other.mManager), mHasValue(other.mHasValue) {
290 mManager(mBytes, other.mBytes, Op::Move);
297 function& operator=(
const function& other)
FL_NO_EXCEPT {
298 if (
this == &other)
return *
this;
300 mInvoker = other.mInvoker;
301 mManager = other.mManager;
302 mHasValue = other.mHasValue;
304 mManager(mBytes,
const_cast<char*
>(other.mBytes), Op::Copy);
311 if (
this == &other)
return *
this;
313 mInvoker = other.mInvoker;
314 mManager = other.mManager;
315 mHasValue = other.mHasValue;
317 mManager(mBytes, other.mBytes, Op::Move);
329 : mInvoker(&null_invoker), mManager(&null_manager), mHasValue(
false) {
338 template <
typename Func,
339 typename = enable_if_t<!is_member_function_pointer<Func>::value &&
340 !is_function_pointer<Func>::value &&
341 !is_same<typename remove_reference<Func>::type, function>::value>>
343 : mInvoker(&null_invoker), mManager(&null_manager), mHasValue(
false) {
349 template <
typename C>
351 : mInvoker(&null_invoker), mManager(&null_manager), mHasValue(
false) {
353 init_with(NonConstMemberWrapper<C>{obj, mf});
357 template <
typename C>
358 function(R (C::*mf)(Args...)
const,
const C* obj)
FL_NO_EXCEPT
359 : mInvoker(&null_invoker), mManager(&null_manager), mHasValue(
false) {
361 init_with(ConstMemberWrapper<C>{obj, mf});
365 return mInvoker(mBytes,
args...);
368 explicit operator bool()
const FL_NO_EXCEPT {
return mHasValue; }
374 return mHasValue == o.mHasValue;
377 bool operator!=(
const function& o)
const FL_NO_EXCEPT {
return !(*
this == o); }
389 "function_list requires a void returning function signature.");
394template <
typename... Args>
395class function_list<void(Args...)> {
397 using FunctionType = function<void(Args...)>;
399 struct FunctionEntry {
404 FunctionEntry()
FL_NO_EXCEPT : id(0), priority(0), fn() {}
405 FunctionEntry(
int idParam,
int priorityParam, FunctionType fnParam)
FL_NO_EXCEPT
406 : id(idParam), priority(priorityParam), fn(fnParam) {}
411 FunctionVector mFunctions;
414 bool mNeedsCompact =
false;
417 function_list()
FL_NO_EXCEPT : mFunctions(), mIdCounter(0), mNeedsCompact(
false) {}
419 : mFunctions(other.mFunctions), mIdCounter(other.mIdCounter), mNeedsCompact(other.mNeedsCompact) {}
421 : mFunctions(
fl::move(other.mFunctions)), mIdCounter(other.mIdCounter), mNeedsCompact(other.mNeedsCompact) {}
422 function_list& operator=(
const function_list& other)
FL_NO_EXCEPT {
423 if (
this != &other) {
424 mFunctions = other.mFunctions;
425 mIdCounter = other.mIdCounter;
426 mNeedsCompact = other.mNeedsCompact;
430 function_list& operator=(function_list&& other)
FL_NO_EXCEPT {
431 if (
this != &other) {
432 mFunctions =
fl::move(other.mFunctions);
433 mIdCounter = other.mIdCounter;
434 mNeedsCompact = other.mNeedsCompact;
438 ~function_list() =
default;
440 int add(function<
void(Args...)> fn,
int priority = 0)
FL_NO_EXCEPT {
441 int id = mIdCounter++;
442 mFunctions.push_back(FunctionEntry(
id, priority, fn));
448 for (
size_t i = 0; i < mFunctions.size(); ++i) {
449 if (mFunctions[i].
id ==
id) {
450 mFunctions[i].fn.clear();
451 mNeedsCompact =
true;
463 if (!mNeedsCompact)
return;
464 size_t write_pos = 0;
465 for (
size_t read_pos = 0; read_pos < mFunctions.size(); ++read_pos) {
466 if (mFunctions[read_pos].fn) {
467 if (write_pos != read_pos) {
468 mFunctions[write_pos] = mFunctions[read_pos];
473 mFunctions.resize(write_pos);
474 mNeedsCompact =
false;
480 for (
const auto& entry : mFunctions) {
490 explicit operator bool()
const FL_NO_EXCEPT {
return !empty(); }
493 if (mFunctions.empty())
return;
497 const size_t invoke_size = mFunctions.size();
499 if (invoke_size == 0) {
505 for (
size_t i = 0; i < invoke_size; ++i) {
506 if (!mFunctions[i].fn)
continue;
508 int p = mFunctions[i].priority;
510 if (priorities.
find(p) == priorities.
end()) {
519 for (
size_t p_idx = 0; p_idx < priorities.
size(); ++p_idx) {
520 int current_priority = priorities[p_idx];
521 for (
size_t i = 0; i < invoke_size; ++i) {
522 if (mFunctions.empty()) {
525 if (mFunctions[i].fn && mFunctions[i].priority == current_priority) {
526 mFunctions[i].fn(
args...);
541template <
typename R,
typename... Args>
542class function_list<R(Args...)> {
544 "function_list only supports void return type. "
545 "Use function_list<void(Args...)> instead of function_list<ReturnType(Args...)>.");