Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   C/C++ (http://www.chiefdelphi.com/forums/forumdisplay.php?f=183)
-   -   Member function as Task (http://www.chiefdelphi.com/forums/showthread.php?t=143815)

cantdecide 02-13-2016 07:05 PM

Member function as Task
 
I'm using the Task class in WPILib to poll for IMU data at the moment, and in doing so I've discovered that I can't cast member functions to a FUNCPTR or a VOIDFUNCPTR. To solve this, I created a static class which holds an IMU instance and has a static function that calls the instance's update method. That did it, but now I have more methods that I'd like to call in the background. I figured that creating a class for every member function is not a very extendable solution, so my question is, how can I create Tasks with member functions? Or am I missing something and can cast a member function to a FUNCPTR? Do I even need to cast functions to FUNCPTRs? The online examples I saw casted functions to FUNCPTRs, and directly passing functions as arguments throws a compile-time error.

duane 02-13-2016 10:25 PM

Re: Member function as Task
 
The technique is to create a static function in your class. The first parameter to your function is this. In the function, dispatch to the member function using the this pointer. This technique is a kind of a thunk.

Code:

class MyClass
{
  private:
    static void sProcessTask(MyClass* self, int someParam);
    void DispatchTask();
    void ProcessTask();
}

void MyClass::sProcessTask(MyClass* self, int someParam)
{
  self.ProcessTask(someParam);
}

void MyClass::DispatchTask()
{
  Task myTask = new Task("MyTask", sProcessTask, this, someParam);
}

void MyClass::ProcessTask(int param)
{
  // do something on task
}

(Warning: Uncompiled and untested)

cantdecide 02-14-2016 06:12 AM

Re: Member function as Task
 
Thanks, that works.

euhlmann 02-14-2016 11:13 AM

Re: Member function as Task
 
You can use a member function but you'll have to pass an instance to Task. I've looked in the Task source and it should work, since it forwards all of its arguments to thread. Thread internally detects if you gave a member function pointer and uses the first argument as the instance to call the function from.
Code:

class MyClass
{
  private:
    void DispatchTask();
    void ProcessTask(int param);
}

void MyClass::DispatchTask()
{
  Task myTask = new Task("MyTask", &MyClass::ProcessTask, this, someParam);
}

void MyClass::ProcessTask(int param)
{
  // do something on task
}

&MyClass::SomeFunction is a pointer to a member function.

AustinSchuh 02-14-2016 02:33 PM

Re: Member function as Task
 
Quote:

Originally Posted by euhlmann (Post 1540075)
You can use a member function but you'll have to pass an instance to Task. I've looked in the Task source and it should work, since it forwards all of its arguments to thread. Thread internally detects if you gave a member function pointer and uses the first argument as the instance to call the function from.
Code:

class MyClass
{
  private:
    void DispatchTask();
    void ProcessTask(int param);
}

void MyClass::DispatchTask()
{
  Task myTask = new Task("MyTask", &MyClass::ProcessTask, this, someParam);
}

void MyClass::ProcessTask(int param)
{
  // do something on task
}

&MyClass::SomeFunction is a pointer to a member function.

I'm not a very big fan of the Task class... There are some weird pieces of WPILib which have APIs which are trying to make Linux look like VxWorks, and Task is one of them.

You can do this in 1 line.

Code:

::std::thread my_thread(::std::bind(&MyClass::MyMethod, this, arg1, arg2));
If you want to delay starting the thread:

Code:

::std::thread my_thread;

my_thread = ::std::thread(::std::bind(&MyClass::MyMethod, this, arg1, arg2));

We use ::std::thread for all threads we start, and it works wonderfully.


All times are GMT -5. The time now is 09:17 AM.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi