C++ Errors C2672 and C2893 when I use mutex in C++

When I use mutual parameter,’some mutex’,in demo of shared data in multi-threading of C++,the two errors occur,and their codes are

C2672:
'invoke': no matching overloaded function found shared_data
C2893:
Failed to specialize function template 'unknown-type std::invoke(_Callable &&) noexcept(<expr>)'

Then I looked the error codes in Microsoft VS Doc,it reads:"To fix this issue, make the template parameter member accessible where it is evaluated.",So what does the sentence mean?Finally,I guess there must be some wrong with the function invoke .

Here’s the code:

#include <list>
#include <mutex>
#include <algorithm>
#include<thread>
std::list<int> some_list; 
std::mutex some_mutex; 
void add_to_list(int new_value)
{
    std::lock_guard<std::mutex> guard(some_mutex); 
    some_list.push_back(new_value);
}
bool list_contains(int value_to_find)
{
    std::lock_guard<std::mutex> guard(some_mutex);
    return std::find(some_list.begin(), some_list.end(), value_to_find) != some_list.end();
}
int main() {
    using std::thread;
    thread t1(add_to_list);
    thread t2(list_contains);
    t1.join();
    t2.join();
    return 0;
}

So confused that I want to ask for help.

>Solution :

My comment written out as a program :

#include <cassert>
#include <list>
#include <mutex>
#include <algorithm>
#include <future>

// avoid global variable, group related functions in a class
//std::list<int> some_list;
//std::mutex some_mutex;

class my_async_list final
{
public:

    void add(const int new_value) // new_value should not change so const
    {
        // scoped_lock instead of lock_guard https://stackoverflow.com/questions/43019598/stdlock-guard-or-stdscoped-lock
        std::scoped_lock<std::mutex> lock{ m_mtx };
        m_list.push_back(new_value);
    }

    bool contains(int value_to_find) const // contains should not change datastructure so it is a const function
    {
        std::scoped_lock<std::mutex> lock{ m_mtx };
        return std::find(m_list.begin(), m_list.end(), value_to_find) != m_list.end();
    }

private:
    mutable std::mutex m_mtx; // so it can be used in const functions
    std::list<int> m_list;
};

int main() 
{
    my_async_list my_list;
  
    // use lambda functions to launch async function call
    auto add_future = std::async(std::launch::async, [&my_list]
    {
        my_list.add(1);
    });

    auto contains_future = std::async(std::launch::async, [&my_list]
    {
        return my_list.contains(1);
    });

    add_future.get(); // wait until add is done.
    bool contains_one = contains_future.get();

    assert(contains_one);
    
    return 0;
}

Leave a Reply