// // Created by erki on 12/09/23. // #pragma once #include #include #include #include #include #include "cpptick/argstore.hpp" #include "cpptick/scheduler.hpp" namespace cpptick { template struct Slot; template struct Slot { std::array*, 12> signals; Scheduler* scheduler; Utility::FunctionOwned, void (ArgStorage&)> invoke_ptr; Slot() = delete; explicit Slot(Scheduler* sched) : scheduler(sched) , invoke_ptr(*this, &Slot::callUp) { signals.fill(nullptr); } Slot(const Slot&) = delete; Slot(Slot&&) = delete; Slot& operator=(const Slot&) = delete; Slot& operator=(Slot&&) = delete; void connect(Utility::IFunction* signal) { for (auto*& callable : signals) { if (callable == nullptr) { callable = signal; break; } } } Utility::IFunction* connect(R (*func)(Args...)) { auto* f = new Utility::Function(func); connect(f); return f; } template Utility::IFunction* connect(Source& src, R (Source::* func)(Args...)) { auto* f = new Utility::FunctionOwned(src, func); connect(f); return f; } template void callUpFunction(Utility::IFunction* func, ArgStorage& args, std::index_sequence) { (*func)(std::forward(args.at(Is))...); } void callUpFunction(Utility::IFunction* func, ArgStorage& args) { callUpFunction(func, args, std::make_index_sequence{}); } void callUp(ArgStorage& args) { for (auto* f : signals) { if (f) callUpFunction(f, args); else break; } args.cleanUp(); } void invoke(Args... args) { ArgStorage& storage = scheduler->storeCall(&invoke_ptr); (storage.pushArg(std::forward(args)), ...); } }; }