diff --git a/Thread.cpp b/Thread.cpp index cd29d98..b5c3dc3 100644 --- a/Thread.cpp +++ b/Thread.cpp @@ -6,7 +6,7 @@ Thread::Thread(void (*callback)(void), unsigned long _interval){ _cached_next_run = 0; last_run = millis(); - ThreadID = (int)this; + ThreadID = (size_t)this; #ifdef USE_THREAD_NAMES ThreadName = "Thread "; ThreadName = ThreadName + ThreadID; @@ -31,12 +31,19 @@ void Thread::setInterval(unsigned long _interval){ _cached_next_run = last_run + interval; } -bool Thread::shouldRun(unsigned long time){ - // If the "sign" bit is set the signed difference would be negative - bool time_remaining = (time - _cached_next_run) & 0x80000000; +long Thread::tillRun(unsigned long time){ + if(!enabled) + return __LONG_MAX__; + else { + long time_remaining = (long) (_cached_next_run - time); + + return time_remaining; + } +} +bool Thread::shouldRun(unsigned long time){ // Exceeded the time limit, AND is enabled? Then should run... - return !time_remaining && enabled; + return tillRun(time) <= 0; } void Thread::onRun(void (*callback)(void)){ diff --git a/Thread.h b/Thread.h index 0e580a9..9fde34a 100644 --- a/Thread.h +++ b/Thread.h @@ -60,8 +60,11 @@ class Thread{ // If the current Thread is enabled or not bool enabled; + // If true this thread wanting to run will not be used to prevent sleeping in runWithDelay + bool canSleep = false; + // ID of the Thread (initialized from memory adr.) - int ThreadID; + size_t ThreadID; #ifdef USE_THREAD_NAMES // Thread Name (used for better UI). @@ -74,11 +77,16 @@ class Thread{ virtual void setInterval(unsigned long _interval); // Return if the Thread should be runned or not - virtual bool shouldRun(unsigned long time); + // Note: no longer virtual - instead override tillRun + bool shouldRun(unsigned long time); // Default is to check whether it should run "now" bool shouldRun() { return shouldRun(millis()); } + // Return # of msecs till this thread will run again (or MAXINT if it is disabled). + // If it is overdue the value will be negative + virtual long tillRun(unsigned long time); + // Callback set void onRun(void (*callback)(void)); diff --git a/ThreadController.cpp b/ThreadController.cpp index 7d8e41c..68ea202 100644 --- a/ThreadController.cpp +++ b/ThreadController.cpp @@ -38,6 +38,45 @@ void ThreadController::run(){ runned(); } +// Try to run our threads, return how long we can sleep before next needed +long ThreadController::runOrDelay(){ + // Run this thread before + if(_onRun != NULL) + _onRun(); + + unsigned long time = millis(); + int checks = 0; + long tillNext = __LONG_MAX__; + nextThread = NULL; + for(int i = 0; i < MAX_THREADS && checks < cached_size; i++){ + // Object exists? Is enabled? Timeout exceeded? + Thread *t = thread[i]; + if(t){ + checks++; + + long threadNext = t->tillRun(time); + if(threadNext <= 0){ // This thread is ready to run right now + t->run(); + // threadNext = t->tillRun(time); // Check when the current thread's new deadline + + if(!t->canSleep) { + tillNext = 0; // we ran something this tick, therefore tell caller it should skip the delay this time + nextThread = t; + } + } + else if(threadNext < tillNext && !t->canSleep) { + tillNext = threadNext; + nextThread = t; + } + } + } + + // ThreadController extends Thread, so we should flag as runned thread + runned(); + + return tillNext; +} + /* List controller (boring part) @@ -63,7 +102,7 @@ bool ThreadController::add(Thread* _thread){ return false; } -void ThreadController::remove(int id){ +void ThreadController::remove(size_t id){ // Find Threads with the id, and removes for(int i = 0; i < MAX_THREADS; i++){ if(thread[i]->ThreadID == id){ diff --git a/ThreadController.h b/ThreadController.h index 8e2888c..2ed46a3 100644 --- a/ThreadController.h +++ b/ThreadController.h @@ -19,7 +19,7 @@ #include "Thread.h" #include "inttypes.h" -#define MAX_THREADS 15 +#define MAX_THREADS 32 class ThreadController: public Thread{ protected: @@ -31,12 +31,15 @@ class ThreadController: public Thread{ // run() Method is overrided void run(); + // Try to run our threads, return how long we can sleep before next needed. + long runOrDelay(); + // Adds a thread in the first available slot (remove first) // Returns if the Thread could be added or not bool add(Thread* _thread); // remove the thread (given the Thread* or ThreadID) - void remove(int _id); + void remove(size_t _id); void remove(Thread* _thread); // Removes all threads @@ -48,6 +51,9 @@ class ThreadController: public Thread{ // Return the I Thread on the array // Returns NULL if none found Thread* get(int index); + + // For debugging it is useful to know the next child thread we want to execute + Thread* nextThread = NULL; }; #endif