forked from meshtastic/firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNotifiedWorkerThread.cpp
More file actions
104 lines (87 loc) · 2.45 KB
/
Copy pathNotifiedWorkerThread.cpp
File metadata and controls
104 lines (87 loc) · 2.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "NotifiedWorkerThread.h"
#include "configuration.h"
#include "main.h"
namespace concurrency
{
static bool debugNotification;
/**
* Notify this thread so it can run
*/
bool NotifiedWorkerThread::notify(uint32_t v, bool overwrite)
{
bool r = notifyCommon(v, overwrite);
if (r)
mainDelay.interrupt();
return r;
}
/**
* Notify this thread so it can run
*/
IRAM_ATTR bool NotifiedWorkerThread::notifyCommon(uint32_t v, bool overwrite)
{
if (overwrite || notification == 0) {
enabled = true;
setInterval(0); // Run ASAP
runASAP = true;
notification = v;
if (debugNotification) {
LOG_DEBUG("Set notification %d", v);
}
return true;
} else {
if (debugNotification) {
LOG_DEBUG("Drop notification %d", v);
}
return false;
}
}
/**
* Notify from an ISR
*
* This must be inline or IRAM_ATTR on ESP32
*/
IRAM_ATTR bool NotifiedWorkerThread::notifyFromISR(BaseType_t *highPriWoken, uint32_t v, bool overwrite)
{
bool r = notifyCommon(v, overwrite);
if (r)
mainDelay.interruptFromISR(highPriWoken);
return r;
}
/**
* Schedule a notification to fire in delay msecs
*/
bool NotifiedWorkerThread::notifyLater(uint32_t delay, uint32_t v, bool overwrite)
{
bool didIt = notify(v, overwrite);
if (didIt) { // If we didn't already have something queued, override the delay to be larger
setIntervalFromNow(delay); // a new version of setInterval relative to the current time
if (debugNotification) {
LOG_DEBUG("Delay notification %u", delay);
}
}
return didIt;
}
void NotifiedWorkerThread::wakePreservingNotification()
{
enabled = true;
setInterval(0);
runASAP = true;
mainDelay.interrupt();
}
void NotifiedWorkerThread::checkNotification()
{
// Atomically read and clear. (This avoids a potential race condition where an interrupt handler could set a new notification
// after checkNotification reads but before it clears, which would cause us to miss that notification until the next one comes
// in.)
auto n = notification.exchange(0); // read+clear atomically: like `n = notification; notification = 0;` but interrupt-safe
if (n) {
onNotify(n);
}
}
int32_t NotifiedWorkerThread::runOnce()
{
enabled = false; // Only run once per notification
checkNotification();
return RUN_SAME;
}
} // namespace concurrency