Hi,
this is my latest work on thread manager.
Note: my goal is to do it in C for now.
- task_manager.h
#ifndef task_manager_h
#define task_manager_h
#include <inttypes.h>
#include <Arduino.h>
#include <SPI.h>
#include <string.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
////////////////////////////////////////////////////////////////////////////////////////
// enumerations
typedef enum: uint8_t {NOT_FINISHED, FINISHED, DONE}STATE;
//typedef enum: bool {NOT_FINISHED, FINISHED}STATE;
// variables
typedef void (*f_ptr)();
typedef void args;
// structs
typedef struct __attribute__((__packed__)) TASK{
uint8_t args_cnts;
args *tsk_args;
f_ptr tsk_fptr;
}TASK;
typedef struct __attribute__((__packed__)) THREAD{
uint8_t tsk_cnts; // task counts
uint8_t tsk_cntr; // task counter
STATE thrd_st; // thread flag states
STATE *tsk_st; // ptr to tsk_st in other scr files
}THREAD;
//functions/////////////////////////////////////////////////////////////////////////////
// threads
void run_thread(THREAD *thrd, TASK *tsk);
#endif
- task_manager.cpp
#include "task_manager.h"
#include "glcd_spi.h"
////////////////////////////////////////////////////////////////////////////////////////////
// main functions definitions
void run_thread(THREAD *thrd, TASK *tsk){
if(thrd->thrd_st == NOT_FINISHED){ // check if thread finished all tasks
if((thrd->tsk_cntr) < (thrd->tsk_cnts)){ // check linear task execution
if(*((STATE*)thrd->tsk_st) == NOT_FINISHED){ // check this task is NOT_FINISHED
switch((tsk+thrd->tsk_cntr)->args_cnts){ // run task by args_cnts
case 0: // dereferencing 0 args
((void(*)())(tsk+thrd->tsk_cntr)->tsk_fptr)();
break;
case 1: // dereferencing 1 args
((void(*)(uint8_t*))(tsk+thrd->tsk_cntr)->tsk_fptr)(
(uint8_t*)(tsk+thrd->tsk_cntr)->tsk_args+0);
break;
case 2: // dereferencing 2 args
((void(*)(uint8_t*,uint8_t*))(tsk+thrd->tsk_cntr)->tsk_fptr)(
(uint8_t*)(tsk+thrd->tsk_cntr)->tsk_args+0,
(uint8_t*)(tsk+thrd->tsk_cntr)->tsk_args+1);
break;
case 3: // dereferencing 3 args
((void(*)(uint8_t*,uint8_t*,uint8_t*))
(tsk+thrd->tsk_cntr)->tsk_fptr)(
(uint8_t*)(tsk+thrd->tsk_cntr)->tsk_args+0,
(uint8_t*)(tsk+thrd->tsk_cntr)->tsk_args+1,
(uint8_t*)(tsk+thrd->tsk_cntr)->tsk_args+2);
break;
case 4: // dereferencing 4 args
((void(*)(uint8_t*,uint8_t*,uint8_t*,uint8_t*))
(tsk+thrd->tsk_cntr)->tsk_fptr)(
(uint8_t*)(tsk+thrd->tsk_cntr)->tsk_args+0,
(uint8_t*)(tsk+thrd->tsk_cntr)->tsk_args+1,
(uint8_t*)(tsk+thrd->tsk_cntr)->tsk_args+2,
(uint8_t*)(tsk+thrd->tsk_cntr)->tsk_args+3);
break;
}
}
else{ // if current task is finished
Serial.print("thrd->tsk_cntr"); Serial.println(thrd->tsk_cntr);
thrd->tsk_cntr++; // go to next task
*((STATE*)thrd->tsk_st) = NOT_FINISHED; // reset finish st flag
}
}
}
else{
Serial.println("thrd FINISHED");
*((STATE*)thrd->thrd_st) = FINISHED;
}
}
- program_run.ino
#include "task_manager.h"
#include "glcd_spi.h"
#include "sensors_modules.h"
#include "arrays.h"
extern STATE lcd_st_flag;
void setup() {
Serial.begin(9600);
///////////////////////////////////// LCD THREAD /////////////////////////////////////
// allocate & initialize lcd thread
THREAD *lcd = (THREAD*)malloc(1*sizeof(THREAD));
TASK *lcd_tsk = (TASK*)malloc(4*sizeof(TASK)); // method #1
// lcd thread initialization
*lcd = (THREAD){4,0,NOT_FINISHED,&lcd_st_flag};
// lcd task initialization
*(lcd_tsk+0) = (TASK){0,(uint8_t*)0,(void(*)())glcd_init};
*(lcd_tsk+1) = (TASK){1,(uint8_t*)1,(void(*)())glcd_graphics_mode};
*(lcd_tsk+2) = (TASK){0,(uint8_t*)0,(void(*)())glcd_clr};
*(lcd_tsk+3) = (TASK){1,(uint8_t*)&PIC3,(void(*)())glcd_img};
while(lcd->thrd_st != FINISHED){
run_thread(lcd, lcd_tsk);
}
///////////////////////////////////// SERIAL THREAD /////////////////////////////////////
Serial.println("thread finished");
}
What you think ? How about my code ? I know there's a lot of casting ![]()