diff --git a/rtos/rtos/Thread.cpp b/rtos/rtos/Thread.cpp index 56415264c27..f9694bd6f6a 100644 --- a/rtos/rtos/Thread.cpp +++ b/rtos/rtos/Thread.cpp @@ -21,7 +21,7 @@ */ #include "Thread.h" -#include "mbed_error.h" +#include "mbed.h" #include "rtos_idle.h" // rt_tid2ptcb is an internal function which we exposed to get TCB for thread id @@ -32,9 +32,11 @@ extern "C" P_TCB rt_tid2ptcb(osThreadId thread_id); namespace rtos { -Thread::Thread(osPriority priority, - uint32_t stack_size, unsigned char *stack_pointer): - _tid(0), _dynamic_stack(stack_pointer == NULL) { +void Thread::constructor(osPriority priority, + uint32_t stack_size, unsigned char *stack_pointer) { + _tid = 0; + _dynamic_stack = (stack_pointer == NULL); + #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) _thread_def.tpriority = priority; _thread_def.stacksize = stack_size; @@ -42,15 +44,11 @@ Thread::Thread(osPriority priority, #endif } -Thread::Thread(void (*task)(void const *argument), void *argument, - osPriority priority, uint32_t stack_size, unsigned char *stack_pointer): - _tid(0), _dynamic_stack(stack_pointer == NULL) { -#if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) - _thread_def.tpriority = priority; - _thread_def.stacksize = stack_size; - _thread_def.stack_pointer = (uint32_t*)stack_pointer; -#endif - switch (start(task, argument)) { +void Thread::constructor(Callback task, + osPriority priority, uint32_t stack_size, unsigned char *stack_pointer) { + constructor(priority, stack_size, stack_pointer); + + switch (start(task)) { case osErrorResource: error("OS ran out of threads!\n"); break; @@ -64,13 +62,13 @@ Thread::Thread(void (*task)(void const *argument), void *argument, } } -osStatus Thread::start(void (*task)(void const *argument), void *argument) { - if (_tid != NULL) { +osStatus Thread::start(Callback task) { + if (_tid != 0) { return osErrorParameter; } #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) - _thread_def.pthread = task; + _thread_def.pthread = (void (*)(const void *))Callback::thunk; if (_thread_def.stack_pointer == NULL) { _thread_def.stack_pointer = new uint32_t[_thread_def.stacksize/sizeof(uint32_t)]; if (_thread_def.stack_pointer == NULL) @@ -82,7 +80,8 @@ osStatus Thread::start(void (*task)(void const *argument), void *argument) { _thread_def.stack_pointer[i] = 0xE25A2EA5; } #endif - _tid = osThreadCreate(&_thread_def, argument); + _task = task; + _tid = osThreadCreate(&_thread_def, &_task); if (_tid == NULL) { if (_dynamic_stack) delete[] (_thread_def.stack_pointer); return osErrorResource; diff --git a/rtos/rtos/Thread.h b/rtos/rtos/Thread.h index 275f6fe5c91..93880117ffd 100644 --- a/rtos/rtos/Thread.h +++ b/rtos/rtos/Thread.h @@ -24,6 +24,7 @@ #include #include "cmsis_os.h" +#include "Callback.h" namespace rtos { @@ -37,7 +38,9 @@ class Thread { */ Thread(osPriority priority=osPriorityNormal, uint32_t stack_size=DEFAULT_STACK_SIZE, - unsigned char *stack_pointer=NULL); + unsigned char *stack_pointer=NULL) { + constructor(priority, stack_size, stack_pointer); + } /** Create a new thread, and start it executing the specified function. @param task function to be executed by this thread. @@ -46,17 +49,78 @@ class Thread { @param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE). @param stack_pointer pointer to the stack area to be used by this thread (default: NULL). */ + Thread(mbed::Callback task, + osPriority priority=osPriorityNormal, + uint32_t stack_size=DEFAULT_STACK_SIZE, + unsigned char *stack_pointer=NULL) { + constructor(task, priority, stack_size, stack_pointer); + } + + /** Create a new thread, and start it executing the specified function. + @param obj argument to task. + @param method function to be executed by this thread. + @param argument pointer that is passed to the thread function as start argument. (default: NULL). + @param priority initial priority of the thread function. (default: osPriorityNormal). + @param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE). + @param stack_pointer pointer to the stack area to be used by this thread (default: NULL). + */ + template + Thread(T *obj, void (T::*method)(), + osPriority priority=osPriorityNormal, + uint32_t stack_size=DEFAULT_STACK_SIZE, + unsigned char *stack_pointer=NULL) { + constructor(mbed::Callback(obj, method), + priority, stack_size, stack_pointer); + } + + /** Create a new thread, and start it executing the specified function. + @param obj argument to task. + @param method function to be executed by this thread. + @param argument pointer that is passed to the thread function as start argument. (default: NULL). + @param priority initial priority of the thread function. (default: osPriorityNormal). + @param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE). + @param stack_pointer pointer to the stack area to be used by this thread (default: NULL). + */ + template + Thread(T *obj, void (*method)(T *), + osPriority priority=osPriorityNormal, + uint32_t stack_size=DEFAULT_STACK_SIZE, + unsigned char *stack_pointer=NULL) { + constructor(mbed::Callback(obj, method), + priority, stack_size, stack_pointer); + } + + /** Create a new thread, and start it executing the specified function. + Provided for backwards compatibility + @param task function to be executed by this thread. + @param argument pointer that is passed to the thread function as start argument. (default: NULL). + @param priority initial priority of the thread function. (default: osPriorityNormal). + @param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE). + @param stack_pointer pointer to the stack area to be used by this thread (default: NULL). + */ Thread(void (*task)(void const *argument), void *argument=NULL, osPriority priority=osPriorityNormal, uint32_t stack_size=DEFAULT_STACK_SIZE, - unsigned char *stack_pointer=NULL); + unsigned char *stack_pointer=NULL) { + constructor(mbed::Callback(argument, (void (*)(void *))task), + priority, stack_size, stack_pointer); + } /** Starts a thread executing the specified function. @param task function to be executed by this thread. - @param argument pointer that is passed to the thread function as start argument. (default: NULL). @return status code that indicates the execution status of the function. */ - osStatus start(void (*task)(void const *argument), void *argument=NULL); + osStatus start(mbed::Callback task); + + /** Starts a thread executing the specified function. + @param obj argument to task + @param method function to be executed by this thread. + @return status code that indicates the execution status of the function. + */ + template + osStatus start(T *obj, M method) { + return start(mbed::Callback(obj, method)); + } /** Wait for thread to terminate @return status code that indicates the execution status of the function. @@ -165,6 +229,17 @@ class Thread { virtual ~Thread(); private: + // Required to share definitions without + // delegated constructors + void constructor(osPriority priority=osPriorityNormal, + uint32_t stack_size=DEFAULT_STACK_SIZE, + unsigned char *stack_pointer=NULL); + void constructor(mbed::Callback task, + osPriority priority=osPriorityNormal, + uint32_t stack_size=DEFAULT_STACK_SIZE, + unsigned char *stack_pointer=NULL); + + mbed::Callback _task; osThreadId _tid; osThreadDef_t _thread_def; bool _dynamic_stack;