From 80a4f39f7b2df6a70b78b37adfc1070e0b1eeb9d Mon Sep 17 00:00:00 2001 From: erki Date: Tue, 24 Oct 2023 20:31:03 +0300 Subject: [PATCH] cpptick - reorganie files --- CppTick/Inc/cpptick/argstore.hpp | 117 +++++++++++++++ CppTick/Inc/cpptick/cpptick.hpp | 234 +----------------------------- CppTick/Inc/cpptick/scheduler.hpp | 45 ++++++ CppTick/Inc/cpptick/slot.hpp | 106 ++++++++++++++ Tests/cpptick.cpp | 2 +- 5 files changed, 273 insertions(+), 231 deletions(-) create mode 100644 CppTick/Inc/cpptick/argstore.hpp create mode 100644 CppTick/Inc/cpptick/scheduler.hpp create mode 100644 CppTick/Inc/cpptick/slot.hpp diff --git a/CppTick/Inc/cpptick/argstore.hpp b/CppTick/Inc/cpptick/argstore.hpp new file mode 100644 index 0000000..9290b45 --- /dev/null +++ b/CppTick/Inc/cpptick/argstore.hpp @@ -0,0 +1,117 @@ +// +// Created by erki on 24/10/23. +// + +#pragma once + +#include +#include +#include + +namespace cpptick +{ + +template +concept TrivialClass = std::is_trivial_v && std::is_trivially_destructible_v; + +template +concept CopyableClass = !TrivialClass && std::copy_constructible; + +template +concept SlotArgument = TrivialClass || CopyableClass; + +struct ArgStorage +{ + std::array buffer; + std::array pointer_buffer; + std::array::iterator pointer_buffer_head; + std::size_t space_remaining; + + ArgStorage() = default; + ArgStorage(const ArgStorage&) = default; + ArgStorage(ArgStorage&&) = default; + + void reset() + { + space_remaining = buffer.size(); + pointer_buffer_head = pointer_buffer.begin(); + *pointer_buffer_head = buffer.data(); + } + + template + void pushArg(T&& arg) + { + if (pointer_buffer_head == pointer_buffer.end() || space_remaining == 0) + std::exit(1); + + void* memory_location = *pointer_buffer_head; + + if (std::align(alignof(T), sizeof(T), memory_location, space_remaining) == nullptr) + std::exit(2); + + std::memcpy(memory_location, &arg, sizeof(T)); + pointer_buffer_head++; + if (pointer_buffer_head != pointer_buffer.end()) + { + *pointer_buffer_head = (char*)memory_location + sizeof(T); + space_remaining -= sizeof(T); + } + } + + template + void pushArg(T&& arg) + { + if (pointer_buffer_head == pointer_buffer.end() || space_remaining == 0) + std::exit(1); + + void* memory_location = *pointer_buffer_head; + + if (std::align(alignof(T), sizeof(T), memory_location, space_remaining) == nullptr) + std::exit(2); + + new (memory_location) T{arg}; + pointer_buffer_head++; + if (pointer_buffer_head != pointer_buffer.end()) + { + *pointer_buffer_head = (char*)memory_location + sizeof(T); + space_remaining -= sizeof(T); + } + } + + template + void cleanUp(const std::size_t) + { } + + template + void cleanUp(const std::size_t index) + { + T* item = reinterpret_cast(pointer_buffer[index]); + item->~T(); + } + + template + void cleanUp(std::index_sequence) + { + (cleanUp(Is), ...); + } + + template + void cleanUp() + { + cleanUp(std::make_index_sequence{}); + } + + template + T& at(const std::size_t idx) + { + return *((T*)pointer_buffer[idx]); + } + + template + const T& at(const std::size_t idx) const + { + return *((T*)pointer_buffer[idx]); + } +}; + +} diff --git a/CppTick/Inc/cpptick/cpptick.hpp b/CppTick/Inc/cpptick/cpptick.hpp index 27a6bec..5e5bb24 100644 --- a/CppTick/Inc/cpptick/cpptick.hpp +++ b/CppTick/Inc/cpptick/cpptick.hpp @@ -1,235 +1,9 @@ // -// Created by erki on 12/09/23. +// Created by erki on 24/10/23. // #pragma once -#include -#include -#include -#include - -#include -#include - -namespace cpptick -{ - -template -concept TrivialClass = std::is_trivial_v && std::is_trivially_destructible_v; - -template -concept CopyableClass = !TrivialClass && std::copy_constructible; - -template -concept SlotArgument = TrivialClass || CopyableClass; - -struct ArgStorage -{ - std::array buffer; - std::array pointer_buffer; - std::array::iterator pointer_buffer_head; - std::size_t space_remaining; - - ArgStorage() = default; - ArgStorage(const ArgStorage&) = default; - ArgStorage(ArgStorage&&) = default; - - void reset() - { - space_remaining = buffer.size(); - pointer_buffer_head = pointer_buffer.begin(); - *pointer_buffer_head = buffer.data(); - } - - template - void pushArg(T&& arg) - { - if (pointer_buffer_head == pointer_buffer.end() || space_remaining == 0) - std::exit(1); - - void* memory_location = *pointer_buffer_head; - - if (std::align(alignof(T), sizeof(T), memory_location, space_remaining) == nullptr) - std::exit(2); - - std::memcpy(memory_location, &arg, sizeof(T)); - pointer_buffer_head++; - if (pointer_buffer_head != pointer_buffer.end()) - { - *pointer_buffer_head = (char*)memory_location + sizeof(T); - space_remaining -= sizeof(T); - } - } - - template - void pushArg(T&& arg) - { - if (pointer_buffer_head == pointer_buffer.end() || space_remaining == 0) - std::exit(1); - - void* memory_location = *pointer_buffer_head; - - if (std::align(alignof(T), sizeof(T), memory_location, space_remaining) == nullptr) - std::exit(2); - - new (memory_location) T{arg}; - pointer_buffer_head++; - if (pointer_buffer_head != pointer_buffer.end()) - { - *pointer_buffer_head = (char*)memory_location + sizeof(T); - space_remaining -= sizeof(T); - } - } - - template - void cleanUp(const std::size_t) - { } - - template - void cleanUp(const std::size_t index) - { - T* item = reinterpret_cast(pointer_buffer[index]); - item->~T(); - } - - template - void cleanUp(std::index_sequence) - { - (cleanUp(Is), ...); - } - - template - void cleanUp() - { - cleanUp(std::make_index_sequence{}); - } - - template - T& at(const std::size_t idx) - { - return *((T*)pointer_buffer[idx]); - } - - template - const T& at(const std::size_t idx) const - { - return *((T*)pointer_buffer[idx]); - } -}; - -struct Scheduler -{ - using StoredCall = std::pair*, ArgStorage>; - Utility::Ringbuffer stored_calls; - - void tick() - { - if (!stored_calls.empty()) - { - auto* f = stored_calls.begin()->first; - auto& args = stored_calls.begin()->second; - (*f)(args); - stored_calls.pop_front(); - } - } - - ArgStorage& storeCall(Utility::IFunction* call) - { - // @todo: handle overflow... - - // still constructs double. - stored_calls.emplace_back(call, ArgStorage{}); - auto& storage = stored_calls.back().second; - storage.reset(); - return storage; - } -}; - -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)), ...); - } -}; - -} +#include "cpptick/argstore.hpp" +#include "cpptick/scheduler.hpp" +#include "cpptick/slot.hpp" diff --git a/CppTick/Inc/cpptick/scheduler.hpp b/CppTick/Inc/cpptick/scheduler.hpp new file mode 100644 index 0000000..0684e4d --- /dev/null +++ b/CppTick/Inc/cpptick/scheduler.hpp @@ -0,0 +1,45 @@ +// +// Created by erki on 24/10/23. +// + +#pragma once + +#include +#include +#include + +#include "cpptick/argstore.hpp" + +namespace cpptick +{ + +struct Scheduler +{ + using StoredCall = std::pair*, ArgStorage>; + Utility::Ringbuffer stored_calls; + + void tick() + { + if (!stored_calls.empty()) + { + auto* f = stored_calls.begin()->first; + auto& args = stored_calls.begin()->second; + (*f)(args); + stored_calls.pop_front(); + } + } + + ArgStorage& storeCall(Utility::IFunction* call) + { + // @todo: handle overflow... + + // still constructs double. + stored_calls.emplace_back(call, ArgStorage{}); + auto& storage = stored_calls.back().second; + storage.reset(); + return storage; + } +}; + +} + diff --git a/CppTick/Inc/cpptick/slot.hpp b/CppTick/Inc/cpptick/slot.hpp new file mode 100644 index 0000000..cb19702 --- /dev/null +++ b/CppTick/Inc/cpptick/slot.hpp @@ -0,0 +1,106 @@ +// +// 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)), ...); + } +}; + +} diff --git a/Tests/cpptick.cpp b/Tests/cpptick.cpp index 2a45187..4270547 100644 --- a/Tests/cpptick.cpp +++ b/Tests/cpptick.cpp @@ -4,7 +4,7 @@ #include -#include +#include "cpptick/cpptick.hpp" namespace {