0
votes

I wrote the following code which gives an error;

ipt.cpp: In function ‘bool isprimet(long unsigned int, int)’: ipt.cpp:28:86: error: no match for call to ‘(std::thread) (void (&)(long unsigned int, long unsigned int, long unsigned int, bool), const long unsigned int&, long unsigned int&, long unsigned int&, unsigned int&)’ for (unsigned long c=0;c

What am I doing wrong?

#include <iostream>
#include <thread>
#include <math.h>

using namespace std;

void ipt(const unsigned long number, const unsigned long root, const unsigned long threadid, bool &result)
{
   result=true;   
   for (unsigned long c=5+threadid*6;c<=root;c+=(threadid+1)*6)
   {
      if(number % c-1 == 0) {result=false; break;};
      if(number % c+1 == 0) {result=false; break;};
   }
}

bool isprimet(const unsigned long number, const int nthreads)
{
   if (number > 1)
   {
      if (number > 3)
      {
         if (number % 2 == 0) return false;
         if (number % 3 == 0) return false;
     unsigned int results[nthreads];
     unsigned long root=(unsigned long)floor(sqrt(number))+1;
     thread t[nthreads];
     for (unsigned long c=0;c<nthreads;c++) t[c](ipt, number, root, c, results[c]);
     for (unsigned long c=0;c<nthreads;c++) t[c].join();
     for (unsigned long c=0;c<nthreads;c++) if (results[c]==false) return false;
     return true;   
     }
      else return true;
   }
   else return false;   
}
2

2 Answers

1
votes

When using std::thread, you need to send a callable object to the constructor of std::thread, and you can use Lambda expressions for this:

t[c] = new thread([&](){ ipt(number, root, c, results[c]); });

The following code works:

#include <thread>
#include <math.h>
#include <iostream>

    using namespace std;
    static int const MAX_THREADS = 128;

    void ipt(const unsigned long number, const unsigned long root, const unsigned long threadid, bool &result)
    {
        result = true;
        for (unsigned long c = 5 + threadid * 6; c <= root; c += (threadid + 1) * 6)
        {
            if (number % c - 1 == 0) { result = false; break; };
            if (number % c + 1 == 0) { result = false; break; };
        }
    }

    bool isprimet(const unsigned long number, const unsigned long nthreads)
    {
        if (number > 1)
        {
            if (number > 3)
            {
                if (number % 2 == 0) return false;
                if (number % 3 == 0) return false;
                bool results[MAX_THREADS];
                unsigned long root = (unsigned long)floor(sqrt(number)) + 1;
                thread* t[MAX_THREADS];
                for (unsigned long c = 0; c < nthreads; c++)
                    t[c] = new thread([&](){ ipt(number, root, c, results[c]); });
                for (unsigned long c = 0; c < nthreads; c++) {
                    t[c]->join();
                    delete t[c];
                }
                for (unsigned long c = 0; c < nthreads; c++) 
                    if (results[c] == false) 
                        return false;
                return true;
            }
            else return true;
        }
        else return false;
    }

int main(int argc, char *argv[])
{
    for (int i = 1; i < 100; ++i)
        if (isprimet(i,5))
            cout << i << "\n";
    return 0;
}
1
votes

There are two problems with your code, they both occur in this line:

for (unsigned long c=0;c<nthreads;c++) t[c](ipt, number, root, c, results[c]);

which should look like this:

for (unsigned long c=0;c<nthreads;c++) t[c] = std::thread(ipt, number, root, c, std::ref(results[c]));

The first problem is the way that you are calling the function -- you can use the assignment operator as I have shown above.

Secondly, the default way that arguments are passed to a thread is by value. However, your function prototype specifies that you want to pass results[c] by reference, so you need to explicitly state that using std::ref(results[c]).

Also, you set the size of a static array with a non-const variable (so the compiler doesn't know the size at compile-time), hence all the compiler warnings. You need to use a constant to set the size, or define a global constant and use that, or pass the number of threads as a template argument, which will get rid of the compiler warnings.

Here is a live demo to a working example without warnings.