How to Use Std::Async on a Member Function

How to use std::async on a member function?

Something like this:

auto f = std::async(&Person::sum, &p, xxx);

or

auto f = std::async(std::launch::async, &Person::sum, &p, xxx);

where p is a Person instance and xxx is an int.

This simple demo works with GCC 4.6.3:

#include <future>
#include <iostream>

struct Foo
{
Foo() : data(0) {}
void sum(int i) { data +=i;}
int data;
};

int main()
{
Foo foo;
auto f = std::async(&Foo::sum, &foo, 42);
f.get();
std::cout << foo.data << "\n";
}

C++ use async with member function

There are a number of typos in your code, but what I think you are trying to get at is that you have the wrong syntax for a pointer to a member function. It should be &class_name::function_name. Also, you need to pass this as before any other parameters to emplace_back, and the last parameter should be work_list, not work_list [i].

So, all-in-all, that gives us:

v_async.emplace_back(std::async(std::launch::async, &Worker::WorkA, this, i, work_list));

Then, it compiles

std::async call of member function

The problem appears to be that it won't play nice with member functions. Perhaps you can std::bind the member function to your object first, before passing it to std::async:

auto func = std::bind(&Foo::bar, this, std::placeholders::_1);
auto handle = std::async(std::launch::async, func, 0);

std::async with non static member functions

You can use a lambda like following, using a policy*

auto handle = std::async(std::launch::async, [&ptr](){
return ptr->foo(); // Ofcourse make foo public in your snippet
});

auto res = handle.get();

*Not necessarily required

Class and std::async on class member in C++

do_rand_stf is a non-static member function and thus cannot be called without a class instance (the implicit this parameter.) Luckily, std::async handles its parameters like std::bind, and bind in turn can use std::mem_fn to turn a member function pointer into a functor that takes an explicit this parameter, so all you need to do is to pass this to the std::async invocation and use valid member function pointer syntax when passing the do_rand_stf:

auto hand=async(launch::async,&A::do_rand_stf,this,i,j);

There are other problems in the code, though. First off, you use std::cout and std::endl without #includeing <iostream>. More seriously, std::future is not copyable, only movable, so you cannot push_back the named object hand without using std::move. Alternatively, just pass the async result to push_back directly:

ran.push_back(async(launch::async,&A::do_rand_stf,this,i,j));

async with member function

cap.pr is an incomplete member function call expression. You must follow it with parentheses containing the appropriate function arguments to make a valid C++ expression.

You can't therefore pass cap.pr to std::async or any other function.

To pass a member function to std::async you need to use the syntax you found:

auto f=std::async(&capc::pr,cap);

Though in this case, you need to be aware that the cap object is copied. You could also use

auto f=std::async(&capc::pr,&cap);

to just pass a pointer to cap.

If the pointer-to-member-function syntax is unwelcome then you can use a lambda:

auto f=std::async([&]{cap.pr();});

This isn't quite the same: it doesn't pass the member function pointer and object pointer to std::async, it passes a lambda object containing a reference to cap that calls its pr member function directly. However, the result is essentially the same.

Can't do async run member function in other class

I tried to fix your code and came up with a version that is working. You have a lot of unecessary cluttering in there. Also your code will leak the workset pointer. As pointed out in the comments the main mistake was the &workset which created a "ref to pointer" where all you need was the pointer itself. You should avoid the plain pointers altogether. This is what I came up with, hope it helps:

#include <vector>
#include <future>
#include <iostream>

class Work
{
public:
void doWork(int A){
std::cout << "I got " << A << std::endl;
}
};

class Worker
{
public:
void Work_MP(){
std::vector< std::future<void> > v_async;
v_async.reserve( 8 );
for( size_t i = 0; i < 8; ++i ){
std::shared_ptr<Work> workset = std::make_shared<Work>();
v_async.emplace_back( std::async( std::launch::async, &Work::doWork, workset, i ) );
}
}
};

int main ()
{
Worker worker;
worker.Work_MP();
return 0;
}

As you can see I inlined the function definition for briefness. Converted the plain pointer to shared pointer and removed unused vars.

See it in action here: https://onlinegdb.com/vFQo8R1rA

How do I pass a function from another class while calling std::async from a function of different class?

As per the comment if the member function you want to run using std::async is CameraToBEV::process then the parameter passed immediately after &CameraToBEV::process should be a pointer to a valid CameraToBEV instance.

In addition, std::async will, by default, pass parameters by value. However the function you're calling has the signature...

cv::Mat process(json&, std::vector<Point2f> = { Point2f(765,57), Point2f(1860,57), Point2f(27, 1000) ,Point2f(1800, 1000) }, Point2f=Point2f(1920,1080), Point2f=Point2f(1920, 1080));

so it expects the first parameter as a non-const reference to a json object. The call to std::async should therefore be (untested)...

processingThread.emplace_back(std::async(std::launch::async, &CameraToBEV::process, &cbevObj, std::ref(jsonObjects[i])));

(Note the use of std::ref)

std::async with a member function, holding another meber fucntion as an argument

fa and fb don't fully "compile" until you actually call them - the function call operators aren't instantiated till then, it seems. Once you call, you'll realize that fb is invalid, i.e. fb() won't compile. As soon as you fix that, the async call will work :)

As a further hint, observe that std::bind is subtly broken and not recommended for new code. You'd be better served with lambdas (they'd actually work here!).

How is bind broken? Like so:

std::bind(&Test::Func1, &te, a, b, fa)(); // won't compile

But:

using FnArg = std::function<void(std::vector<double> const&, int)>;
fb = std::bind(&Test::Func1, &te, a, b, FnArg(fa));
fb(); // compiles OK

So, you'd be best served by forgetting about std::bind's existence, and use lambdas:

#include <functional>
#include <future>
#include <string>
#include <vector>

class Test
{
public:
using FnArg = std::function<void(std::vector<double> const&, int)>;
void Func1(std::string const&, std::string const&, FnArg) {}
std::vector<double> Func2(std::vector<double> const&, size_t const) {}
};

int main()
{
Test te;
std::vector<double> vd;
std::string a, b;
auto fa = [&te](const auto &a, auto b){ return te.Func2(a, b); };
auto fb = [=,&te](){ return te.Func1(a, b, fa); };
fa(vd, 1);
fb();

auto fab = std::async(std::launch::async, fb);
fab.wait();
}

Feel free to mess with it online.



Related Topics



Leave a reply



Submit