2023-10-24 23:22:47 +03:00

107 lines
2.1 KiB
C++

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