diff options
author | Nick Brassel <nick@tzarc.org> | 2021-11-16 05:21:09 +1100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-15 18:21:09 +0000 |
commit | 36d123e9c5a9ce0e29b9bc22ef87661bf479e299 (patch) | |
tree | 1033718afb33e1eb7dc3cd7b99db59a90668fa8a /docs | |
parent | b3ee124da666287ef13787523ea88bf40713ff4c (diff) |
Add support for deferred executors. (#14859)
* Add support for deferred executors.
* More docs.
* Include from quantum.h
* Cleanup.
* Parameter checks
* Comments.
* qmk format-c
* I accidentally a few words.
* API name change.
* Apply suggestions from code review
Co-authored-by: Sergey Vlasov <sigprof@gmail.com>
* Review comments.
* qmk format-c
* Review comments.
Co-authored-by: Sergey Vlasov <sigprof@gmail.com>
Diffstat (limited to 'docs')
-rw-r--r-- | docs/config_options.md | 2 | ||||
-rw-r--r-- | docs/custom_quantum_functions.md | 66 | ||||
-rw-r--r-- | docs/getting_started_make_guide.md | 4 |
3 files changed, 72 insertions, 0 deletions
diff --git a/docs/config_options.md b/docs/config_options.md index ece7ab8ee3..9f2453b698 100644 --- a/docs/config_options.md +++ b/docs/config_options.md @@ -446,6 +446,8 @@ Use these to enable or disable building certain features. The more you have enab * Forces the keyboard to wait for a USB connection to be established before it starts up * `NO_USB_STARTUP_CHECK` * Disables usb suspend check after keyboard startup. Usually the keyboard waits for the host to wake it up before any tasks are performed. This is useful for split keyboards as one half will not get a wakeup call but must send commands to the master. +* `DEFERRED_EXEC_ENABLE` + * Enables deferred executor support -- timed delays before callbacks are invoked. See [deferred execution](custom_quantum_functions.md#deferred-execution) for more information. ## USB Endpoint Limitations diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md index 798c346e67..dd1654bd29 100644 --- a/docs/custom_quantum_functions.md +++ b/docs/custom_quantum_functions.md @@ -405,3 +405,69 @@ And you're done. The RGB layer indication will only work if you want it to. And * Keymap: `void eeconfig_init_user(void)`, `uint32_t eeconfig_read_user(void)` and `void eeconfig_update_user(uint32_t val)` The `val` is the value of the data that you want to write to EEPROM. And the `eeconfig_read_*` function return a 32 bit (DWORD) value from the EEPROM. + +### Deferred Execution :id=deferred-execution + +QMK has the ability to execute a callback after a specified period of time, rather than having to manually manage timers. + +#### Deferred executor callbacks + +All _deferred executor callbacks_ have a common function signature and look like: + +```c +uint32_t my_callback(uint32_t trigger_time, void *cb_arg) { + /* do something */ + bool repeat = my_deferred_functionality(); + return repeat ? 500 : 0; +} +``` + +The first argument `trigger_time` is the intended time of execution. If other delays prevent executing at the exact trigger time, this allows for "catch-up" or even skipping intervals, depending on the required behaviour. + +The second argument `cb_arg` is the same argument passed into `defer_exec()` below, and can be used to access state information from the original call context. + +The return value is the number of milliseconds to use if the function should be repeated -- if the callback returns `0` then it's automatically unregistered. In the example above, a hypothetical `my_deferred_functionality()` is invoked to determine if the callback needs to be repeated -- if it does, it reschedules for a `500` millisecond delay, otherwise it informs the deferred execution background task that it's done, by returning `0`. + +?> Note that the returned delay will be applied to the intended trigger time, not the time of callback invocation. This allows for generally consistent timing even in the face of occasional late execution. + +#### Deferred executor registration + +Once a callback has been defined, it can be scheduled using the following API: + +```c +deferred_token my_token = defer_exec(1500, my_callback, NULL); +``` + +The first argument is the number of milliseconds to wait until executing `my_callback` -- in the case above, `1500` milliseconds, or 1.5 seconds. + +The third parameter is the `cb_arg` that gets passed to the callback at the point of execution. This value needs to be valid at the time the callback is invoked -- a local function value will be destroyed before the callback is executed and should not be used. If this is not required, `NULL` should be used. + +The return value is a `deferred_token` that can consequently be used to cancel the deferred executor callback before it's invoked. If a failure occurs, the returned value will be `INVALID_DEFERRED_TOKEN`. Usually this will be as a result of supplying `0` to the delay, or a `NULL` for the callback. The other failure case is if there are too many deferred executions "in flight" -- this can be increased by changing the limit, described below. + +#### Extending a deferred execution + +The `deferred_token` returned by `defer_exec()` can be used to extend a the duration a pending execution waits before it gets invoked: +```c +// This will re-delay my_token's future execution such that it is invoked 800ms after the current time +extend_deferred_exec(my_token, 800); +``` + +#### Cancelling a deferred execution + +The `deferred_token` returned by `defer_exec()` can be used to cancel a pending execution before it gets invoked: +```c +// This will cancel my_token's future execution +cancel_deferred_exec(my_token); +``` + +Once a token has been canceled, it should be considered invalid. Reusing the same token is not supported. + +#### Deferred callback limits + +There are a maximum number of deferred callbacks that can be scheduled, controlled by the value of the define `MAX_DEFERRED_EXECUTORS`. + +If registrations fail, then you can increase this value in your keyboard or keymap `config.h` file, for example to 16 instead of the default 8: + +```c +#define MAX_DEFERRED_EXECUTORS 16 +``` diff --git a/docs/getting_started_make_guide.md b/docs/getting_started_make_guide.md index a514864353..1a7e276098 100644 --- a/docs/getting_started_make_guide.md +++ b/docs/getting_started_make_guide.md @@ -145,6 +145,10 @@ Lets you replace the default matrix scanning routine with your own code. For fur Lets you replace the default key debouncing routine with an alternative one. If `custom` you will need to provide your own implementation. +`DEFERRED_EXEC_ENABLE` + +Enables deferred executor support -- timed delays before callbacks are invoked. See [deferred execution](custom_quantum_functions.md#deferred-execution) for more information. + ## Customizing Makefile Options on a Per-Keymap Basis If your keymap directory has a file called `rules.mk` any options you set in that file will take precedence over other `rules.mk` options for your particular keyboard. |