---
title: "Delayed work"
canonical_url: https://developer.repebble.com/pebbleos/docs/samples/kernel/delayed_work/
last_updated: 2026-11-13
sdk_version: 4.44
---
# Delayed work

Source: https://developer.repebble.com/pebbleos/docs/samples/kernel/delayed_work/

This sample runs work after a delay, in three common shapes: a debounce, where every edge of a button pushes the work back; a timeout, which keeps its first delay; and a heartbeat that schedules itself again without drifting, until it is canceled.

`pbl_delayed_work_cancel_sync()` returns with the heartbeat stopped for good, although its function schedules it again: what a driver calls before freeing the object the work lives in.

Run:

`pbl samples samples/kernel/delayed_work`

Boards:

every board

## Sources

src/main.c

```
#include \<pbl/kernel/delay.h\>#include \<pbl/kernel/work.h\>#include \<pbl/logging/logging.h\>#define DEBOUNCE\_MS 200#define HEARTBEAT\_MS 20static unsigned int s\_presses;static unsigned int s\_heartbeats;static void prv\_button\_settled(struct pbl\_work \*work) {s\_presses++;PBL\_LOG\_INFO("button: settled, press %u", s\_presses);}static void prv\_heartbeat(struct pbl\_work \*work);static PBL\_DELAYED\_WORK\_DEFINE(s\_debounce, prv\_button\_settled);static PBL\_DELAYED\_WORK\_DEFINE(s\_heartbeat, prv\_heartbeat);/\* Unlike a timer callback this runs on a thread, and may block or take locks. \*/static void prv\_heartbeat(struct pbl\_work \*work) {s\_heartbeats++;/\* Counts from the last expiry, not from now, so the period does not drift. \*/pbl\_delayed\_work\_schedule\_next(&s\_heartbeat, pbl\_ms\_to\_ticks(HEARTBEAT\_MS));}/\* What a button interrupt would do on every edge, bounces included. \*/static void prv\_button\_edge(void) {pbl\_delayed\_work\_reschedule(&pbl\_sys\_workq, &s\_debounce, PBL\_MSEC(DEBOUNCE\_MS));}int main(void) {bool kept;PBL\_LOG\_INFO("main: five edges 5 ms apart, each pushing the work back");for (unsigned int i = 0; i \< 5; i++) {prv\_button\_edge();pbl\_sleep\_ms(5);}pbl\_sleep\_ms(2 \* DEBOUNCE\_MS);/\* schedule() keeps a delay that is running, where reschedule() replaces it. \*/pbl\_delayed\_work\_schedule(&pbl\_sys\_workq, &s\_debounce, PBL\_MSEC(DEBOUNCE\_MS));kept = !pbl\_delayed\_work\_schedule(&pbl\_sys\_workq, &s\_debounce, PBL\_SEC(10));PBL\_LOG\_INFO("main: scheduled twice, first delay kept: %s", kept ? "yes" : "no");pbl\_sleep\_ms(2 \* DEBOUNCE\_MS);pbl\_delayed\_work\_schedule(&pbl\_sys\_workq, &s\_heartbeat, PBL\_MSEC(HEARTBEAT\_MS));pbl\_sleep\_ms(5 \* HEARTBEAT\_MS + HEARTBEAT\_MS / 2);/\* Stops it for good, even though its function schedules it again. \*/pbl\_delayed\_work\_cancel\_sync(&s\_heartbeat);PBL\_LOG\_INFO("main: heartbeat stopped after %u beats, pending: %s", s\_heartbeats,pbl\_delayed\_work\_is\_pending(&s\_heartbeat) ? "yes" : "no");PBL\_LOG\_INFO("Sample done");return 0;}
```

## Output

```
main: five edges 5 ms apart, each pushing the work back
button: settled, press 1
main: scheduled twice, first delay kept: yes
button: settled, press 2
main: heartbeat stopped after \d beats, pending: no
Sample done
```

Generated from PebbleOS [f4926c952](https://github.com/coredevices/pebbleos/commit/f4926c952bf9b82bce9e3cdb44645a59531c0ee9). This page is maintained in the pebbleos repository: [docs/samples/kernel/delayed\_work.md](https://github.com/coredevices/pebbleos/blob/f4926c952bf9b82bce9e3cdb44645a59531c0ee9/docs/samples/kernel/delayed_work.md).
