qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

deferred_exec.h (5519B)


      1 // Copyright 2021 Nick Brassel (@tzarc)
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 #pragma once
      5 
      6 #include <stdbool.h>
      7 #include <stdint.h>
      8 #include <stdlib.h>
      9 
     10 //------------------------------------
     11 // Common
     12 //------------------------------------
     13 
     14 /**
     15  * @typedef A token that can be used to cancel or extend an existing deferred execution.
     16  */
     17 typedef uint8_t deferred_token;
     18 
     19 /**
     20  * @def The constant used to denote an invalid deferred execution token.
     21  */
     22 #define INVALID_DEFERRED_TOKEN 0
     23 
     24 /**
     25  * @typedef Callback to execute.
     26  * @param trigger_time[in] the intended trigger time to execute the callback -- equivalent time-space as timer_read32()
     27  * @param cb_arg[in] the callback argument specified when enqueueing the deferred executor
     28  * @return non-zero re-queues the callback to execute after the returned number of milliseconds. Zero cancels repeated execution.
     29  */
     30 typedef uint32_t (*deferred_exec_callback)(uint32_t trigger_time, void *cb_arg);
     31 
     32 //------------------------------------
     33 // Basic API: used by user-mode code, guaranteed to not collide with core deferred execution
     34 //------------------------------------
     35 
     36 /**
     37  * Configures the supplied deferred executor to be executed after the required number of milliseconds.
     38  *
     39  * @param delay_ms[in] the number of milliseconds before executing the callback
     40  * @param callback[in] the executor to invoke
     41  * @param cb_arg[in] the argument to pass to the executor, may be NULL if unused by the executor
     42  * @return a token usable for extension/cancellation, or INVALID_DEFERRED_TOKEN if an error occurred
     43  */
     44 deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg);
     45 
     46 /**
     47  * Allows for extending the timeframe before an existing deferred execution is invoked.
     48  *
     49  * @param token[in] the returned value from defer_exec for the deferred execution you wish to extend
     50  * @param delay_ms[in] the number of milliseconds before executing the callback
     51  * @return true if the token was extended successfully, otherwise false
     52  */
     53 bool extend_deferred_exec(deferred_token token, uint32_t delay_ms);
     54 
     55 /**
     56  * Allows for cancellation of an existing deferred execution.
     57  *
     58  * @param token[in] the returned value from defer_exec for the deferred execution you wish to cancel
     59  * @return true if the token was cancelled successfully, otherwise false
     60  */
     61 bool cancel_deferred_exec(deferred_token token);
     62 
     63 /**
     64  * Forward declaration for the main loop in order to execute any deferred executors. Should not be invoked by keyboard/user code.
     65  */
     66 void deferred_exec_task(void);
     67 
     68 //------------------------------------
     69 // Advanced API: used when a custom-allocated table is used, primarily for core code.
     70 //------------------------------------
     71 
     72 /**
     73  * @struct Structure for containing self-hosted deferred executor tables.
     74  * @brief Core-side code can use this to create their own tables without impacting on the use of users' ability to add deferred execution.
     75  *        Code outside deferred_exec.c should not worry about internals of this struct, and should just allocate the required number in an array.
     76  */
     77 typedef struct deferred_executor_t {
     78     deferred_token         token;
     79     uint32_t               trigger_time;
     80     deferred_exec_callback callback;
     81     void                  *cb_arg;
     82 } deferred_executor_t;
     83 
     84 /**
     85  * Configures the supplied deferred executor to be executed after the required number of milliseconds.
     86  *
     87  * @param table[in] the custom table used for storage
     88  * @param table_count[in] the number of available items in the table
     89  * @param delay_ms[in] the number of milliseconds before executing the callback
     90  * @param callback[in] the executor to invoke
     91  * @param cb_arg[in] the argument to pass to the executor, may be NULL if unused by the executor
     92  * @return a token usable for extension/cancellation, or INVALID_DEFERRED_TOKEN if an error occurred
     93  */
     94 deferred_token defer_exec_advanced(deferred_executor_t *table, size_t table_count, uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg);
     95 
     96 /**
     97  * Allows for extending the timeframe before an existing deferred execution is invoked.
     98  *
     99  * @param token[in] the returned value from defer_exec for the deferred execution you wish to extend
    100  * @param delay_ms[in] the number of milliseconds before executing the callback
    101  * @return true if the token was extended successfully, otherwise false
    102  */
    103 bool extend_deferred_exec_advanced(deferred_executor_t *table, size_t table_count, deferred_token token, uint32_t delay_ms);
    104 
    105 /**
    106  * Allows for cancellation of an existing deferred execution.
    107  *
    108  * @param token[in] the returned value from defer_exec for the deferred execution you wish to cancel
    109  * @return true if the token was cancelled successfully, otherwise false
    110  */
    111 bool cancel_deferred_exec_advanced(deferred_executor_t *table, size_t table_count, deferred_token token);
    112 
    113 /**
    114  * Forward declaration for the main loop in order to execute any custom table deferred executors. Should not be invoked by keyboard/user code.
    115  * Needed for any custom-allocated deferred execution tables. Any core tasks should add appropriate invocation to quantum/main.c.
    116  *
    117  * @param table[in] the custom table used for storage
    118  * @param table_count[in] the number of available items in the table
    119  * @param last_execution_time[in,out] the last execution time -- this will be checked first to determine if execution is needed, and updated if execution occurred
    120  */
    121 void deferred_exec_advanced_task(deferred_executor_t *table, size_t table_count, uint32_t *last_execution_time);