-1

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.

mch
  • 9,424
  • 2
  • 28
  • 42
Victor Hut
  • 35
  • 5
  • 1
    Your functions require parameters, so you need to pass them with your thread() initialisation – SimonC Jun 24 '22 at 09:14
  • 1
    As said you need to pass a parameter to add_to_list, you can use a lambda to do that like this `thread t1([]{ add_to_list(1); })`. Note I prefer to use std::future/std::async combinations because it lets me return values/exceptions back to the calling thread. eg. `std::future future_bool = std::async(std::launch::async, []{return list_contains(1); })` then instead of join you can check `future_bool.get();` it will return a bool once the background thread has done its work. (or throw an exception if 'list_contains' threw an exception) – Pepijn Kramer Jun 24 '22 at 09:21

1 Answers1

1

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;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19