Thread.start broken in current mbed-os release

08 Nov 2016

The following demo program or any other program which uses the same thread start call construction will not compile in the online ide The call follows the syntax of the current online documentation for the mbed-os Thread class

#include "mbed.h"
#include "Thread.h"
#include "Callback.h"

DigitalOut led1(LED1);

#define mySignal 0x01

void myWorker(void const* args)
 {
      MyTest* t = (MyTest*)args;
      int i;
      i++;
      osSignalSet(t->_id, mySignal);
 }
     

class MyTest 
{
    public:
    osThreadId _id;
    Thread _thread;
        
    MyTest(osThreadId id) :
    _id(id),
    _thread()
    {
     osStatus status =  _thread.start(this, &MyTest::myWorker);  
//      _thread.start(mbed::Callback<void>(this, &Test::myWorker));  
    }
        
};

// main() runs in its own thread in the OS
// (note the calls to Thread::wait below for delays)
int main() {
    osThreadId id = Thread::gettid();
    MyTest* test = new MyTest(id);
    while (true) {
        led1 = !led1;
        Thread::wait(500);
    }
}

The compiler outputs the following warning and error messages during the build

Warning: Function "rtos::Thread::start(T *, M) [with T=MyTest, M=void (MyTest::*)(const void *)]" (declared at <a href="#" onmousedown="mbed_doc_goto('/mbed-os-Thread_Testextras/mbed-os.lib/rtos/Thread.h', '214'); return false;">/extras/mbed-os.lib/rtos/Thread.h:214</a>) was declared deprecated ("The start function does not support cv-qualifiers. Replaced by thread.start(callback(obj, method)). [since mbed-os-5.1]") in "main.cpp", Line: 26, Col: 34

Error: No instance of overloaded function "rtos::Thread::start" matches the argument list in "extras/mbed-os.lib/rtos/Thread.h", Line: 215, Col: 17

