Skip to content

Instantly share code, notes, and snippets.

@DaBs
Created April 28, 2022 21:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DaBs/1be19c63757126bebc4f6d1368dc9813 to your computer and use it in GitHub Desktop.
Save DaBs/1be19c63757126bebc4f6d1368dc9813 to your computer and use it in GitHub Desktop.
#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