TeensyThreads starting function with multiple parameters

ladansedesdamnes

Active member
So, as stated in the title, I'm experimenting with the TeensyThreads library and would like to start several threads with a function taking multiple parameters.
I'm facing a couple of problems, due to the fact that threads.addThread() only takes a function with a single parameter, either int or void*.
I attempted to create a struct type which could take the parameters, pass a pointer to the variable containing the values, and casting it back to the proper type inside the function, but this is producing garbage (see code and output below).

Problems:
  1. Values in variable after cast (inside function) are garbage
  2. I'm guessing threads only start execution AFTER main code block, as printout in function shows the same values even after changing values in original variable before starting each thread

Code:
#include "TeensyThreads.h"

struct blinkParameters {
  int ledPin;
  int ledColor;
  int waitTime;
};

void blinkLed(void *p) {  
  // tested this to make sure it wasn't a case of badly allocated memory space
  //blinkParameters* param = (struct blinkParameters*) malloc(sizeof(*param));

  blinkParameters* param = (blinkParameters*) p;
  
  // PRINTOUT FUNCTION
  Serial.println(param->ledPin);
  Serial.println(param->ledColor);
  Serial.println(param->waitTime);

  threads.yield();
}

void setup() {
  Serial.begin(9600);
  Serial.println("Starting.......");

  blinkParameters temp = {0, 0x160000, 1000};
  
  // PRINTOUT 1
  Serial.println(temp.ledPin);
  Serial.println(temp.ledColor);
  Serial.println(temp.waitTime);

  threads.addThread(blinkLed, &temp);

  temp.ledPin = 1;
  temp.ledColor = 0x000016;
  temp.waitTime = 500;

  threads.addThread(blinkLed, &temp);
  
  // PRINTOUT 2
  Serial.println(temp.ledPin);
  Serial.println(temp.ledColor);
  Serial.println(temp.waitTime);

  temp.ledPin = 2;
  temp.ledColor = 0x001600;
  temp.waitTime = 1500;
  threads.addThread(blinkLed, &temp);
  
  // PRINTOUT 2
  Serial.println(temp.ledPin);
  Serial.println(temp.ledColor);
  Serial.println(temp.waitTime);

  Serial.println("Done.......");
}

14:57:01.989 -> Starting.......
14:57:01.989 -> 0
14:57:02.356 -> 1441792
14:57:02.356 -> 1000
14:57:02.356 -> 1
14:57:02.356 -> 22
14:57:02.356 -> 500
14:57:02.356 -> Done.......
14:57:02.356 -> 0
14:57:02.356 -> 0
14:57:02.356 -> 1171677184
14:57:02.356 -> 0
14:57:02.356 -> 0
14:57:02.356 -> 1171677184
14:57:02.356 -> 0
14:57:02.356 -> 0
14:57:02.356 -> 1171677184


I'm not that well versed in multi-threaded programming outside of C#, so there's a massive probability that I'm doing something (or a lot) wrong here in regards to that, but I'm kind of stumped as to why I'm not able to get any proper values from the parameter in itself (as the garbage isn't even the same as the last assigned value)
 
Quick guess: The passed pointer is saved at time of .addThread( ..., TEMP). So subsequent calls to blinkLed() are pointing to that space on the stack that was in use during setup().

Make " blinkParameters temp = {0, 0x160000, 1000}; " a static or global scope : blinkParameters gPerm = {0, 0x160000, 1000};

Code:
void setup() {
...
  blinkParameters temp = {0, 0x160000, 1000};
  
  // PRINTOUT 1
  Serial.println(temp.ledPin);
  Serial.println(temp.ledColor);
  Serial.println(temp.waitTime);

  threads.addThread(blinkLed, &temp);
 
blinkParameters temp is a local variable created on the stack (push) within setup(). Once setup() returns, the memory this variable once resided is reclaimed (pop) and thus loses context.
In other words, temp disappears once setup() returns.
The other problem is temp is shared amongst all four (initial + the 3 created) threads but is unprotected.
I would make blinkParameters temp a static global then have a single 'blinkParameters' per thread, thus 'blinkParameters temp[3]' in this case.
 
Thank you both for your replies!

I ended up following your suggestions and got it to work by creating a global struct array with the max amount of simultaneous values, and passing a pointer to the specific array index to the function.
Since I need to update these values in runtime, I can't make the variable static, but having it as global with preallocated size makes this work!
 
Back
Top