Issue invoking member function asynchronously when class has a std::mutex member

Fernando 21 Reputation points
2020-09-30T02:37:34.713+00:00

Hi

The code below compiles and runs successfully and Foo's compute method can be invoked both synchronously as well as asynchronously using std::async.

#include <iostream>
#include <future>

struct Foo
{
    int compute()
    {
        return 123;
    }

    // === UNCOMMENT THE LINE BELOW TO SHOW THE ERROR ===
    //std::mutex the_mutex;
};

int main()
{
    Foo foo;
    std::cout << "result: " << foo.compute() << std::endl;

    std::future<int> f = std::async(std::launch::async, &Foo::compute, foo);
    std::cout << "result: " << f.get() << std::endl;

    return 0;
}

However, if you uncomment the std::mutex member, compilation fails with the following error:

Error C2661 'std::tuple<int (__thiscall Foo:: )(void),Foo>::tuple': no overloaded function takes 2 arguments*

Moreover, the error disappears if you comment out the code that invokes the method asynchronously, I'm using VS2019 v16.7.4. Note that this is not an issue with std::mutex per se. I can see the same behavior if I replaced it with a boost::asio::io_context member variable.

I haven't done C++ programming for a very long time. Assuming this is not a compiler bug, I would like to understand the reason and find a workaround.

Thanks

C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,636 questions
0 comments No comments
{count} votes

Accepted answer
  1. Jeanine Zhang-MSFT 9,431 Reputation points Microsoft Vendor
    2020-09-30T08:52:56.467+00:00

    Hi,

    std::mutex is non-copyable. Therefore, the Foo class that contains it becomes non-copyable. You are passing a temporary Foo object to std::future, and you probably want to use the same object in all your threads. I suggest you could use std::ref to pass a reference of an existing object.

    Here is the code:

    #include <iostream>  
    #include <future>  
      
    struct Foo  
    {  
    	int compute()  
    	{  
    	return 123;  
    	}  
      
    	// === UNCOMMENT THE LINE BELOW TO SHOW THE ERROR ===  
    	std::mutex the_mutex;  
    };  
      
    int main()  
    {  
    	Foo foo;  
    	std::cout << "result: " << foo.compute() << std::endl;  
      
    	std::future<int> f = std::async(std::launch::async, &Foo::compute, std::ref(foo));  
    	std::cout << "result: " << f.get() << std::endl;  
      
    	return 0;  
    }  
    

    Best Regards,

    Jeanine Zhang


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful