Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: TeensyThreads starting function with multiple parameters

  1. #1

    TeensyThreads starting function with multiple parameters

    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)

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,433
    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);

  3. #3
    Senior Member
    Join Date
    Mar 2017
    Location
    Ireland
    Posts
    101
    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.

  4. #4
    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!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •