Corium 1.1.0
High-Performance Zero-Heap C++20 MPSC Application Runtime
Loading...
Searching...
No Matches
ApplicationContext.hpp
Go to the documentation of this file.
1
7#pragma once
8
9#include <array>
10#include <chrono>
11#include <cstddef>
12#include <type_traits>
13#include <utility>
14#include <variant>
15
16#include "corium/Events.hpp"
17#include "corium/EventSink.hpp"
24
25namespace corium {
26
31template <typename EventVariant = DefaultEvents>
33 static constexpr std::size_t NumEvents = std::variant_size_v<EventVariant>;
34
35 using RegFn = bool (*)(
36 void* busPtr,
37 void* handlerObj,
38 void* invokerFn,
39 void (*mover)(void* destStorage, void*& destInstance, void*& srcInstance) noexcept,
40 void (*destroyer)(void* instance) noexcept,
41 std::size_t size
42 );
43
44public:
45 using EventVariantType = EventVariant;
46
47 using ScheduleDelayedFn = TimerId (*)(void* ptr, EventVariant event, std::chrono::microseconds delay, EventPriority priority);
48 using SchedulePeriodicFn = TimerId (*)(void* ptr, EventVariant event, std::chrono::microseconds interval, EventPriority priority);
49 using CancelTimerFn = bool (*)(void* ptr, TimerId id);
50
51 ApplicationContext() = default;
52
53 template <typename EventBusType>
54 ApplicationContext(EventBusType& events, StaticCallback quitCallback)
55 : _busPtr(&events), _eventSink(events.sink()), _quitCallback(quitCallback)
56 {
57 initRegFns<EventBusType>(std::make_index_sequence<NumEvents>{});
58 }
59
60 template <typename Scheduler>
61 void setTimerScheduler(Scheduler& scheduler) noexcept
62 {
63 _timerSchedulerPtr = &scheduler;
64 _scheduleDelayedFn = [](void* ptr, EventVariant evt, std::chrono::microseconds delay, EventPriority prio) {
65 return static_cast<Scheduler*>(ptr)->scheduleDelayed(std::move(evt), delay, prio);
66 };
67 _schedulePeriodicFn = [](void* ptr, EventVariant evt, std::chrono::microseconds interval, EventPriority prio) {
68 return static_cast<Scheduler*>(ptr)->schedulePeriodic(std::move(evt), interval, prio);
69 };
70 _cancelTimerFn = [](void* ptr, TimerId id) {
71 return static_cast<Scheduler*>(ptr)->cancelTimer(id);
72 };
73 }
74
76 template <typename Handler>
77 bool registerHandler(Handler&& handler)
78 {
79 using EventType = callable_event_type_t<Handler>;
80 static_assert(has_variant_type_v<EventType, EventVariant>, "EventType is not part of Application's EventVariant list!");
81 constexpr std::size_t typeIdx = variant_index_v<EventType, EventVariant>;
82
83 if (_busPtr && _regFns[typeIdx]) {
84 using Decayed = std::decay_t<Handler>;
85 Decayed h(std::forward<Handler>(handler));
86
87 void (*invoker)(void* instance, const EventType& event) = [](void* instance, const EventType& event) {
88 (*static_cast<Decayed*>(instance))(event);
89 };
90
91 auto mover = [](void* destStorage, void*& destInstance, void*& srcInstance) noexcept {
92 auto* src = static_cast<Decayed*>(srcInstance);
93 ::new (destStorage) Decayed(std::move(*src));
94 src->~Decayed();
95 destInstance = destStorage;
96 srcInstance = nullptr;
97 };
98
99 auto destroyer = [](void* instance) noexcept {
100 static_cast<Decayed*>(instance)->~Decayed();
101 };
102
103 void* srcPtr = &h;
104 return _regFns[typeIdx](_busPtr, srcPtr, reinterpret_cast<void*>(invoker), mover, destroyer, sizeof(Decayed));
105 }
106 return false;
107 }
108
112 template <typename Filter, typename Handler>
113 bool registerFilteredHandler(Filter&& filter, Handler&& handler)
114 {
115 using EventType = callable_event_type_t<Handler>;
116 return registerHandler([f = std::forward<Filter>(filter), h = std::forward<Handler>(handler)](const EventType& event) {
117 if (f(event)) {
118 h(event);
119 }
120 });
121 }
122
124 [[nodiscard]] EventSinkT<EventVariant> eventSink() const noexcept
125 {
126 return _eventSink;
127 }
128
130 template <typename Rep, typename Period>
131 [[nodiscard]] TimerId scheduleDelayed(EventVariant event, const std::chrono::duration<Rep, Period>& delay, EventPriority priority = EventPriority::Normal) const
132 {
133 if (_scheduleDelayedFn && _timerSchedulerPtr) {
134 return _scheduleDelayedFn(_timerSchedulerPtr, std::move(event), std::chrono::duration_cast<std::chrono::microseconds>(delay), priority);
135 }
136 return INVALID_TIMER_ID;
137 }
138
140 template <typename Rep, typename Period>
141 [[nodiscard]] TimerId schedulePeriodic(EventVariant event, const std::chrono::duration<Rep, Period>& interval, EventPriority priority = EventPriority::Normal) const
142 {
143 if (_schedulePeriodicFn && _timerSchedulerPtr) {
144 return _schedulePeriodicFn(_timerSchedulerPtr, std::move(event), std::chrono::duration_cast<std::chrono::microseconds>(interval), priority);
145 }
146 return INVALID_TIMER_ID;
147 }
148
150 [[nodiscard]] bool cancelTimer(TimerId id) const noexcept
151 {
152 if (_cancelTimerFn && _timerSchedulerPtr) {
153 return _cancelTimerFn(_timerSchedulerPtr, id);
154 }
155 return false;
156 }
157
159 void requestQuit() const
160 {
161 if (_quitCallback) {
162 _quitCallback();
163 }
164 }
165
167 void setRuntimeDetach(void* runtimePtr, void (*detachFn)(void*) noexcept) noexcept
168 {
169 _runtimePtr = runtimePtr;
170 _detachFn = detachFn;
171 }
172
174 void detachFromRuntime() noexcept
175 {
176 if (_detachFn && _runtimePtr) {
177 _detachFn(_runtimePtr);
178 _detachFn = nullptr;
179 _runtimePtr = nullptr;
180 }
181 }
182
184 void reset() noexcept
185 {
186 _busPtr = nullptr;
187 _runtimePtr = nullptr;
188 _detachFn = nullptr;
189 _timerSchedulerPtr = nullptr;
190 _scheduleDelayedFn = nullptr;
191 _schedulePeriodicFn = nullptr;
192 _cancelTimerFn = nullptr;
193 _quitCallback = StaticCallback{};
194 }
195
196 explicit operator bool() const noexcept
197 {
198 return _busPtr != nullptr;
199 }
200
201private:
202 template <typename EventBusType, std::size_t... Is>
203 void initRegFns(std::index_sequence<Is...>) noexcept
204 {
205 ((_regFns[Is] = [](
206 void* bPtr,
207 void* handlerObj,
208 void* invokerFn,
209 void (*mover)(void* destStorage, void*& destInstance, void*& srcInstance) noexcept,
210 void (*destroyer)(void* instance) noexcept,
211 std::size_t size
212 ) -> bool {
213 using EventType = std::variant_alternative_t<Is, EventVariant>;
214 using StoragePolicy = typename EventBusType::ReactorType::StoragePolicyType;
215 constexpr std::size_t InlineSize = StoragePolicy::inline_storage_size;
216
217 if (size > InlineSize) {
218 return false;
219 }
220
221 auto* bus = static_cast<EventBusType*>(bPtr);
222 auto stub = reinterpret_cast<void (*)(void*, const EventType&)>(invokerFn);
223
224 EventHandlerDelegate<EventType, InlineSize> del(handlerObj, stub, mover, destroyer);
225 return bus->template registerHandler<EventType>(std::move(del));
226 }), ...);
227 }
228
229 void* _busPtr = nullptr;
230 EventSinkT<EventVariant> _eventSink{};
231 StaticCallback _quitCallback{};
232 std::array<RegFn, NumEvents> _regFns{};
233
234 void* _timerSchedulerPtr = nullptr;
235 ScheduleDelayedFn _scheduleDelayedFn = nullptr;
236 SchedulePeriodicFn _schedulePeriodicFn = nullptr;
237 CancelTimerFn _cancelTimerFn = nullptr;
238
239 void* _runtimePtr = nullptr;
240 void (*_detachFn)(void*) noexcept = nullptr;
241};
242
243} // namespace corium
Compile-time introspection traits for callable objects and event handlers.
Non-allocating type-erased fat pointer handle for lock-free event posting.
Standard lifecycle events (QuitEvent, ErrorEvent, TimerEvent).
Zero-allocating Small Buffer Optimized (SBO) static delegate dispatcher.
Bounded and multi-tier priority MPSC queueing policies.
Thread wake-up policies (NoSignalPolicy, ConditionVariableSignalPolicy).
Fixed-capacity static timer scheduler for delayed and periodic events.
Compile-time type index resolution for std::variant alternative types.
Context object passed to Application providing event registration, sink access, quit requests,...
Definition ApplicationContext.hpp:32
void setTimerScheduler(Scheduler &scheduler) noexcept
Definition ApplicationContext.hpp:61
bool(*)(void *ptr, TimerId id) CancelTimerFn
Definition ApplicationContext.hpp:49
EventVariant EventVariantType
Definition ApplicationContext.hpp:45
bool registerFilteredHandler(Filter &&filter, Handler &&handler)
Register a filtered event handler executed only when predicate evaluates to true.
Definition ApplicationContext.hpp:113
TimerId(*)(void *ptr, EventVariant event, std::chrono::microseconds delay, EventPriority priority) ScheduleDelayedFn
Definition ApplicationContext.hpp:47
TimerId schedulePeriodic(EventVariant event, const std::chrono::duration< Rep, Period > &interval, EventPriority priority=EventPriority::Normal) const
Schedule a recurring periodic event with std::chrono duration.
Definition ApplicationContext.hpp:141
ApplicationContext(EventBusType &events, StaticCallback quitCallback)
Definition ApplicationContext.hpp:54
void setRuntimeDetach(void *runtimePtr, void(*detachFn)(void *) noexcept) noexcept
Attach runtime detachment handle.
Definition ApplicationContext.hpp:167
void reset() noexcept
Reset context state to empty.
Definition ApplicationContext.hpp:184
bool registerHandler(Handler &&handler)
Register an event handler into the application event bus.
Definition ApplicationContext.hpp:77
EventSinkT< EventVariant > eventSink() const noexcept
Access event sink handle.
Definition ApplicationContext.hpp:124
TimerId(*)(void *ptr, EventVariant event, std::chrono::microseconds interval, EventPriority priority) SchedulePeriodicFn
Definition ApplicationContext.hpp:48
bool cancelTimer(TimerId id) const noexcept
Cancel an active timer.
Definition ApplicationContext.hpp:150
TimerId scheduleDelayed(EventVariant event, const std::chrono::duration< Rep, Period > &delay, EventPriority priority=EventPriority::Normal) const
Schedule a single-shot delayed event with std::chrono duration.
Definition ApplicationContext.hpp:131
void requestQuit() const
Request graceful application exit.
Definition ApplicationContext.hpp:159
void detachFromRuntime() noexcept
Detach application from runtime to prevent dangling callbacks on shutdown.
Definition ApplicationContext.hpp:174
Definition Application.hpp:16
EventPriority
Event priority levels for multi-priority queue policies.
Definition QueuePolicies.hpp:32
uint32_t TimerId
Definition TimerScheduler.hpp:22
constexpr TimerId INVALID_TIMER_ID
Definition TimerScheduler.hpp:23
Lightweight non-allocating static callback wrapper (function pointer + optional context argument).
Definition SignalPolicies.hpp:35