diff --git a/Arduino_Threads.h b/Arduino_Threads.h index 6a69c2e..1d5935c 100644 --- a/Arduino_Threads.h +++ b/Arduino_Threads.h @@ -33,78 +33,81 @@ class Shared // template definition #define INCF(F) INCF_(F) #define INCF_(F) #F -class ArduinoThreadClass { -public: - void add(rtos::Thread* me) { - if (controller == NULL) { - controller = new rtos::Thread(osPriorityHigh, 512); - controller->start(mbed::callback(this, &ArduinoThreadClass::loop)); - } - list[idx++] = me; - } +#define _macroToString(sequence) #sequence - void ping(rtos::Thread* me) { - for (int i=0; i < idx; i++) { - if (me == list[i]) { - timestamps[i] = millis(); - } - } - } -private: - - void loop() { - while (1) { - for (int i = 0; i < idx; i++) { - if (millis() - timestamps[i] > 5000) { - // list[i]->terminate(); - // TODO: reorder threads and make list[i] == NULL - // Serial.println(list[i]->get_name() + String(" killed ")); +class ArduinoThreads { + private: + static rtos::EventFlags globalEvents; + uint32_t startFlags; + uint32_t stopFlags; + uint32_t loopDelay; + virtual void setup(void) {}; + virtual void loop(void) {}; + void execute() { + setup(); + // if startFlags have been passed then wait until all the flags are set + // before starting the loop. this is used to synchronize loops from multiple + // sketches. + globalEvents.wait_all(startFlags); + // if stopFlags have been passed stop when all the flags are set + // otherwise loop forever + while ( 1 ) { + loop(); + // on exit clear the flags that have forced us to stop. + // note that if two groups of sketches stop on common flags + // the first group will clear them so the second group may never + // exit + if (stopFlags!=0) { + if ((globalEvents.get()&stopFlags)!=stopFlags) { + globalEvents.clear(stopFlags); + return; + } + if ((rtos::ThisThread::flags_get()&stopFlags)!=stopFlags) { + rtos::ThisThread::flags_clear(stopFlags); + return; + } } - } - delay(1000); + // sleep for the time we've been asked to insert between loops + rtos::ThisThread::sleep_for(loopDelay); + } + } + rtos::Thread *t; + public: + // start this sketch + void start(int stacksize = 4096, uint32_t startFlags=0, uint32_t stopFlags=0) { + this->startFlags = startFlags; + this->stopFlags = stopFlags; + loopDelay=0; + t = new rtos::Thread(osPriorityNormal, stacksize, nullptr, _macroToString(tabname)); + t->start(mbed::callback(this, &ArduinoThreads::execute)); + } + // kill this sketch + void terminate() { + t->terminate(); + } + // send an event to all sketches at the same time + static void broadcastEvent(uint32_t event) { + globalEvents.set(event); + } + // send an event only to this sketch + void sendEvent(uint32_t event) { + t->flags_set(event); + } + // set the rate at which loop function will be called + void setLoopDelay(uint32_t delay) { + loopDelay = delay; } - } - - rtos::Thread* controller = NULL; - rtos::Thread* list[10] = {NULL}; - uint32_t timestamps[10] = {0}; - int idx = 0; }; -ArduinoThreadClass ArduinoThread; +rtos::EventFlags ArduinoThreads::globalEvents; -#define _macroToString(sequence) #sequence - -#define THD_ENTER(tabname) class CONCAT(tabname, Class) { \ +#define THD_ENTER(tabname) class CONCAT(tabname, Class) : public ArduinoThreads { \ +private: -#define THD_DONE(tabname) private: \ - void execute() { \ - ArduinoThread.add(t); \ - setup(); \ - while (1) { \ - loop(); \ - ArduinoThread.ping(t); \ - } \ - } \ - rtos::Thread* t; \ - \ - public: \ - void start(int stacksize = 4096) { \ - t = new rtos::Thread(osPriorityNormal, stacksize, nullptr, _macroToString(tabname)); \ - t->start(mbed::callback(this, &CONCAT(tabname,Class)::execute)); \ - } \ - void begin() { \ - start(); \ - } \ -}; \ +#define THD_DONE(tabname) \ +}; \ CONCAT(tabname,Class) tabname; -/* -#define NEWTHREAD(tabname) THD_ENTER(tabname) \ - \#include CONCAT(tabname, .h) \ - THD_DONE(tabname) -*/ - #include "Wire.h" #include "SerialDispatcher.h" \ No newline at end of file