lundi 27 février 2017

std::invoke no matching overloaded function found error in C++

I'm learning about threads, parallel programming and tasks and farming.

I'm trying to have a Task class with its derivates, and basically create a vector of threads, each taking a worker function that loads an element from a queue of tasks (one task simply is a 'hello' message printed on the console), runs it, and then pops it out of the queue, going to the next one in the queue. The problems is that after doing everything I am getting two errors:

C2672: std::invoke no matching overloaded function found

C2893: Failed to specialize function template 'unknown-type std::invoke (_Callable&&, _Types&&...)

This is the code for my classes:

class Task
{
public:
    virtual ~Task()
    {
    }
    virtual void run() = 0;
};

class MessageTask : public Task
    {
    public:
        MessageTask(const string& message)
            : message_(message)
        {
        }
        void run()
        {
            cout << message_ << endl;
        }
    private:
        const string message_;
    };

class Farm
{
public:
    void add_task(Task* task);
    void run();

protected:
    queue<Task*> farmTasks;
    mutex farm_queue_mutex;

private:
    void workerFunction(queue<Task*>& theQueue);
};

Here are the memeber functions implementations:

void Farm::add_task(Task * task)
{
    mutex_lock queueLock(farm_queue_mutex);
    farmTasks.push(task);
}
void Farm::run()
{
    int pcThreadsNo = thread::hardware_concurrency();

    vector<thread*> threads(pcThreadsNo);
    for (int i = 0; i < threads.size(); i++)
    {
        mutex_lock queueLock(farm_queue_mutex);
        threads.push_back(new thread(mem_fun(&Farm::workerFunction), farmTasks));
    }

    for (int i = 0; i < threads.size(); i++)
    {
        threads[i]->join();
    }
}
void Farm::workerFunction(queue<Task*>& theQueue)
{
        while (true)
        {
            mutex_lock queueLock(farm_queue_mutex);
            if (theQueue.empty())
            {
                return;
            }
            else
            {
                //get task from queue and run it, then remove it
                Task* currentTask = theQueue.front();
                theQueue.pop();
                currentTask->run();
                currentTask = nullptr;
            }
        }
}

In Farm::run() I had to use 's mem_func in order to transform the member workerFunction() into a function-like object to pass it to the new thread constructor. Finally, here's the main():

int main()
{
    Farm farm;
    for (int i = 0; i < 5; i++)
    {
        farm.add_task(new MessageTask("hello"));
    }
    farm.run();

    return 0;
}

I really hope someone can help me with this problem, and any help or further explanation of what exactly is happening behind the scenes with these errors and the threads in order to understand this topic more would be greatly appreciated.

1 commentaire: