Skip to content

Commit 1674c72

Browse files
committed
add regular scheduled functions, now also callable on yield()
added bool schedule_function_us(std::function<bool(void)> fn, uint32_t repeat_us) lambda must return true to be not removed from the schedule function list if repeat_us is 0, then the function is called only once. Legacy schedule_function() is preserved Linked list management is simplified This addition allows network drivers like ethernet chips on lwIP to be regularly called - even if some user code loops on receiving data without getting out from main loop (callable from yield()) - without the need to call the driver handling function (transparent) This may be also applicable with common libraries (mDNS, Webserver, )
1 parent 1750022 commit 1674c72

File tree

5 files changed

+42
-40
lines changed

5 files changed

+42
-40
lines changed

cores/esp8266/FunctionalInterrupt.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include "Arduino.h"
44
#include <ScheduledFunctions.h>
55

6+
static ScheduledFunctions* scheduledInterrupts;
7+
68
// Duplicate typedefs from core_esp8266_wiring_digital_c
79
typedef void (*voidFuncPtr)(void);
810
typedef void (*voidFuncPtrArg)(void*);

cores/esp8266/FunctionalInterrupt.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ struct ArgStructure {
2929
FunctionInfo* functionInfo = nullptr;
3030
};
3131

32-
static ScheduledFunctions* scheduledInterrupts;
3332
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
3433
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode);
3534

cores/esp8266/Schedule.cpp

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
#include "Schedule.h"
2+
#include "PolledTimeout.h"
3+
4+
typedef std::function<bool(void)> mFuncT;
25

36
struct scheduled_fn_t
47
{
58
scheduled_fn_t* mNext;
6-
std::function<void(void)> mFunc;
9+
mFuncT mFunc;
10+
esp8266::polledTimeout::periodicFastUs callNow;
11+
12+
scheduled_fn_t(): callNow(esp8266::polledTimeout::periodicFastUs::alwaysExpired) { }
713
};
814

915
static scheduled_fn_t* sFirst = 0;
10-
static scheduled_fn_t* sLast = 0;
11-
1216
static scheduled_fn_t* sFirstUnused = 0;
13-
static scheduled_fn_t* sLastUnused = 0;
1417

1518
static int sCount = 0;
1619

@@ -20,9 +23,6 @@ static scheduled_fn_t* get_fn() {
2023
if (sFirstUnused) {
2124
result = sFirstUnused;
2225
sFirstUnused = result->mNext;
23-
if (sFirstUnused == NULL) {
24-
sLastUnused = NULL;
25-
}
2626
}
2727
// if no unused items, and count not too high, allocate a new one
2828
else if (sCount != SCHEDULED_FN_MAX_COUNT) {
@@ -35,44 +35,40 @@ static scheduled_fn_t* get_fn() {
3535

3636
static void recycle_fn(scheduled_fn_t* fn)
3737
{
38-
if (!sLastUnused) {
39-
sFirstUnused = fn;
40-
}
41-
else {
42-
sLastUnused->mNext = fn;
43-
}
44-
fn->mNext = NULL;
45-
sLastUnused = fn;
38+
fn->mNext = sFirstUnused;
39+
sFirstUnused = fn;
4640
}
4741

48-
bool schedule_function(std::function<void(void)> fn)
42+
bool schedule_function_us(mFuncT fn, uint32_t repeat_us)
4943
{
5044
scheduled_fn_t* item = get_fn();
5145
if (!item) {
5246
return false;
5347
}
5448
item->mFunc = fn;
55-
item->mNext = NULL;
56-
if (!sFirst) {
57-
sFirst = item;
58-
}
59-
else {
60-
sLast->mNext = item;
61-
}
62-
sLast = item;
49+
item->mNext = sFirst;
50+
sFirst = item;
51+
if (repeat_us)
52+
item->callNow.reset(repeat_us);
6353
return true;
6454
}
6555

56+
bool schedule_function(std::function<void(void)> fn)
57+
{
58+
return schedule_function_us([&fn](){ fn(); return false; }, 0);
59+
}
60+
6661
void run_scheduled_functions()
6762
{
68-
scheduled_fn_t* rFirst = sFirst;
69-
sFirst = NULL;
70-
sLast = NULL;
71-
while (rFirst) {
72-
scheduled_fn_t* item = rFirst;
73-
rFirst = item->mNext;
74-
item->mFunc();
75-
item->mFunc = std::function<void(void)>();
76-
recycle_fn(item);
63+
scheduled_fn_t* toCall = sFirst;
64+
while (toCall) {
65+
scheduled_fn_t* item = toCall;
66+
toCall = item->mNext;
67+
if (item->callNow && !item->mFunc()) {
68+
if (sFirst == item)
69+
sFirst = item->mNext;
70+
item->mFunc = mFuncT();
71+
recycle_fn(item);
72+
}
7773
}
7874
}

cores/esp8266/Schedule.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,24 @@
66
#define SCHEDULED_FN_MAX_COUNT 32
77
#define SCHEDULED_FN_INITIAL_COUNT 4
88

9-
// Warning
10-
// This API is not considered stable.
9+
// Warning
10+
// This API is not considered stable.
1111
// Function signatures will change.
1212
// You have been warned.
1313

14-
// Run given function next time `loop` function returns,
14+
// Run given function ONCE next time `loop` function returns,
15+
// or `yield` is called,
1516
// or `run_scheduled_functions` is called.
1617
// Use std::bind to pass arguments to a function, or call a class member function.
1718
// Note: there is no mechanism for cancelling scheduled functions.
1819
// Keep that in mind when binding functions to objects which may have short lifetime.
1920
// Returns false if the number of scheduled functions exceeds SCHEDULED_FN_MAX_COUNT.
2021
bool schedule_function(std::function<void(void)> fn);
2122

22-
// Run all scheduled functions.
23+
// run given function every at least <repeat_us> microseconds until it returns false
24+
bool schedule_function_us(std::function<bool(void)> fn, uint32_t repeat_us);
25+
26+
// Run all scheduled functions.
2327
// Use this function if your are not using `loop`, or `loop` does not return
2428
// on a regular basis.
2529
void run_scheduled_functions();

cores/esp8266/core_esp8266_main.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,15 @@ extern "C" void esp_yield() {
9191
}
9292

9393
extern "C" void esp_schedule() {
94+
// always on CONT stack here
95+
run_scheduled_functions();
9496
ets_post(LOOP_TASK_PRIORITY, 0, 0);
9597
}
9698

9799
extern "C" void __yield() {
98100
if (cont_can_yield(g_pcont)) {
99101
esp_schedule();
100-
esp_yield();
102+
cont_yield(g_pcont); //esp_yield();
101103
}
102104
else {
103105
panic();
@@ -122,7 +124,6 @@ static void loop_wrapper() {
122124
setup_done = true;
123125
}
124126
loop();
125-
run_scheduled_functions();
126127
esp_schedule();
127128
}
128129

0 commit comments

Comments
 (0)