boost :: thread_group зависает навсегда после завершения потоков - PullRequest
0 голосов
/ 19 февраля 2019

У меня есть простая программа, которая вычисляет лемуан n (и минимизирует p) для всех n в диапазоне.Я пытаюсь использовать boost :: thread_group для выполнения заданий с использованием определенного числа ядер.Вот мой код:

int is_prime(unsigned int number)
{
        if (number <= 1) return 0;
        unsigned int i;
        for (i=2; i*i<=number; i++) {
                if (number % i == 0) return 0;
        }
        return 1;
}

void lemoine(unsigned int n)
{
        unsigned int q, p;
        for (q = n/2; q > 0; q--) {
                p = n - 2 * q;
                if (is_prime(p) && is_prime(q)) {
                        printf("%d = %d + 2*%d\n", n, p, q);
                        return;
                }
        }
}


void guess(unsigned int lower, unsigned int upper, unsigned int cores)
{
        unsigned int n;
        boost::asio::io_service svc;
        boost::asio::io_service::work work(svc);
        boost::thread_group threadpool;

        for (int i = 0; i < cores; i++) {
                threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &svc));
        }

        for (n = lower; n <= upper; n+=2) {
                svc.post(std::bind(lemoine, n));
        }

        threadpool.join_all();
}

Я собрал это вместе с различными примерами, найденными онлайн.Проблема в threadpool.join_all () никогда не возвращается.По распечатке я вижу, что все мои работы выполнены, но все равно зависает.Один пример, который я нашел, предлагает выполнить svc.stop () перед объединением, но это делает вывод непредсказуемым, поскольку он явно убивает задания до их завершения (а не ожидает их завершения).Как я могу обеспечить выполнение всех заданий и поручиться за них?

1 Ответ

0 голосов
/ 19 февраля 2019

Ваши коды зависают при вызове io_service::run, потому что вы создали io_service::work объект ( рабочая ссылка ).io_service::run может возвращаться, только если вызывается деструктор work - что невозможно в вашем случае, потому что dtor of work вызывается после join_all (когда функция выходит из области видимости).Вы можете решить эту проблему, создав work экземпляр в куче (затем вы можете вручную удалить этот объект, что может вызвать dtor из work и io_service::run):

void guess(unsigned int lower, unsigned int upper, unsigned int cores)
{
        unsigned int n;
        boost::asio::io_service svc;
        std::unique_ptr<boost::asio::io_service::work> work =     // ADDED
           std::make_unique<boost::asio::io_service::work>(svc); // ADDED
        boost::thread_group threadpool;

        for (int i = 0; i < cores; i++) {
                threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &svc));
        }

        for (n = lower; n <= upper; n+=2) {
                svc.post(std::bind(lemoine, n));
        }

        work.reset(); // delete work, ADDED
        threadpool.join_all();
}

После удаления work на work.reset() ваши темы заканчиваются, когда их работа завершена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...