Повышение прерывания в реализации наивного опроса
Я разработал простой поток опроса (используя Boost 1.39.0), который проверяет, был ли доступ к ресурсу данных в течение определенного периода времени, и очищает соединение, если нет. Соответствующий код может быть рассмотрен ниже.
Мои опасения двояки:
1) Целесообразно ли использовать прерывание во сне для безопасного закрытия потока? Будет ли прерывание ждать окончания сна или оно прервется немедленно? Вы можете видеть, что я ловлю исключение thread_interrupted только для того, чтобы избежать цикла while.
2) Расточительно ли использовать нить, которая проводит большую часть своего времени во сне? Есть ли лучший шаблон для реализации простого механизма опроса в стандартном C++?
boost::xtime xt;
while (1) {
try {
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += _sleep_secs;
boost::thread::sleep(xt);
//
// logic to check resource access
// etc.
}
catch(boost::thread_interrupted const&) {
return;
}
}
2 ответа
1) Это должно быть безопасно, судя по реализации Boost boost::thread::interrupt() для потоков POSIX:
void thread::interrupt()
{
detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info)
{
lock_guard<mutex> lk(local_thread_info->data_mutex);
local_thread_info->interrupt_requested=true;
if(local_thread_info->current_cond)
{
BOOST_VERIFY(!pthread_cond_broadcast(local_thread_info->current_cond));
}
}
}
Они блокируют мьютекс, устанавливают для interrupt_requested значение true и транслируют по условной переменной. И поток сразу же проснется, если он спит в boost::thread::sleep(). И они не используют pthread_cancel в нем для того, чтобы отменить поток.
2) Я не думаю, что один поток является пустой тратой ресурсов, если мы говорим о таких операционных системах, как Windows, Linux или HP-UX. Это цитата в поддержку этого пункта:
Многие ОС также имеют проблемы с обработкой более чем нескольких сотен потоков. Если каждый поток получает 2 МБ стека (не редкое значение по умолчанию), у вас заканчивается виртуальная память со значением (2^30 / 2^21) = 512 потоков на 32-разрядной машине с виртуальной машиной, доступной для пользователя 1 ГБ (как, скажем, Линукс как обычно поставляется на x86)
,
Я думаю, что использование совершенно нормально, многие люди используют его (например, последовательность выключения, когда вам нужно закрыть потоки - вы будете прерывать () все, после чего они могут отключиться).
Что касается повышения, тем не менее, обязательно прочитайте документацию: в частности, только несколько инструкций являются "точками прерывания", что означает, что поток будет прерван и получит это исключение, только если вы прерветесь во время выполнения этой инструкции. Если поток делает что-то еще, прерывание будет получено только при вводе точки прерывания, что может произойти через некоторое время после запроса interrupt
в зависимости от того, что вы делаете в своей теме.
Я думаю, что это правда в любом случае, вот как я понимаю следующее:
поток будет прерван в следующий раз, когда он войдет в одну из предварительно определенных точек прерывания с включенным прерыванием, или если он в данный момент заблокирован при вызове в одну из предварительно определенных точек прерывания с включенным прерыванием.