Skip to content

Commit 455583b

Browse files
authored
scheduled functions: calls from yield are now optional (#6158)
* scheduled functions: calls from yield are now optional * add move constructors * yield every 100ms
1 parent dddc8d2 commit 455583b

File tree

3 files changed

+55
-20
lines changed

3 files changed

+55
-20
lines changed

cores/esp8266/Schedule.cpp

+29-12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "Schedule.h"
55
#include "PolledTimeout.h"
66
#include "interrupts.h"
7+
#include "coredecls.h"
78

89
typedef std::function<bool(void)> mFuncT;
910

@@ -12,15 +13,14 @@ struct scheduled_fn_t
1213
scheduled_fn_t* mNext = nullptr;
1314
mFuncT mFunc;
1415
esp8266::polledTimeout::periodicFastUs callNow;
16+
schedule_e policy;
1517

1618
scheduled_fn_t() : callNow(esp8266::polledTimeout::periodicFastUs::alwaysExpired) { }
1719
};
1820

1921
static scheduled_fn_t* sFirst = nullptr;
2022
static scheduled_fn_t* sLast = nullptr;
21-
2223
static scheduled_fn_t* sUnused = nullptr;
23-
2424
static int sCount = 0;
2525

2626
IRAM_ATTR // called from ISR
@@ -52,7 +52,7 @@ static void recycle_fn_unsafe(scheduled_fn_t* fn)
5252
}
5353

5454
IRAM_ATTR // (not only) called from ISR
55-
bool schedule_function_us(std::function<bool(void)>&& fn, uint32_t repeat_us)
55+
bool schedule_function_us(std::function<bool(void)>&& fn, uint32_t repeat_us, schedule_e policy)
5656
{
5757
assert(repeat_us < decltype(scheduled_fn_t::callNow)::neverExpires); //~26800000us (26.8s)
5858

@@ -64,8 +64,9 @@ bool schedule_function_us(std::function<bool(void)>&& fn, uint32_t repeat_us)
6464

6565
if (repeat_us)
6666
item->callNow.reset(repeat_us);
67-
67+
item->policy = policy;
6868
item->mFunc = fn;
69+
6970
if (sFirst)
7071
sLast->mNext = item;
7172
else
@@ -76,24 +77,24 @@ bool schedule_function_us(std::function<bool(void)>&& fn, uint32_t repeat_us)
7677
}
7778

7879
IRAM_ATTR // (not only) called from ISR
79-
bool schedule_function_us(const std::function<bool(void)>& fn, uint32_t repeat_us)
80+
bool schedule_function_us(const std::function<bool(void)>& fn, uint32_t repeat_us, schedule_e policy)
8081
{
81-
return schedule_function_us(std::function<bool(void)>(fn), repeat_us);
82+
return schedule_function_us(std::function<bool(void)>(fn), repeat_us, policy);
8283
}
8384

8485
IRAM_ATTR // called from ISR
85-
bool schedule_function(std::function<void(void)>&& fn)
86+
bool schedule_function(std::function<void(void)>&& fn, schedule_e policy)
8687
{
87-
return schedule_function_us([fn]() { fn(); return false; }, 0);
88+
return schedule_function_us([fn]() { fn(); return false; }, 0, policy);
8889
}
8990

9091
IRAM_ATTR // called from ISR
91-
bool schedule_function(const std::function<void(void)>& fn)
92+
bool schedule_function(const std::function<void(void)>& fn, schedule_e policy)
9293
{
93-
return schedule_function(std::function<void(void)>(fn));
94+
return schedule_function(std::function<void(void)>(fn), policy);
9495
}
9596

96-
void run_scheduled_functions()
97+
void run_scheduled_functions(schedule_e policy)
9798
{
9899
// Note to the reader:
99100
// There is no exposed API to remove a scheduled function:
@@ -110,13 +111,22 @@ void run_scheduled_functions()
110111
fence = true;
111112
}
112113

