diff --git a/StaticThreadController.h b/StaticThreadController.h index 6e316ea..2e4b6cc 100644 --- a/StaticThreadController.h +++ b/StaticThreadController.h @@ -42,7 +42,7 @@ class StaticThreadController: public Thread{ { // Run this thread before if(_onRun != nullptr && shouldRun()) - _onRun(); + _onRun(_param); for(int i = 0; i < N; i++){ // Is enabled? Timeout exceeded? diff --git a/Thread.cpp b/Thread.cpp index cd29d98..067dc67 100644 --- a/Thread.cpp +++ b/Thread.cpp @@ -1,9 +1,10 @@ #include "Thread.h" -Thread::Thread(void (*callback)(void), unsigned long _interval){ +Thread::Thread(void (*callback)(void*), unsigned long _interval, void *param){ enabled = true; onRun(callback); _cached_next_run = 0; + _param = param; last_run = millis(); ThreadID = (int)this; @@ -39,13 +40,13 @@ bool Thread::shouldRun(unsigned long time){ return !time_remaining && enabled; } -void Thread::onRun(void (*callback)(void)){ - _onRun = callback; +void Thread::onRun(void (*callback)(void*)){ + _onRun = callback; } void Thread::run(){ if(_onRun != NULL) - _onRun(); + _onRun(_param); // Update last_run and _cached_next_run runned(); diff --git a/Thread.h b/Thread.h index 0e580a9..f3eccc3 100644 --- a/Thread.h +++ b/Thread.h @@ -53,7 +53,10 @@ class Thread{ void runned() { runned(millis()); } // Callback for run() if not implemented - void (*_onRun)(void); + void (*_onRun)(void *); + + // Pointer to a parameter used in callback + void *_param; public: @@ -68,7 +71,7 @@ class Thread{ String ThreadName; #endif - Thread(void (*callback)(void) = NULL, unsigned long _interval = 0); + Thread(void (*callback)(void*) = NULL, unsigned long _interval = 0, void *param = NULL); // Set the desired interval for calls, and update _cached_next_run virtual void setInterval(unsigned long _interval); @@ -80,7 +83,7 @@ class Thread{ bool shouldRun() { return shouldRun(millis()); } // Callback set - void onRun(void (*callback)(void)); + void onRun(void (*callback)(void *)); // Runs Thread virtual void run(); diff --git a/ThreadController.cpp b/ThreadController.cpp index af5f1d9..3784b29 100644 --- a/ThreadController.cpp +++ b/ThreadController.cpp @@ -20,7 +20,7 @@ ThreadController::ThreadController(unsigned long _interval): Thread(){ void ThreadController::run(){ // Run this thread before if(_onRun != NULL) - _onRun(); + _onRun(_param); // TODO #ivan, why is it needed? unsigned long time = millis(); int checks = 0; diff --git a/examples/ParameterizedCallback/ParameterizedCallback.ino b/examples/ParameterizedCallback/ParameterizedCallback.ino new file mode 100644 index 0000000..af411ce --- /dev/null +++ b/examples/ParameterizedCallback/ParameterizedCallback.ino @@ -0,0 +1,72 @@ +/* + This example shows how to use a single callback function for multiple threads. + Each of 5 threads lights up one of 5 LEDs in randomly selected intervals. + Single callback function is called with a pointer to a data structure, which + can be used for identifying a pin it needs to light up and thread point to set up + a new waiting interval. + + author: Ivan Koryakovskiy + date: 2017-07-29 +*/ + +#include +#include + +typedef struct blinkParam +{ + Thread *th; + int pin; +}; + +ThreadController g_controller = ThreadController(); + +// Creating 5 controllers, each will call same callback function, +// but with a different thread pointer as a parameter, and therefore different led +const int g_th_num = 5; +Thread *g_th[g_th_num]; +blinkParam *g_param[g_th_num]; + +int nextInterval() +{ + // next time call thread after 1-5 seconds + return 1000 + random(4000); +} + +void blinkLed(void *param) +{ + // cast parameters to data structure + blinkParam *bp = static_cast(param); + + digitalWrite(bp->pin, HIGH); + delayMicroseconds(10000); + digitalWrite(bp->pin, LOW); + + bp->th->setInterval(nextInterval()); +} + +void setup() +{ + randomSeed(analogRead(0)); + + // create five threads to light up pins D9-D13 (Arduino Nano) + int pin = 9; + for (int i = 0; i < g_th_num; i++) + { + g_param[i] = new blinkParam; + + // note that parameter includes placeholders for thread pointer and pin number + g_th[i] = new Thread(blinkLed, nextInterval(), static_cast(g_param[i])); + + g_param[i]->th = g_th[i]; + g_param[i]->pin = pin + i; + + g_controller.add(g_th[i]); + + pinMode(g_param[i]->pin, OUTPUT); + } +} + +void loop() +{ + g_controller.run(); +}