W aplikacji występuje wyścig. Proszę go wyeliminować dbając o to, aby rozwiązanie było skalowalne. Nie modyfikuj funkcji main. Aplikacja znajduje liczby pierwsze w kolekcji dostarczonych liczb.

W funkcji main występują obiekty ref(x). Są to obiekty pomocnicze, które zapobiegają tworzeniu kopii obiektu, więc np. thread thrd1( ref(p1) ); oznacza, że konstruktor std::thread nie wykona kopii obiektu p1. Nie jest to kluczowe do znalezienia rozwiązania.

Posługujemy się także wektorem liczb z biblioteki standardowej, oraz iteratorem. Iterator pokazuje na element w kolekcji (element w wektorze)

#include <vector>
#include <thread>
#include <mutex>
#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>

using namespace std;

const int N = 10000;

class InputNumbers  {
public:
    InputNumbers(const vector<long>& n) : numbers(n), current(numbers.begin()) {}

    long getNext() {
        if( current < numbers.end() ) {
            return *(current++);
        }
        else {
            return 0;
        }
    }
private:
    vector<long> numbers;
    vector<long>::const_iterator current;
};

class OutputNumbers {
public:
    OutputNumbers() {}

    void add(long n) {
        numbers.push_back(n);
    }

    vector<long>& get() { return numbers; }
private:
    vector<long> numbers;
};

//bada, czy n jest liczba pierwsza
bool isPrime(long n) {
    if( n <= 3) return true;
    if( n % 2 == 0) return false;
    for(long i = 3; i * i <= n; i = i + 2)
        if(n % i == 0) return false;
    return true;
}

class ThreadPrime {
public:
    ThreadPrime(InputNumbers& in, OutputNumbers& out) : input(in), output(out) { }

    //bada kolejne liczby z kolekcji input i dodaje liczbe do output, jezeli jest pierwsza
    void operator()() {

        for(long n = input.getNext(); n > 0; n = input.getNext() ) {
            if(isPrime(n) ) {
                output.add(n);
            }
        }
    }
private:
    InputNumbers& input;
    OutputNumbers& output;
};

int main () {
    vector<long> v(N); //wektor N liczb
    std::mt19937_64 gen; //generator losowy (Mersanne Twister, default seed)
    std::uniform_int_distribution<long> distr(1'000'000'000, 9'000'000'000);
    generate( v.begin(), v.end(), [&](){ return distr(gen);}); //N liczb losowych od 1*10^12 do 9*10^12

    InputNumbers input(v);
    OutputNumbers output;

    ThreadPrime t1(input, output);
    ThreadPrime t2(input, output);

    thread thrd1( ref(t1) );
    thread thrd2( ref(t2) );

    thrd1.join();
    thrd2.join();

    cout << "num primes:" << output.get().size() << endl;
    copy( output.get().begin(), output.get().end(), ostream_iterator(cout, " ") ); //drukuje liczby pierwsze
    cout << endl;

    return 0;
}