114+
esp8266::polledTimeout::periodicFastMs yieldNow(100); // yield every 100ms
113115
scheduled_fn_t* lastRecurring = nullptr;
114116
scheduled_fn_t* nextCall = sFirst;
115117
while (nextCall)
116118
{
117119
scheduled_fn_t* toCall = nextCall;
118120
nextCall = nextCall->mNext;
119-
if (toCall->callNow)
121+
122+
// run scheduled function:
123+
// - when its schedule policy allows it anytime
124+
// - or if we are called at loop() time
125+
// and
126+
// - its time policy allows it
127+
if ( ( toCall->policy == SCHEDULED_FUNCTION_WITHOUT_YIELDELAYCALLS
128+
|| policy == SCHEDULED_FUNCTION_ONCE_PER_LOOP)
129+
&& toCall->callNow)
120130
{
121131
if (toCall->mFunc())
122132
{
@@ -142,6 +152,13 @@ void run_scheduled_functions()
142152
else
143153
// function stays in list
144154
lastRecurring = toCall;
155+
156+
if (policy == SCHEDULED_FUNCTION_ONCE_PER_LOOP && yieldNow)
157+
{
158+
// this is yield() in cont stack:
159+
esp_schedule();
160+
cont_yield(g_pcont);
161+
}
145162
}
146163

147164
fence = false;

cores/esp8266/Schedule.h

+17-5
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,33 @@
2626

2727
#define SCHEDULED_FN_MAX_COUNT 32
2828

29+
enum schedule_e
30+
{
31+
SCHEDULED_FUNCTION_ONCE_PER_LOOP,
32+
SCHEDULED_FUNCTION_WITHOUT_YIELDELAYCALLS
33+
};
34+
2935
// * Run the lambda only once next time
30-
//bool schedule_function(std::function<void(void)>&& fn);
31-
bool schedule_function(const std::function<void(void)>& fn);
36+
bool schedule_function(std::function<void(void)>&& fn,
37+
schedule_e policy = SCHEDULED_FUNCTION_ONCE_PER_LOOP);
38+
bool schedule_function(const std::function<void(void)>& fn,
39+
schedule_e policy = SCHEDULED_FUNCTION_ONCE_PER_LOOP);
3240

3341
// * Run the lambda periodically about every <repeat_us> microseconds until
3442
// it returns false.
3543
// * Note that it may be more than <repeat_us> microseconds between calls if
3644
// `yield` is not called frequently, and therefore should not be used for
3745
// timing critical operations.
38-
//bool schedule_function_us(std::function<bool(void)>&& fn, uint32_t repeat_us);
39-
bool schedule_function_us(const std::function<bool(void)>& fn, uint32_t repeat_us);
46+
bool schedule_function_us(std::function<bool(void)>&& fn,
47+
uint32_t repeat_us,
48+
schedule_e policy = SCHEDULED_FUNCTION_ONCE_PER_LOOP);
49+
bool schedule_function_us(const std::function<bool(void)>& fn,
50+
uint32_t repeat_us,
51+
schedule_e policy = SCHEDULED_FUNCTION_ONCE_PER_LOOP);
4052

4153
// Run all scheduled functions.
4254
// Use this function if your are not using `loop`, or `loop` does not return
4355
// on a regular basis.
44-
void run_scheduled_functions();
56+
void run_scheduled_functions(schedule_e policy = SCHEDULED_FUNCTION_ONCE_PER_LOOP);
4557

4658
#endif //ESP_SCHEDULE_H

cores/esp8266/core_esp8266_main.cpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -84,22 +84,27 @@ void preloop_update_frequency() {
8484
}
8585

8686

87+
static inline void esp_yield_within_cont() __attribute__((always_inline));
88+
static void esp_yield_within_cont() {
89+
cont_yield(g_pcont);
90+
run_scheduled_functions(SCHEDULED_FUNCTION_WITHOUT_YIELDELAYCALLS);
91+
}
92+
8793
extern "C" void esp_yield() {
8894
if (cont_can_yield(g_pcont)) {
89-
cont_yield(g_pcont);
95+
esp_yield_within_cont();
9096
}
9197
}
9298

9399
extern "C" void esp_schedule() {
94100
// always on CONT stack here
95-
run_scheduled_functions();
96101
ets_post(LOOP_TASK_PRIORITY, 0, 0);
97102
}
98103

99104
extern "C" void __yield() {
100105
if (cont_can_yield(g_pcont)) {
101106
esp_schedule();
102-
cont_yield(g_pcont); //esp_yield();
107+
esp_yield_within_cont();
103108
}
104109
else {
105110
panic();
@@ -124,6 +129,7 @@ static void loop_wrapper() {
124129
setup_done = true;
125130
}
126131
loop();
132+
run_scheduled_functions(SCHEDULED_FUNCTION_ONCE_PER_LOOP);
127133
esp_schedule();
128134
}
129135

0 commit comments

Comments
 (0)