rotor_light
real-time C++ actor micro-framework for embedded systems, supervisable
planner.hpp
1// SPDX-License-Identifier: MIT
2// SPDX-FileCopyrightText: 2022 Ivan Baidakou
3
4#pragma once
5
6#include "definitions.hpp"
7#include "rotor-light-bsp.h"
8#include <cstddef>
9#include <type_traits>
10
11namespace rotor_light {
12
15struct TimeEvent {
16 TimeEvent() = default;
17 TimeEvent(TimeEvent &&) = delete;
18 TimeEvent(const TimeEvent &) = delete;
19
21 TimeEvent &operator=(const TimeEvent &other) = default;
22
24 Callback callback = nullptr;
25
27 void *data;
28
30 TimePoint when = 0;
31
33 EventId event_id = 0;
34};
35
36struct PlannerBase;
37
42 void call_next();
43
45 operator bool() const;
46
48
49private:
50 friend struct PlannerBase;
51 EventConsumer(TimePoint deadline, PlannerBase *watchdog);
52 TimePoint deadline;
53 PlannerBase *watchdog;
54 int32_t index;
55};
56
61 PlannerBase(TimeEvent *events, int32_t events_count);
62 PlannerBase(const PlannerBase &) = delete;
63 PlannerBase(PlannerBase &&) = delete;
64
72 template <typename Ctx>
73 EventId add_event(TimePoint when, Callback callback, void *data) {
74 if constexpr (std::is_same_v<Ctx, ctx::thread>) {
75 ROTOR_LIGHT_DISABLE_INTERRUPTS();
76 }
77 EventId r;
78 if (last_event + 1 >= events_count) {
79 r = 0;
80 } else {
81
82 EventId future_id = next_id + 1;
83 bool recheck = false;
84 int i = last_event + 1;
85 // find the insertion point (skip previous events)
86 for (int j = 0; j <= last_event; ++j) {
87 auto &event = events[j];
88 if (event.event_id == future_id) {
89 ++future_id;
90 recheck = true;
91 }
92 if (event.when <= when) {
93 continue;
94 } else {
95 i = j;
96 }
97 }
98 while (recheck || !future_id) {
99 recheck = false;
100 if (!future_id) {
101 ++future_id;
102 }
103 for (int j = 0; j <= last_event; ++j) {
104 auto &event = events[j];
105 if (event.event_id == future_id) {
106 ++future_id;
107 recheck = true;
108 break;
109 }
110 }
111 }
112 // copy next events into the next position
113 for (int j = last_event; j >= i; --j) {
114 events[j + 1] = events[j];
115 }
116 events[i] = TimeEvent{callback, data, when, next_id};
117 next_id = future_id;
118 ++last_event;
119 r = events[i].event_id;
120 }
121
122 if constexpr (std::is_same_v<Ctx, ctx::thread>) {
123 ROTOR_LIGHT_ENABLE_INTERRUPTS();
124 }
125 return r;
126 }
127
129 void remove_event(EventId event_id);
130
132 EventConsumer consume(TimePoint deadline);
133
135 TimePoint next_event();
136
137private:
138 friend struct EventConsumer;
139 void commit(size_t index);
140 TimeEvent *events;
141 int32_t events_count;
142 int32_t last_event;
143 EventId next_id;
144};
145
148template <size_t TimeEventsCount> struct Planner : PlannerBase {
149 static_assert(TimeEventsCount > 0, "at least one event have to be allocated");
150 Planner() : PlannerBase(events_holder, TimeEventsCount) {}
151
153 TimeEvent events_holder[TimeEventsCount];
154};
155
156} // namespace rotor_light
iterator-like struct over expired time events
Definition: planner.hpp:40
bookeeper of future events
Definition: planner.hpp:59
void remove_event(EventId event_id)
PlannerBase(TimeEvent *events, int32_t events_count)
EventId add_event(TimePoint when, Callback callback, void *data)
records the new event
Definition: planner.hpp:73
EventConsumer consume(TimePoint deadline)
bookeeper of future events, templated for fixed amount of events
Definition: planner.hpp:148
TimeEvent events_holder[TimeEventsCount]
Definition: planner.hpp:153
links together callback, data, timepoint and event id
Definition: planner.hpp:15
TimeEvent & operator=(const TimeEvent &other)=default
void * data
Definition: planner.hpp:27
EventId event_id
Definition: planner.hpp:33
Callback callback
Definition: planner.hpp:24
TimePoint when
Definition: planner.hpp:30