ReactESP 3.3.1
Asynchronous programming for the ESP microcontrollers
Loading...
Searching...
No Matches
event_loop.cpp
Go to the documentation of this file.
1#include "event_loop.h"
2
3#include <freertos/semphr.h>
4
5namespace reactesp {
6
8 xSemaphoreTakeRecursive(timed_queue_mutex_, portMAX_DELAY);
9 const uint64_t now = micros64();
10
11 while (!timed_events_.empty()) {
12 auto it = timed_events_.begin();
13 TimedEvent* event = *it;
14 if (now < event->getTriggerTimeMicros()) {
15 break;
16 }
17#if __cplusplus >= 201703L
18 // Extract the node to avoid heap deallocation. RepeatEvent::tick()
19 // will update the trigger time; we reinsert the same node afterward.
20 auto node = timed_events_.extract(it);
21#else
22 // C++14 fallback: erase + reinsert, one heap alloc + dealloc per
23 // RepeatEvent tick.
24 timed_events_.erase(it);
25#endif
26 xSemaphoreGiveRecursive(timed_queue_mutex_);
27 // tick() may call back into the event loop. For RepeatEvent, tick()
28 // updates the trigger time. For DelayEvent, tick() sets enabled=false.
29 // Either type's callback may call remove(), which also sets
30 // enabled=false.
31 event->tick(this);
33 xSemaphoreTakeRecursive(timed_queue_mutex_, portMAX_DELAY);
34#if __cplusplus >= 201703L
35 if (event->isEnabled() && !node.empty()) {
36 // RepeatEvent: reinsert the extracted node without allocation.
37 timed_events_.insert(std::move(node));
38 } else {
39 // DelayEvent (done) or RepeatEvent removed from within its
40 // callback: drop the node and delete the event.
41 delete event;
42 }
43#else
44 if (event->isEnabled()) {
45 timed_events_.insert(event);
46 } else {
47 delete event;
48 }
49#endif
50 }
51 xSemaphoreGiveRecursive(timed_queue_mutex_);
52}
53
55 xSemaphoreTakeRecursive(untimed_list_mutex_, portMAX_DELAY);
56 for (UntimedEvent* re : this->untimed_list) {
57 re->tick(this);
59 }
60 xSemaphoreGiveRecursive(untimed_list_mutex_);
61}
62
65 tickTimed();
67}
68
69DelayEvent* EventLoop::onDelay(uint32_t delay, react_callback callback) {
70 auto* dre = new DelayEvent(delay, callback);
71 dre->add(this);
72 return dre;
73}
74
76 auto* dre = new DelayEvent(delay, callback);
77 dre->add(this);
78 return dre;
79}
80
81RepeatEvent* EventLoop::onRepeat(uint32_t interval, react_callback callback) {
82 auto* rre = new RepeatEvent(interval, callback);
83 rre->add(this);
84 return rre;
85}
86
88 react_callback callback) {
89 auto* rre = new RepeatEvent(interval, callback);
90 rre->add(this);
91 return rre;
92}
93
95 auto* sre = new StreamEvent(stream, callback);
96 sre->add(this);
97 return sre;
98}
99
100ISREvent* EventLoop::onInterrupt(uint8_t pin_number, int mode,
101 react_callback callback) {
102 auto* isrre = new ISREvent(pin_number, mode, callback);
103 isrre->add(this);
104 return isrre;
105}
106
108 auto* tre = new TickEvent(callback);
109 tre->add(this);
110 return tre;
111}
112
113void EventLoop::remove(TimedEvent* event) { event->remove(this); }
114
116 xSemaphoreTakeRecursive(this->untimed_list_mutex_, portMAX_DELAY);
117 auto it = std::find(this->untimed_list.begin(), this->untimed_list.end(), event);
118 if (it != this->untimed_list.end()) {
119 this->untimed_list.erase(it);
120 }
121 delete event;
122 xSemaphoreGiveRecursive(this->untimed_list_mutex_);
123}
125 xSemaphoreTakeRecursive(this->isr_event_list_mutex_, portMAX_DELAY);
126 auto it = std::find(this->isr_event_list.begin(), this->isr_event_list.end(), event);
127 if (it != this->isr_event_list.end()) {
128 this->isr_event_list.erase(it);
129 }
130 delete event;
131 xSemaphoreGiveRecursive(this->isr_event_list_mutex_);
132}
133
134void EventLoop::remove(Event* event) { event->remove(this); }
135
136} // namespace reactesp
Event that is triggered after a certain time delay.
Definition events.h:155
friend class TimedEvent
Definition event_loop.h:17
friend class UntimedEvent
Definition event_loop.h:19
void remove(TimedEvent *event)
DelayEvent * onDelayMicros(uint64_t delay, react_callback callback)
Create a new DelayEvent.
friend class ISREvent
Definition event_loop.h:20
SemaphoreHandle_t untimed_list_mutex_
Definition event_loop.h:151
StreamEvent * onAvailable(Stream &stream, react_callback callback)
Create a new StreamEvent.
friend class Event
Definition event_loop.h:16
TickEvent * onTick(react_callback callback)
Create a new TickEvent.
DelayEvent * onDelay(uint32_t delay, react_callback callback)
Create a new DelayEvent.
uint64_t untimed_event_counter
Definition event_loop.h:155
std::vector< UntimedEvent * > untimed_list
Definition event_loop.h:144
RepeatEvent * onRepeatMicros(uint64_t interval, react_callback callback)
Create a new RepeatEvent.
SemaphoreHandle_t timed_queue_mutex_
Definition event_loop.h:150
ISREvent * onInterrupt(uint8_t pin_number, int mode, react_callback callback)
Create a new ISREvent (interrupt event).
RepeatEvent * onRepeat(uint32_t interval, react_callback callback)
Create a new RepeatEvent.
TimedEventSet timed_events_
Definition event_loop.h:140
SemaphoreHandle_t isr_event_list_mutex_
Definition event_loop.h:152
uint64_t timed_event_counter
Definition event_loop.h:154
friend class RepeatEvent
Definition event_loop.h:18
std::vector< ISREvent * > isr_event_list
Definition event_loop.h:147
Event that is triggered when there is input available at the given Arduino Stream.
Definition events.h:219
Event that is triggered unconditionally at each execution loop.
Definition events.h:239
std::function< void()> react_callback
Definition events.h:12
uint64_t ICACHE_RAM_ATTR micros64()
Return the current time since the device restart in microseconds.
Definition events.h:22