Changing the call from Thread.start( .... to Thread.start(callback(....

eliminates the warning message and changes the error message to Error: No instance of overloaded function "rtos::Thread::start" matches the argument list in "main.cpp", Line: 27, Col: 36

Changing the call from Thread.start( .... to Thread.start(Callback::Callback(.... or Thread.start(mbed:::Callback<MyTest*>(... generated the following error Error: Incomplete type is not allowed in "MyTest.cpp", Line: 18, Col: 39

04 Nov 2016

Can you paste the full code example? I am having a little trouble reproducing with the code segments above.

Both of these compile for me:

Example one that generates warning mentioned above

#include "mbed.h"

class MyClass {
public:
    MyClass(Thread _thread){
        _thread.start(this, &MyClass::do_stuff);
    }
    void do_stuff(){
        printf("hi\n");
    }
};

int main() {
    Thread _thread;
    MyClass myclass(_thread);
}

Example two with callback used

#include "mbed.h"

class MyClass {
public:
    MyClass(Thread _thread){
        _thread.start(callback(this, &MyClass::do_stuff));
    }
    void do_stuff(){
        printf("hi\n");
    }
};

int main() {
    Thread _thread;
    MyClass myclass(_thread);
}
08 Nov 2016

The code was in the first post however it was some how mangled before it made the forum page here it is again Hop it doesn't get mangled again The thread stuff is a strip down version of a construction used in the Multi-Tech mbed base Mdot Lora system pasted into the mbed-os brinkly example

#include "mbed.h" 
#include "Thread.h" 
#.include "Callback.h" 

DigitalOut led1(LED1);

#define mySignal 0x01

 void myWorker(void const* args)
 { 
         MyTest* t = (MyTest*)args;
         int i; 
         i++;
        osSignalSet(t->_id, mySignal); 
}

 class MyTest 
{
    public:
    osThreadId _id;
    Thread _thread; 

MyTest(osThreadId id) :  _id(id),  _thread()
 { 
         osStatus status = _thread.start(this, &MyTest::myWorker);
       //  osStatus status = _thread.start(mbed::Callback<void>(this, &Test::myWorker));
 }

};

 main() runs in its own thread in the OS  (note the calls to Thread::wait below for delays) 
int main()
 { 
       osThreadId id = Thread::gettid(); 
       MyTest* test = new MyTest(id);
      while (true)
        { 
         led1 = !led1; 
         Thread::wait(500);
        }
}
06 Nov 2016

A bit has changed with that API, I believe. The void pointer parameter is no longer necessary. This works for me.

#include "mbed.h" 
 
DigitalOut led1(LED1);
 
#define mySignal 0x01
 
 class MyTest 
{
    public:
    osThreadId _id;
    Thread _thread; 
 
     void myWorker()
 { 
         int i; 
         i++;
        osSignalSet(_id, mySignal); 
}
 
MyTest(osThreadId id) :  _id(id),  _thread()
 { 
         //osStatus status = _thread.start(this, &MyTest::myWorker);
         _thread.start(callback(this, &MyTest::myWorker));
 }
 
};

int main()
 { 
       osThreadId id = Thread::gettid(); 
       MyTest* test = new MyTest(id);
      while (true)
        { 
         led1 = !led1; 
         Thread::wait(500);
        }
}
08 Nov 2016

Thank your for you input Sarah

I however made a critical error when cutting the real world code down to a simple demo app. In the real world code the thread worker function is not a member of the class but rather an external function which operates on instances of the class passed to the function via its pointer argument.

I have update the demo code examples to match the real world usage construction

Indeed if the worker function is a class member a pointer argument is not needed and the code will compile under mbed 5 if the argument is removed as you have shown.

However for the external function case the pointer argument is required and code which worked under mbed 2 will not compile under mbed 5

One either gets a

Error: No instance of overloaded function "rtos::Thread::start" matches the argument list in "extras/mbed-os.lib/rtos/Thread.h", Line: 215, Col: 17 when one lets the compiler automatically remap the deprecated Tread,start(... function to its replacement function

or the error

Error: Incomplete type is not allowed in "MyTest.cpp", Line: 17, Col: 39 if one explicitly codes the replacement form of the function Thread::start(mbed::Callback<void>(...

08 Nov 2016

Hey Steve,

Sorry for all the troubles. I was able to get the following to compile:

#include "mbed.h"
 
DigitalOut led1(LED1);
 
#define mySignal 0x01

class MyTest;

void myWorker(const void* args);
 
class MyTest 
{
    public:
    osThreadId _id;
    Thread _thread;
        
    MyTest(osThreadId id) :
    _id(id),
    _thread()
    {
     _thread.start(callback(&myWorker, this)); 
//      _thread.start(mbed::Callback<void>(this, &Test::myWorker));  
    }
        
};

void myWorker(const void* args)
 {
      MyTest* t = (MyTest*)args;
      int i;
      i++;
      osSignalSet(t->_id, mySignal);
 }
     
 
// main() runs in its own thread in the OS
// (note the calls to Thread::wait below for delays)
int main() {
    osThreadId id = Thread::gettid();
    MyTest* test = new MyTest(id);
    while (true) {
        led1 = !led1;
        Thread::wait(500);
    }
}

We are currently working on documentation for this usage, so it certainly isn't made clear anywhere. Just make sure your mbed-os is updated in the program you are writing. The code for this usage can be seen here, but it is not feasible for you to have known that.

10 Nov 2016

Sarah

Again thank for your assistance

I was also able to get the code to compile with mbed-os 5.2; however I was not able to get it to compile with mbed-os 5.1.5

Until a couple of days ago I was stuck with 5.1.5 by the need to used the third party Multi-Tech Lora Radio library. Due to regulatory constrains imposed by the Federal Communication Commission (FCC) they can only distribute that library in binary form. The available libraries where built using mbed-os 5.1.5 and were incompatible with the 5.2 and later mbed-os releases. Multi-Tech recently released new develop version of their library which are compatible with the 5.2 & 5.2.2 mbed-os releases; however the production version of the library still requires the 5.1.5 version of the mbed-os library.

I am now able to move forward with my project

Thank you again

23 Nov 2016

Steve,

Your issue is caused by an invalid type deduction during the instantiation of the Thread::start member function. Constraints over types in input have been relaxed since but if you need to compile with mbed OS 5.1.5 you can do the following:

#include "mbed.h"

class MyTest;
 
void myWorker(const void* args);
 
class MyTest 
{        
    MyTest(osThreadId id) :
    _id(id),
    _thread()
    {
     // this is casted to the type expected by the myWorker function.
     // It is important to specify cv qualifier, they won't be adjusted in mbed os 5.1.5
     _thread.start(static_cast<const void*>(this), myWorker); 
    }        
};
21 Apr 2017

I'm confused... the code proposed by sarah the 6.11 compiles for me... I didn't test the one proposed the 8.11. And I can not understand how we can have such different syntax :

thread.start(callback(this, &MyTest::myWorker));
thread.start(callback(&myWorker, this));

Is this due to some changes on the mbed libraries ? or what ?