Repository navigation
Expand file tree
/
Copy pathasync.cpp
More file actions
102 lines (87 loc) · 3.21 KB
/
Copy pathasync.cpp
File metadata and controls
102 lines (87 loc) · 3.21 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
#include "async.h"
Async::Async(unsigned short sizePool) {
nodePool = (ScheduleNode*) malloc(sizeof(ScheduleNode)*sizePool);
for(unsigned short i = 0; i < sizePool; i++) {
*(nodePool + i) = {
.lastExecution = 0,
.interval = 0,
.flags = 0b00000010,
.function = nullptr
};
}
nNodes = 0;
this->sizePool = sizePool;
}
short Async::setInterval(void (*fun)(void), unsigned long time) {
if(fun == nullptr || nNodes >= sizePool)
return -1;
for(unsigned short i = 0; i < sizePool; i++) {
if((nodePool + i)->flags & 0b00000010) { // Is finished, bit 1
*(nodePool + i) = {
.lastExecution = millis(),
.interval = time,
.flags = 0b00000001,
.function = fun
};
nNodes++;
return i;
}
}
return -1; // No free slot
}
short Async::setTimeout(void (*fun)(void), unsigned long time) {
if(fun == nullptr || nNodes >= sizePool)
return -1;
for(unsigned short i = 0; i < sizePool; i++) {
if((nodePool + i)->flags & 0b00000010) { // Is finished, bit 1
*(nodePool + i) = {
.lastExecution = millis(),
.interval = time,
.flags = 0b00000000,
.function = fun
};
nNodes++;
return i;
}
}
return -1; // No free slot
}
bool Async::clearInterval(short id) {
if(id < 0 || (unsigned short) id >= sizePool)
return false;
if((nodePool + id)->flags & 0b00000010) // Already finished, nothing to release
return true;
(nodePool + id)->flags = 0b00000010; // Mark as finished, bit 1
nNodes--; // Release the slot in the counter too, otherwise the pool is seen
// as full after sizePool calls and every later set* returns -1
return true;
}
void Async::run() {
for(unsigned short i = 0; i < sizePool; i++) {
if(!((nodePool + i)->flags & 0b00000010)) { // Is not finished
// Unsigned arithmetic already wraps correctly, so the millis()
// overflow at ~49.7 days needs no special case. Read the clock
// once per node: the old code sampled it twice and could compare
// one value but subtract another.
unsigned long elapsedTime = millis() - (nodePool + i)->lastExecution;
if(elapsedTime >= (nodePool + i)->interval) {
ScheduleNode* node = nodePool + i;
if(!(node->flags & 0b00000001)) { // Is not loop, bit 0
// Release the slot before the call: the callback may clear
// its own id (must not decrement nNodes twice) or schedule
// a new timer that reuses this slot (must not be wiped).
node->flags = 0b00000010; // Mark as finished, bit 1
nNodes--;
node->function();
} else {
node->function();
if(!(node->flags & 0b00000010)) // Not cleared inside the callback
node->lastExecution = millis();
}
} // End elapsed time greater than interval of node
} // End if node not finished
} // End for
}
Async::~Async() {
free(nodePool);
}