Disable GetQueuedCompletionStatus workaround on recent Windows versions.

This commit is contained in:
Christopher Kohlhoff 2014-05-02 12:51:32 +10:00
parent 9c1fd314c8
commit eabbbace2d
2 changed files with 24 additions and 7 deletions

View File

@ -69,6 +69,7 @@ win_iocp_io_service::win_iocp_io_service(
stopped_(0),
stop_event_posted_(0),
shutdown_(0),
gqcs_timeout_(get_gqcs_timeout()),
dispatch_required_(0)
{
ASIO_HANDLER_TRACKING_INIT;
@ -116,7 +117,7 @@ void win_iocp_io_service::shutdown_service()
dword_ptr_t completion_key = 0;
LPOVERLAPPED overlapped = 0;
::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
&completion_key, &overlapped, gqcs_timeout);
&completion_key, &overlapped, gqcs_timeout_);
if (overlapped)
{
::InterlockedDecrement(&outstanding_work_);
@ -362,7 +363,7 @@ size_t win_iocp_io_service::do_one(bool block, asio::error_code& ec)
LPOVERLAPPED overlapped = 0;
::SetLastError(0);
BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
&completion_key, &overlapped, block ? gqcs_timeout : 0);
&completion_key, &overlapped, block ? gqcs_timeout_ : 0);
DWORD last_error = ::GetLastError();
if (overlapped)
@ -453,6 +454,16 @@ size_t win_iocp_io_service::do_one(bool block, asio::error_code& ec)
}
}
DWORD win_iocp_io_service::get_gqcs_timeout()
{
OSVERSIONINFO version_info;
version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (::GetVersionEx(&version_info))
if (version_info.dwMajorVersion >= 6)
return INFINITE;
return default_gqcs_timeout;
}
void win_iocp_io_service::do_add_timer_queue(timer_queue_base& queue)
{
mutex::scoped_lock lock(dispatch_mutex_);

View File

@ -206,6 +206,9 @@ private:
// either 0 or 1).
ASIO_DECL size_t do_one(bool block, asio::error_code& ec);
// Helper to calculate the GetQueuedCompletionStatus timeout.
ASIO_DECL static DWORD get_gqcs_timeout();
// Helper function to add a new timer queue.
ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
@ -245,11 +248,11 @@ private:
enum
{
// Timeout to use with GetQueuedCompletionStatus. Some versions of windows
// have a "bug" where a call to GetQueuedCompletionStatus can appear stuck
// even though there are events waiting on the queue. Using a timeout helps
// to work around the issue.
gqcs_timeout = 500,
// Timeout to use with GetQueuedCompletionStatus on older versions of
// Windows. Some versions of windows have a "bug" where a call to
// GetQueuedCompletionStatus can appear stuck even though there are events
// waiting on the queue. Using a timeout helps to work around the issue.
default_gqcs_timeout = 500,
// Maximum waitable timer timeout, in milliseconds.
max_timeout_msec = 5 * 60 * 1000,
@ -267,6 +270,9 @@ private:
overlapped_contains_result = 2
};
// Timeout to use with GetQueuedCompletionStatus.
const DWORD gqcs_timeout_;
// Function object for processing timeouts in a background thread.
struct timer_thread_function;
friend struct timer_thread_function;