Components and supplies
Arduino MKR Zero
Arduino UNO
Teensy 3.6
Project description
Code
ThreadHandler
Repository
ExecutionDemo
c_cpp
Example code
1#include "ThreadHandler.h" 2 3void simulateWork() 4{ 5 delay(1000); 6} 7 8//Configures the interrupt timer ticks in us (1000 gives 1ms). 9//This tick time will be the lowest time resolution for thread periods and offsets. 10//Setting the value to 0 leaves the Interrupt timers defautl tick, this is usefull since 11//this setting will not be in conflict with other libraries and analogWrite. 12SET_THREAD_HANDLER_TICK(0); 13 14//This macro configures which timer should be used for generating 15//the interrupts driving the ThreadHandler. 16//The user can implement there own InterruptTimer by inhereting 17//from the ThreadHandler::InterruptTimerInterface. This is usefull 18//for adding support for new boards that this library does not support yet. 19//Currently the library supports SAMD21 and all version supported by the 20//TimerOne library. To see how to do this lock in the "platformSpecificClasses.h". 21THREAD_HANDLER(InterruptTimer::getInstance()); 22 23//This is the first thread class with its run function 24//configured to run every 20s with an offset of 0s and priority 1. 25//The scheduling scheme of the ThreadHandler library is as follows: 26// 1) Highest priority first. 27// 2) If the priority is the same then 28// the thread with the earliest dedline 29// is executed first. 30// 3) If two threads have the same dedline then 31// the first created thread will execute first. 32// 4) A thread can only be intrrupted by threads with 33// higher priority. 34// 5) Once a thread is executing it will block execution 35// for all threads with lower priority untill the run 36// function returns. 37// 6) The loop function has priority -128 compared to 38// ThreadHandler threads. 39class TestThread1 : public Thread 40{ 41public: 42 TestThread1() : Thread(1, 20000000, 0) 43 { 44 } 45 46 virtual ~TestThread1() 47 { 48 } 49 50 virtual void run() 51 { 52 { 53 //The ThreadInterruptBlocker class is used 54 //to avoid race conditions between threads. 55 //When creating a blocker the interrupt timers 56 //interrupt vector is dissabled and when it is 57 //destroyd it enables the interrupt again. 58 //It does not affect global interrupts, only 59 //the interrupt timer. The blocker object also 60 //has a lock and an unlock function to be able 61 //to dissable/enable interrupts without 62 //creating/destroying blocker objects. 63 ThreadInterruptBlocker block; 64 Serial.println(" ___"); 65 Serial.println(" |T1|"); 66 } 67 for (int i = 0; i < 3; i++) 68 { 69 simulateWork(); 70 ThreadInterruptBlocker block; 71 Serial.println(" | #|"); 72 } 73 { 74 ThreadInterruptBlocker block; 75 Serial.println(" ^^"); 76 } 77 } 78}; 79 80//This is the second thread class with its run function 81//configured to run every 20s with an offset of 6s and priority 1. 82//If the offset of TestThread2 would be set to 0s, in this case, TestThread1 83//and TestThread2 objects whould be qued up to run directly after each 84//other, since they both have the same period time. Now TestThread2 object 85//run 6s after TestThread1 objects. 86class TestThread2 : public Thread 87{ 88public: 89 TestThread2() : Thread(1, 20000000, 6000000) 90 { 91 } 92 93 virtual ~TestThread2() 94 { 95 } 96 97 virtual void run() 98 { 99 { 100 ThreadInterruptBlocker block; 101 Serial.println(" ___"); 102 Serial.println(" |T2|"); 103 } 104 for (int i = 0; i < 3; i++) 105 { 106 simulateWork(); 107 ThreadInterruptBlocker block; 108 Serial.println(" | #|"); 109 } 110 { 111 ThreadInterruptBlocker block; 112 Serial.println(" ^^"); 113 } 114 } 115}; 116 117//create the thread objects. When a thread object 118//is created it will add it self to the ThreadHandler 119//automatically. 120TestThread1* testThread1 = new TestThread1(); 121TestThread2* testThread2 = new TestThread2(); 122 123CodeBlocksThread* testThread3 = nullptr; 124unsigned int test = 0; 125FunctionalWrapper<bool>* delayFunction = createFunctionalWrapper<bool>( 126 [&test]() 127 { 128 test++; 129 if (test > 1000) 130 { 131 test = 0; 132 return true; 133 } 134 return false; 135 }); 136 137void setup() 138{ 139 Serial.begin(115200); 140 141 //This creates the third thread object directly without first defining 142 //a thread type. This thread will run its lambda function 143 //every 4s with an offset of 0s and priority 2. 144 testThread3 = createThreadWithCodeBlocks(2, 4000000, 0, 145 []() 146 { 147 { 148 ThreadInterruptBlocker block; 149 Serial.println(" ___"); 150 Serial.println(" |T3|"); 151 } 152 for (int i = 0; i < 1; i++) 153 { 154 simulateWork(); 155 ThreadInterruptBlocker block; 156 Serial.println(" | #|"); 157 } 158 { 159 ThreadInterruptBlocker block; 160 Serial.println(" ^^"); 161 } 162 //Thread::delayNextCodeBlock(500000); 163 Thread::delayNextCodeBlockUntil(delayFunction); 164 }); 165 166 testThread3->addCodeBlock( 167 []() 168 { 169 Serial.println(" | #|secCodeBlock"); 170 }); 171 172 //start executing threads 173 ThreadHandler::getInstance()->enableThreadExecution(); 174} 175 176int loopCount = 0; 177 178//The loop function has priority -128 and will be interrupted 179//by all the thread objects 180void loop() 181{ 182 { 183 ThreadInterruptBlocker block; 184 Serial.println("___"); 185 Serial.println("|LP|"); 186 } 187 for (int i = 0; i < 6; i++) 188 { 189 simulateWork(); 190 ThreadInterruptBlocker block; 191 Serial.println("| #|"); 192 } 193 { 194 ThreadInterruptBlocker block; 195 Serial.println(" ^^"); 196 } 197 if (loopCount == 10) 198 { 199 loopCount = 11; 200 201 //It is also possible to delete threads 202 //to stop executing them. However if a thread 203 //is supposed to be started and stopped multiple 204 //times it is more efficient to just add an if 205 //statement first in the run function checking 206 //if the function should do any work. 207 ThreadInterruptBlocker block; 208 delete testThread3; 209 Serial.println("T3 deleted"); 210 } 211 else 212 { 213 loopCount++; 214 } 215} 216
ThreadHandler
Repository
ExecutionDemo
c_cpp
Example code
1#include "ThreadHandler.h" 2 3void simulateWork() 4{ 5 delay(1000); 6} 7 8//Configures 9 the interrupt timer ticks in us (1000 gives 1ms). 10//This tick time will be the 11 lowest time resolution for thread periods and offsets. 12//Setting the value to 13 0 leaves the Interrupt timers defautl tick, this is usefull since 14//this setting 15 will not be in conflict with other libraries and analogWrite. 16SET_THREAD_HANDLER_TICK(0); 17 18//This 19 macro configures which timer should be used for generating 20//the interrupts driving 21 the ThreadHandler. 22//The user can implement there own InterruptTimer by inhereting 23//from 24 the ThreadHandler::InterruptTimerInterface. This is usefull 25//for adding support 26 for new boards that this library does not support yet. 27//Currently the library 28 supports SAMD21 and all version supported by the 29//TimerOne library. To see how 30 to do this lock in the "platformSpecificClasses.h". 31THREAD_HANDLER(InterruptTimer::getInstance()); 32 33//This 34 is the first thread class with its run function 35//configured to run every 20s 36 with an offset of 0s and priority 1. 37//The scheduling scheme of the ThreadHandler 38 library is as follows: 39// 1) Highest priority first. 40// 2) If the priority 41 is the same then 42// the thread with the earliest dedline 43// is 44 executed first. 45// 3) If two threads have the same dedline then 46// the 47 first created thread will execute first. 48// 4) A thread can only be intrrupted 49 by threads with 50// higher priority. 51// 5) Once a thread is executing 52 it will block execution 53// for all threads with lower priority untill the 54 run 55// function returns. 56// 6) The loop function has priority -128 57 compared to 58// ThreadHandler threads. 59class TestThread1 : public Thread 60{ 61public: 62 63 TestThread1() : Thread(1, 20000000, 0) 64 { 65 } 66 67 virtual 68 ~TestThread1() 69 { 70 } 71 72 virtual void run() 73 { 74 { 75 76 //The ThreadInterruptBlocker class is used 77 //to avoid 78 race conditions between threads. 79 //When creating a blocker the interrupt 80 timers 81 //interrupt vector is dissabled and when it is 82 //destroyd 83 it enables the interrupt again. 84 //It does not affect global interrupts, 85 only 86 //the interrupt timer. The blocker object also 87 //has 88 a lock and an unlock function to be able 89 //to dissable/enable interrupts 90 without 91 //creating/destroying blocker objects. 92 ThreadInterruptBlocker 93 block; 94 Serial.println(" ___"); 95 Serial.println(" 96 |T1|"); 97 } 98 for (int i = 0; i < 3; i++) 99 { 100 101 simulateWork(); 102 ThreadInterruptBlocker block; 103 Serial.println(" 104 | #|"); 105 } 106 { 107 ThreadInterruptBlocker block; 108 109 Serial.println(" ^^"); 110 } 111 } 112}; 113 114//This 115 is the second thread class with its run function 116//configured to run every 20s 117 with an offset of 6s and priority 1. 118//If the offset of TestThread2 would be 119 set to 0s, in this case, TestThread1 120//and TestThread2 objects whould be qued 121 up to run directly after each 122//other, since they both have the same period time. 123 Now TestThread2 object 124//run 6s after TestThread1 objects. 125class TestThread2 126 : public Thread 127{ 128public: 129 TestThread2() : Thread(1, 20000000, 6000000) 130 131 { 132 } 133 134 virtual ~TestThread2() 135 { 136 } 137 138 virtual 139 void run() 140 { 141 { 142 ThreadInterruptBlocker block; 143 144 Serial.println(" ___"); 145 Serial.println(" |T2|"); 146 147 } 148 for (int i = 0; i < 3; i++) 149 { 150 simulateWork(); 151 152 ThreadInterruptBlocker block; 153 Serial.println(" | 154 #|"); 155 } 156 { 157 ThreadInterruptBlocker block; 158 159 Serial.println(" ^^"); 160 } 161 } 162}; 163 164//create 165 the thread objects. When a thread object 166//is created it will add it self to 167 the ThreadHandler 168//automatically. 169TestThread1* testThread1 = new TestThread1(); 170TestThread2* 171 testThread2 = new TestThread2(); 172 173CodeBlocksThread* testThread3 = nullptr; 174unsigned 175 int test = 0; 176FunctionalWrapper<bool>* delayFunction = createFunctionalWrapper<bool>( 177 178 [&test]() 179 { 180 test++; 181 if (test > 1000) 182 { 183 184 test = 0; 185 return true; 186 } 187 return 188 false; 189 }); 190 191void setup() 192{ 193 Serial.begin(115200); 194 195 196 //This creates the third thread object directly without first defining 197 //a 198 thread type. This thread will run its lambda function 199 //every 4s with an 200 offset of 0s and priority 2. 201 testThread3 = createThreadWithCodeBlocks(2, 202 4000000, 0, 203 []() 204 { 205 { 206 ThreadInterruptBlocker 207 block; 208 Serial.println(" ___"); 209 Serial.println(" 210 |T3|"); 211 } 212 for (int i = 0; i < 1; i++) 213 214 { 215 simulateWork(); 216 ThreadInterruptBlocker 217 block; 218 Serial.println(" | #|"); 219 } 220 221 { 222 ThreadInterruptBlocker block; 223 Serial.println(" 224 ^^"); 225 } 226 //Thread::delayNextCodeBlock(500000); 227 228 Thread::delayNextCodeBlockUntil(delayFunction); 229 }); 230 231 232 testThread3->addCodeBlock( 233 []() 234 { 235 Serial.println(" 236 | #|secCodeBlock"); 237 }); 238 239 //start executing threads 240 241 ThreadHandler::getInstance()->enableThreadExecution(); 242} 243 244int loopCount 245 = 0; 246 247//The loop function has priority -128 and will be interrupted 248//by 249 all the thread objects 250void loop() 251{ 252 { 253 ThreadInterruptBlocker 254 block; 255 Serial.println("___"); 256 Serial.println("|LP|"); 257 258 } 259 for (int i = 0; i < 6; i++) 260 { 261 simulateWork(); 262 263 ThreadInterruptBlocker block; 264 Serial.println("| #|"); 265 } 266 267 { 268 ThreadInterruptBlocker block; 269 Serial.println(" ^^"); 270 271 } 272 if (loopCount == 10) 273 { 274 loopCount = 11; 275 276 //It 277 is also possible to delete threads 278 //to stop executing them. However 279 if a thread 280 //is supposed to be started and stopped multiple 281 //times 282 it is more efficient to just add an if 283 //statement first in the run function 284 checking 285 //if the function should do any work. 286 ThreadInterruptBlocker 287 block; 288 delete testThread3; 289 Serial.println("T3 deleted"); 290 291 } 292 else 293 { 294 loopCount++; 295 } 296} 297
Downloadable files
ExecutionDemo connection example
Connection example for ExecutionDemo
ExecutionDemo connection example
Comments
Only logged in users can leave comments
adamb314
0 Followers
•0 Projects
0