2

I have a class called MatrixAlt and i'm trying to multi thread a function to do some work on that matrix.

My general method worked when I just implemented it in a couple of functions. But when I try to bring it into the class methods, I get an error.

The problematic line (or where it highlights anyway) is 4 lines from the end and the error message is in the comments just above it.

#include <vector>
#include <future>
#include <thread>

class MatrixAlt
{
    public:
    MatrixAlt();

    // initilaise the matrix to constant value for each entry
    void function01(size_t maxThreads);
    void function02(size_t threadIndex);

};

MatrixAlt::MatrixAlt()
{

}

void MatrixAlt::function02(size_t threadIndex)
{
    // do some stuff 
    return;

}


void MatrixAlt::function01(size_t maxThreads)
{

    // To control async threads and their results
    std::vector<std::future<bool>> threadsIssued;

    // now loop through all the threads and orchestrate the work to be done
    for (size_t threadIndex = 0; threadIndex < maxThreads; ++threadIndex)
    {
        // line 42 gives error:
        // 'MatrixAlt::function02': non-standard syntax; use '&' to create a pointer to member
        // 'std::async': no matching overloaded function found
        threadsIssued.push_back(std::async(function02, threadIndex));
    }
    return;
}
genpfault
  • 51,148
  • 11
  • 85
  • 139
PBS
  • 37
  • 4
  • 2
    Use `&MatrixAlt::function02` as the error message suggests. – user0042 Oct 26 '17 at 17:26
  • 1
    Class methods may be implemented as functions under the hood, but in C++, a method pointer is distinct from a function pointer, and they have their own rules for how to work with them. – jxh Oct 26 '17 at 17:28
  • Possible duplicate of https://stackoverflow.com/questions/13669094/how-to-use-stdasync-on-a-member-function – Galik Oct 26 '17 at 17:38
  • I looked at the possible duplicate question and confess that I'm not smart enough to see the analogy. I'm pretty new to c++ but have been coding for 40 years off and on. It means some concepts that are obvious to many remain a bit mysterious to me. Sorry! – PBS Oct 26 '17 at 17:51
  • please dont fix the errors in your question according to answers/comments when it is about the problem you are asking for. I rolled back to the original version because as it was, the error message was completely unrelated to the code and the question didnt make much sense – 463035818_is_not_an_ai Oct 26 '17 at 17:58

2 Answers2

1

Your first problem is solved like this

threadsIssued.push_back(std::async(&MatrixAlt::function02, this, threadIndex));

You need to specify the exact class::function and take its address and which instance of the class your doing it for, and then the parameters.

The second problem which you haven't see yet is this line

 std::vector<std::future<bool>> threadsIssued;

All those futures will be lost in scope exit, like tears in rain. Time to destroy.

Freely after Blade runner.

All those moments will be lost in time, like tears in rain. Time to die.

Surt
  • 15,501
  • 3
  • 23
  • 39
  • I'm still feeling my way and I tried using the solution to my first problem and it won't compile. The error is as follows: no instance of overloaded function "std::async" matches the argument list argument types are : (bool (MatrixAlt::*)(size_t threadIndex), MatrixAlt *, size_t) It's not obvious to me what I should do to fix that. The second problem can sit and wait for me a while yet – PBS Oct 26 '17 at 21:55
  • re my second problem: Are you saying that because I don't do anything with the threads then the processes will die when it hits the return? If yes, it may be relevant that I'd stripped out this (not yet working) code as I was trying to create the minimal code to post that illustrated the problem I was experiencing, float accumulator = 0; for (int index = 0; index < threadsToUse; ++index) { double temp = futureVector[index].get(); accumulator += temp; } If it's nothing to do with that, any chance you could elaborate slightly? Thanks – PBS Oct 28 '17 at 15:04
  • When you exit the function all the futures in the vectors are lost, but the code you describe there should use them before exit. – Surt Oct 28 '17 at 15:06
0

Whenever you have a member function in C++, that function takes the object itself as an implicit first argument. So you need to pass the object as well, but even then, it can't be called with the same syntax as a normal function that takes the object.

The simplest way to setup an asynchronous job in C++ is typically just to use lambdas. They've very clear and explicit. So, for example, you could change your call to:

threadsIssued.push_back(std::async([this] (size_t t) { this->function02(t);}, threadIndex));

This lambda is explicitly capturing the this pointer, which tells us that all of the function02 calls will be called on the same object that the calling function01 is called on.

In addition to being correct, and explicit, this also helps highlight an important point: all of the function02 objects will be running with mutable access to the same MatrixAlt object. This is very dangerous, so you need to make sure that function02 is thread safe, one way or another (usually easy if its conceptually const, otherwise perhaps need a mutex, or something else).

Nir Friedman
  • 17,108
  • 2
  • 44
  • 72
  • I'm feeling my way. The suggested line would only compile if I change this line: std::vector> threadsIssued; to std::vector> threadsIssued; I'll need to work out the implications of that tomorrow Thanks for the threadsafe warning. At the moment, I believe that will be ok as I'm carving up the matrix and operating on discrete chunks of it in the actual code. – PBS Oct 26 '17 at 21:38
  • @PBS Yes because function02 returns void, so where can it get the bool from? Sorry I missed that point in my answer. – Nir Friedman Oct 27 '17 at 00:37