2009-12-14 2 views
2

Как я могу прервать спящий/заблокированный boost :: thread?Boost (v1.33.1) Прерывание потока

Я использую Boost v1.33.1, обновление не является вариантом.

Спасибо.

+2

Почему он спит/заблокирован? Разве не имело бы смысла заставить его ждать переменную состояния или мьютекса или что-то еще, если вам нужно иметь возможность разбудить его по требованию? – jalf

+0

Если вы можете предложить лучшее решение, я пытаюсь добавить тайм-аут к определенному фрагменту кода: У меня есть блокирующий вызов, который получает новые данные и сохраняет его как самое последнее. Эти данные имеют срок службы, и мне нужно инициировать событие, когда оно истекает *, если я не получаю новые данные за это время, и в этом случае я повторно инициализирую тайм-аут на новую продолжительность жизни и снова жду. – James

+0

Является ли обязательный код неизменяемого кода блокировки, который вам нужен, или вы можете изменить его на неблокирующий/тайм-аут? –

ответ

1

Быстрое прочтение документации для boost.thread в 1.33 предполагает, что нет никакого переносного способа достижения прерывания. Был введен прерывание потока (для потоков в одной из точек «перерыва» повышения) в 1,35.

В результате единственный вариант, о котором я могу думать, это использовать сигналы (которые также не относятся к 1.33, поэтому вам нужно будет отступить, например, pthreads) в сочетании с тайм-аутами по любым методам которые блокируют. В основном используйте сигналы для пробуждения потоков, которые спали, заставляя их спать в ожидании сигнала и таймаутов при блокировке потоков, чтобы они просыпались и проверяли, должны ли они выйти. К сожалению, это очень нежелательное решение, и в какой-то мере это означает, что более новые версии boost делают все равно.

Если вы используете boost.thread, вам следует рассмотреть возможность перехода на более новую версию для других проектов, потому что 1.33 не поддерживает подавляющее большинство конструкций, которые необходимы для многопоточности.

0

Невозможно прервать заблокированную нить в boost :: thread. Вам нужно реализовать собственное прерывание потока самостоятельно, используя boost :: условный например.

AFAIK Любой существующий способ прервать работу потока (TerminateThread в Windows API, например) приводит только к проблемам (память утечки одного из них).

1

Я согласен с опросом, изучаю условные переменные. Если у вас есть потоки, которые вы хотите просыпаться время от времени, это то, что ожидают от вас. Если вы ожидаете, что потоки будут блокироваться при других вызовах (например, вызовы в сокеты BSD или что-то подобное), это не поможет вам. Вам нужно будет использовать тайм-аут этих вызовов напрямую, если они существуют.

Вот пример, используя только средства, доступные в boost 1.33.1. Я не скомпилировал его, поэтому могут быть небольшие ошибки. Я включил использование туманного класса Work, но вам не нужно вообще работать с общими данными для использования этого шаблона. Требуется только мьютекс и переменная условия.

Work work; 
boost::condition workAvailable; 
boost::mutex workMutex; 

void Producer() 
{ 
    { 
    boost::mutex::scoped_lock lock(workMutex); 
    UpdateWork(work); 
    workAvailable.notify_one(); 
    } 
    boost::mutex::scoped_lock lock(workMutex); 
    work.SetOver(); 
    workAvailable.notify_one(); 
} 

void Consumer() 
{ 
    //This thread uses data protected by the work mutex 
    boost::mutex::scoped_lock lock(workMutex); 
    while(true) 
    { 
    //this call releases the work mutex 
    //when this thread is notified, the mutex is re-acquired 
    workAvailable.wait(lock); 
    //once we have the mutex we can work with shared data 
    //which might require this thread to terminate 
    if(work.Over()) 
    { 
     return; 
    } 
    DoWork(work); 
    } 
} 

Нить производителя создаст одну единицу работы, а затем заблокирует. Потребительский поток выполнит эту работу, а затем заблокирует. Затем поток производителя установит условие завершения и выйдет. Затем потребитель выйдет.

+1

Я только что заметил комментарий о блокирующем унаследованном вызове, который был его сердцем этой проблемы. Это определенно не помогает ответить на исходный вопрос. Я не знаю, есть ли безопасный способ прекратить блокирующий вызов в boost 1.33.1.Если унаследованный вызов является безопасным для исключения, более поздние версии boost могут помочь. Я решил удалить это, но я оставлю это здесь, потому что ответ может быть полезен кому-то, кроме OP. –