Created
April 28, 2022 21:38
-
-
Save DaBs/1be19c63757126bebc4f6d1368dc9813 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef THROTTLE_H | |
#define THROTTLE_H | |
#include <stdint.h> | |
#include <stdbool.h> | |
uintptr_t THROTTLE_CallbackEnqueue(uint32_t timeout, void (*timerCallback)()); | |
uint32_t THROTTLE_ReadTime(); | |
/** | |
* @brief Creates functions for setting up a throttled function based on the system timer. | |
* @param TIMEOUT_MS uint32_t - Throttle time in ms, e.g. 200 | |
* @param LEADING boolean - Whether or not the first call should be immediately executed | |
* @param TRAILING boolean - Whether the last value, regardless of time passed, should be dispatched after time elapsed | |
* @param FUNCTION_NAME Function name you want to be able to call | |
* @param ARGUMENTS_TYPE struct of arguments to give function | |
*/ | |
#define TROTTLE_FUNCTION(TIMEOUT_MS, LEADING, TRAILING, FUNCTION_NAME, ARGUMENTS_TYPE)\ | |
\ | |
static uint32_t FUNCTION_NAME ##_lastTime = 0; /* static time needed for the last time we enqueue a callback */\ | |
static uint32_t FUNCTION_NAME ##_time = 0; /* static time needed to check if the function has been called after the initial call */\ | |
static uint32_t FUNCTION_NAME ##_timeoutHandle = NULL; /* Timeout handle for the system timer */\ | |
static ARGUMENTS_TYPE FUNCTION_NAME ##_lastParameters; /* Last parameters struct to be able to call inner function when timer gets called */\ | |
\ | |
int FUNCTION_NAME ##_inner(ARGUMENTS_TYPE parameters);\ | |
void FUNCTION_NAME ##_timerCallback();\ | |
int FUNCTION_NAME(ARGUMENTS_TYPE parameters);\ | |
\ | |
int FUNCTION_NAME(ARGUMENTS_TYPE parameters)\ | |
{\ | |
int result = 0;\ | |
FUNCTION_NAME ##_time = THROTTLE_ReadTime(); /* Read the core timer when called, updating the time */\ | |
FUNCTION_NAME ##_lastParameters = parameters; /* Set last parameters to ensure that callback can call with correct parameters */\ | |
if (FUNCTION_NAME ##_timeoutHandle == NULL) { /* If handle is not set to a valid handle, we don't have a timer running - create it here */\ | |
if (LEADING) { /* If we've enabled leading, immediately run inner function now */\ | |
result = FUNCTION_NAME ##_inner(parameters);\ | |
}\ | |
FUNCTION_NAME ##_lastTime = FUNCTION_NAME ##_time;\ | |
FUNCTION_NAME ##_timeoutHandle = THROTTLE_CallbackEnqueue(TIMEOUT_MS, &(FUNCTION_NAME ##_timerCallback)); /* Schedule future callback */\ | |
}\ | |
return result;\ | |
};\ | |
\ | |
void FUNCTION_NAME ##_timerCallback() /* Timer callback function */\ | |
{\ | |
if (FUNCTION_NAME ##_time - FUNCTION_NAME ##_lastTime >= TIMEOUT_MS || TRAILING) { /* If the time from the context is bigger or equal or we have enabled trailing, let's call our inner */\ | |
FUNCTION_NAME ##_inner(FUNCTION_NAME ##_lastParameters);\ | |
}\ | |
\ | |
FUNCTION_NAME ##_timeoutHandle = NULL; /* Reset timeout handle */\ | |
}\ | |
\ | |
int FUNCTION_NAME ##_inner | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment