Can I make a class member function a task's TaskFunction_t pcTaskCode?

Hello all,
I have two tasks doing the same job on different data and hardware peripherals. Now I think of making a class for this. But how can I create the tasks and give each the function of one class instance? Something like this:

class my_class
{
  public:
  void task_main_func (void);
....
}

my_class my_tasks [2];

xTaskCreateStatic (my_tasks [0].task_main_func, ....);
xTaskCreateStatic (my_tasks [1].task_main_func, ....);

This fails to compile because the function signature does not match.
How to do it? The pointer needed for a TaskFunction_t could be the this pointer of a class member function.

Thanks for any hint
Martin

Normally you do this kind of thing by having a dispatcher function as the task function. You pass the this pointer of your class instance as the task parameter, and the dispatcher then invokes your instance’s task_main_func member via the coerced instance pointer.

Thanks for your answer.
Sorry I don’t fully understand, can you make a short example please?

void DispatcherFn(void *arg)
{
my_class *x = (my_class *)arg
x->task_main_func();
}

xTaskCreateStatic(…,DispatcherFn,…(void *)myTasks[0],…);

Ah, ok, thanks for the example.
I found myself this solution and thought it could be more straight forward:

  void task0_main_func (void * pvParameters)
  {
    my_tasks  [0].task_main_func ();
  }
  void task1_main_func (void * pvParameters)
  {
    my_tasks  [1].task_main_func ();
  }

Yours is shorter but more tricky to understand (I think). But if you have more than 2 identical tasks, yours is surely better.
Just to be sure:
Either entry function is called only once when the tasks enters running state for the first time, right? After that the current program position is recalled and the entry function play no more roll.
Thanks
Martin

I’m not quite sure I understand what you are getting at here. When you break into, say, somewhere into my_class.task_main_func(), your debugger will of course remember the full call stack down to either of your task_main_func or (in my case) the dispatcher fn, but (assuming your my_class.task_main_func() never returns, which is the normal and regular behavior), control flow never unwinds to the “shell” function.

Your solution isx perfectly ok. As you suggest, mine comes in handy when there is a variable number of instances. Say, for example, that your application is a communication server where you can activate a configuration dependent number of serial ports at runtime. In such a case, you typically have a class that represents a serial port and that has a thread fn as a member. In that use case, it is an advantage not to have to pass a task fn into xTaskCreateStatic() that is linked to the instance but a generic function.

Ok, thanks for shring this extra information, your example makes it very clear.

1 Like