как поток может сигнализировать, когда он закончил? - PullRequest
1 голос
/ 28 мая 2010
#include <iostream>
#include <boost/thread.hpp>
using std::endl; using std::cout;
using namespace boost;


mutex running_mutex;

struct dostuff
{
    volatile bool running;
    dostuff() : running(true) {}
    void operator()(int x)
    {
        cout << "dostuff beginning " << x << endl;
        this_thread::sleep(posix_time::seconds(2));
        cout << "dostuff is done doing stuff" << endl;
        mutex::scoped_lock running_lock(running_mutex);
        running = false;
    }
};

bool is_running(dostuff& doer)
{
    mutex::scoped_lock running_lock(running_mutex);
    return doer.running;
}

int main()
{
    cout << "Begin.." << endl;
    dostuff doer;
    thread t(doer, 4);

    if (is_running(doer)) cout << "Cool, it's running.\n";

    this_thread::sleep(posix_time::seconds(3));

    if (!is_running(doer)) cout << "Cool, it's done now.\n";
    else cout << "still running? why\n"; // This happens! :(

    return 0;
}

Почему вывод вышеуказанной программы:

Начало ..
Круто, он работает.
начало производства 4
Dostuff готов делать вещи
Все еще работает? почему

Как правильно сделать пометку, когда это сделано? Я не хочу сидеть сложа руки в ожидании этого, я просто хочу получать уведомления, когда это будет сделано.

Ответы [ 4 ]

4 голосов
/ 28 мая 2010

Проблема в этом примере состоит в том, что есть два экземпляра dostuff, поэтому в operator() версия, установленная в false, отличается от версии main.

Из документации по управлению потоками :

Новый поток запускается путем передачи в конструктор объекта вызываемого типа, который может быть вызван без параметров. Затем объект копируется во внутреннее хранилище и вызывается во вновь созданном потоке выполнения. Если объект нельзя (или нельзя) копировать, тогда можно использовать boost :: ref для передачи ссылки на объект функции. В этом случае пользователь Boost.Thread должен убедиться, что указанный объект переживает вновь созданный поток выполнения.

Если вы не хотите копировать объект, используйте boost::ref:

thread t(boost::ref(doer), 4);
2 голосов
/ 28 мая 2010

Вы не можете предполагать, что нить будет закончена просто сном.

Вы можете позвонить присоединиться к ветке. Это будет ожидать завершения потока и возобновления потока.

Для расширенного уведомления между потоками о том или ином событии вы можете использовать условие повышения .

1 голос
/ 28 мая 2010

Я предполагаю, что ваша проблема на самом деле является ошибкой в ​​вашем коде.Из документации Boost для thread:

Конструктор потоков с аргументами

шаблонрезьба (F f, A1 a1, A2 a2, ...);

Условия: F и каждый A n должен быть копируемым или подвижным.

Эффекты:Как будто поток (boost :: bind (f, a1, a2, ...)). Следовательно, f и каждый a n копируются во внутреннее хранилище для доступа нового потока.

Итак, я думаю, что поток модифицирует свойкопия пользователя, а не объекта, чье состояние запуска вы проверяете.

0 голосов
/ 28 мая 2010

Реальный вопрос не в том, как поток данных должен отправлять сигнал, а в том, как основной поток должен принимать сигнал. Мой любимый метод - использовать socketpair () для создания локального соединения с сокетом, а затем передать один сокет дочернему потоку, а другой сокет - основному. Затем два потока могут использовать сокет-соединение для связи друг с другом. В вашем случае все, что вам нужно, это чтобы дочерний поток отправлял байт в сокет (или просто закрывал свой дескриптор файла сокета) непосредственно перед его выходом, и этого было бы достаточно, чтобы вырвать основной поток из select () или poll () или что бы он ни блокировал, и пусть он знает, что дочерний поток завершил свою задачу.

Обратите внимание, что основной поток должен по-прежнему вызывать join () для идентификатора потока дочернего потока (после того, как он получит сигнал уходящего ребенка), чтобы убедиться, что дочерний поток действительно действительно мертв, прежде чем освобождать любые ресурсы ... в противном случае вы рискуете состязанием основного потока, освобождающего ресурс после того, как дочерний поток дал сигнал, но до завершения процедур очистки потока.

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