Использование WaitForSingleObject в Windows, но поддержка прерываний потока поддержки

Вспомогательные нити имеют удобную функцию «прерывания». Платформа вводит точки прерывания, когда вы спите, и т. Д. Однако использование блокировок вызовов Win32 обходит эту функцию. Например, WaitForSingleObject заблокирует поток, но не допустит его прерывания механизмом прерывания вспомогательного потока.

Есть ли способ обернуть WaitForSingleObject или скажите boost подождать дескриптор события Win32, чтобы я мог восстановить точку прерывания?

1

Решение

detail::win32::interruptible_wait реализует только это.

Как вы можете видеть, он ожидает 3 дескриптора (2 в дополнение к указанному вызывающим абонентом), чтобы соблюдать прерывание.

Смотрите конкретно

  • WaitForMultipleObjectsEx вызов
  • блок

    else if(notified_index==interruption_index)
    {
    detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle);
    throw thread_interrupted();
    }
    

Для справки, Повышенная лицензия:

bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
{
detail::win32::handle handles[3]={0};
unsigned handle_count=0;
unsigned wait_handle_index=~0U;
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
unsigned interruption_index=~0U;
#endif
unsigned timeout_index=~0U;
if(handle_to_wait_for!=detail::win32::invalid_handle_value)
{
wait_handle_index=handle_count;
handles[handle_count++]=handle_to_wait_for;
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
if(detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled)
{
interruption_index=handle_count;
handles[handle_count++]=detail::get_current_thread_data()->interruption_handle;
}
#endif
detail::win32::handle_manager timer_handle;

#ifndef UNDER_CE
#if !BOOST_PLAT_WINDOWS_RUNTIME
unsigned const min_timer_wait_period=20;

if(!target_time.is_sentinel())
{
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
if(time_left.milliseconds > min_timer_wait_period)
{
// for a long-enough timeout, use a waitable timer (which tracks clock changes)
timer_handle=CreateWaitableTimer(NULL,false,NULL);
if(timer_handle!=0)
{
LARGE_INTEGER due_time=get_due_time(target_time);

bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
if(set_time_succeeded)
{
timeout_index=handle_count;
handles[handle_count++]=timer_handle;
}
}
}
else if(!target_time.relative)
{
// convert short absolute-time timeouts into relative ones, so we don't race against clock changes
target_time=detail::timeout(time_left.milliseconds);
}
}
#endif
#endif

bool const using_timer=timeout_index!=~0u;
detail::timeout::remaining_time time_left(0);

do
{
if(!using_timer)
{
time_left=target_time.remaining_milliseconds();
}

if(handle_count)
{
unsigned long const notified_index=detail::win32::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0);
if(notified_index<handle_count)
{
if(notified_index==wait_handle_index)
{
return true;
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
else if(notified_index==interruption_index)
{
detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle);
throw thread_interrupted();
}
#endif
else if(notified_index==timeout_index)
{
return false;
}
}
}
else
{
detail::win32::sleep(time_left.milliseconds);
}
if(target_time.relative)
{
target_time.milliseconds-=detail::timeout::max_non_infinite_wait;
}
}
while(time_left.more);
return false;
}
2

Другие решения


По вопросам рекламы [email protected]