Skip to content

Commit 0869c22

Browse files
committed
Merge branch 'mc/cancel'
* mc/cancel: timer:cancel: handle cancel of expired tasks timer:keywords: add Task type, and cancel method timer:examples:full: add cancel example timer:README: update for cancel method timer: add cancel method
2 parents b7117dc + 114e404 commit 0869c22

File tree

4 files changed

+68
-12
lines changed

4 files changed

+68
-12
lines changed

README.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ timer.every(interval, function_to_call);
4949
timer.every(interval, function_to_call, argument); // with argument
5050
```
5151

52+
To **cancel** a *Task*
53+
```cpp
54+
auto task = timer.in(delay, function_to_call);
55+
timer.cancel(task);
56+
```
57+
5258
Be fancy with **lambdas**
5359
```cpp
5460
timer.in(1000, [](void*) -> bool { return false; });
@@ -76,13 +82,19 @@ bool handler(void *argument);
7682
void tick();
7783
7884
/* Calls handler with opaque as argument in delay units of time */
79-
bool in(unsigned long delay, handler_t handler, void *opaque = NULL);
85+
Timer<>::Task
86+
in(unsigned long delay, handler_t handler, void *opaque = NULL);
8087
8188
/* Calls handler with opaque as argument at time */
82-
bool at(unsigned long time, handler_t handler, void *opaque = NULL);
89+
Timer<>::Task
90+
at(unsigned long time, handler_t handler, void *opaque = NULL);
8391
8492
/* Calls handler with opaque as argument every interval units of time */
85-
bool every(unsigned long interval, handler_t handler, void *opaque = NULL);
93+
Timer<>::Task
94+
every(unsigned long interval, handler_t handler, void *opaque = NULL);
95+
96+
/* Cancel a timer task */
97+
void cancel(Timer<>::Task &task);
8698
```
8799

88100
### Installation
@@ -129,7 +141,9 @@ Currently only a software timer. Any blocking code delaying *timer*.**tick()** w
129141
130142
The library does not do any dynamic memory allocation.
131143
132-
The number of concurrent tasks is a compile time constant, meaning there is a limit to the number of concurrent tasks. The **in / at / every** functions return **false** if the *Timer* is full.
144+
The number of concurrent tasks is a compile time constant, meaning there is a limit to the number of concurrent tasks. The **in / at / every** functions return **NULL** if the *Timer* is full.
145+
146+
A *Task* value is valid only for the timer that created it, and only for the lifetime of that timer.
133147
134148
Change the number of concurrent tasks using the *Timer* constructors. Save memory by reducing the number, increase memory use by having more. The default is **TIMER_MAX_TASKS** which is currently 16.
135149

examples/full/full.ino

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* - Setting a different number of tasks with microsecond resolution
77
* - disabling a repeated function
88
* - running a function after a delay
9+
* - cancelling a task
910
*
1011
*/
1112

@@ -61,6 +62,10 @@ void setup() {
6162
// call the print_message function at time + 10 seconds
6263
timer.at(millis() + 10000, print_message, (void *)"call at millis() + 10 seconds");
6364

65+
// call the toggle_led function every 500 millis (half second)
66+
auto task = timer.every(500, toggle_led);
67+
timer.cancel(task); // this task is now cancelled, and will not run
68+
6469
// call print_message in 2 seconds, but with microsecond resolution
6570
u_timer.in(2000000, print_message, (void *)"delayed two seconds using microseconds");
6671

keywords.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#######################################
88

99
Timer KEYWORD1
10+
Task KEYWORD1
1011
handler_t KEYWORD1
1112

1213
#######################################
@@ -17,6 +18,7 @@ in KEYWORD2
1718
at KEYWORD2
1819
every KEYWORD2
1920
tick KEYWORD2
21+
cancel KEYWORD2
2022

2123
#######################################
2224
# Instances (KEYWORD2)

src/timer.h

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,28 +52,47 @@ template <
5252
class Timer {
5353
public:
5454

55+
typedef uintptr_t Task; /* public task handle */
5556
typedef bool (*handler_t)(void *opaque); /* task handler func signature */
5657

5758
/* Calls handler with opaque as argument in delay units of time */
58-
bool
59+
Task
5960
in(unsigned long delay, handler_t h, void *opaque = NULL)
6061
{
61-
return add_task(time_func(), delay, h, opaque);
62+
return task_id(add_task(time_func(), delay, h, opaque));
6263
}
6364

6465
/* Calls handler with opaque as argument at time */
65-
bool
66+
Task
6667
at(unsigned long time, handler_t h, void *opaque = NULL)
6768
{
6869
const unsigned long now = time_func();
69-
return add_task(now, time - now, h, opaque);
70+
return task_id(add_task(now, time - now, h, opaque));
7071
}
7172

7273
/* Calls handler with opaque as argument every interval units of time */
73-
bool
74+
Task
7475
every(unsigned long interval, handler_t h, void *opaque = NULL)
7576
{
76-
return add_task(time_func(), interval, h, opaque, interval);
77+
return task_id(add_task(time_func(), interval, h, opaque, interval));
78+
}
79+
80+
/* Cancel the timer task */
81+
void
82+
cancel(Task &task)
83+
{
84+
if (!task) return;
85+
86+
for (size_t i = 0; i < max_tasks; ++i) {
87+
struct task * const t = &tasks[i];
88+
89+
if (t->handler && (t->id ^ task) == (uintptr_t)t) {
90+
remove(t);
91+
break;
92+
}
93+
}
94+
95+
task = NULL;
7796
}
7897

7998
/* Ticks the timer forward - call this function in loop() */
@@ -117,12 +136,15 @@ class Timer {
117136

118137
private:
119138

139+
size_t ctr;
140+
120141
struct task {
121142
handler_t handler; /* task handler callback func */
122143
void *opaque; /* argument given to the callback handler */
123144
unsigned long start,
124-
expires, /* when the task expires */
125-
repeat; /* repeat task */
145+
expires; /* when the task expires */
146+
size_t repeat, /* repeat task */
147+
id;
126148
} tasks[max_tasks];
127149

128150
inline
@@ -134,6 +156,16 @@ class Timer {
134156
task->start = 0;
135157
task->expires = 0;
136158
task->repeat = 0;
159+
task->id = 0;
160+
}
161+
162+
inline
163+
Task
164+
task_id(const struct task * const t)
165+
{
166+
const Task id = (uintptr_t)t;
167+
168+
return id ? id ^ t->id : id;
137169
}
138170

139171
inline
@@ -157,6 +189,9 @@ class Timer {
157189

158190
if (!slot) return NULL;
159191

192+
if (++ctr == 0) ++ctr; // overflow
193+
194+
slot->id = ctr;
160195
slot->handler = h;
161196
slot->opaque = opaque;
162197
slot->start = start;

0 commit comments

Comments
 (0)