Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
[Win32] простой вопрос по iocp 20.08.08 09:56 Число просмотров: 1890
Автор: void <Grebnev Valery> Статус: Elderman
|
Хорошо бы получить ответ на один маленький давнишний вопрос... Не задавал его раньше, поскольку и так работает... Есть функция, которая весьма стандартно "вычитывает" данные из overlapped socket (впрочем не важно что это сокет - это может быть любой oveplapped хендл)
bool read(DWORD bytes_to_read)
{
if (m_io_status == IOSTATUS_NOOP|m_io_status == IOSTATUS_COMPLETED)
{
// reset counters and start reading
::ZeroMemory( get_overlapped(), sizeof(OVERLAPPED)); //reset overlapped
m_bytes_done = 0; // how many bytes we've received
m_bytes_left = bytes_to_read; // how many bytes we have left to receive
}
else if (m_io_status == IOSTATUS_PENDING|m_io_status == IOSTATUS_COMPLETED_SYNCHRONOUSLY)
{
DWORD async_done = (DWORD) get_overlapped()->InternalHigh;
m_bytes_done += async_done;
m_bytes_left -= async_done;
if ( 0 == m_bytes_left)
{
// reading is completed
m_io_status = IOSTATUS_COMPLETED;
return true;
}
else if (m_io_status == IOSTATUS_PENDING)
{
// continue reading asynchronous results
return true;
}
else
{
// queue next overlapped operation
}
}
else
{
m_io_status = IOSTATUS_ERROR;
return false;
}
// queue next overlapped operation
if ( read((LPBYTE)m_buffer + m_bytes_done, m_bytes_left) )
{
// completed synchronously
m_io_status = IOSTATUS_COMPLETED_SYNCHRONOUSLY;
return true;
}
else
{
DWORD err = ::GetLastError();
if (err == ERROR_IO_PENDING )
{
// operation will complete in the future
m_io_status = IOSTATUS_PENDING;
return true;
}
else
{
m_io_status = IOSTATUS_ERROR;
return false;
}
}
}
---
Это работает нормально. Хотелось бы чуток лучше - если операция заканчивается синхронно (см. m_io_status = IOSTATUS_COMPLETED_SYNCHRONOUSLY), то получив сразу же ! данные, я их не обрабатываю, поскольку IOCP всё равно поместит соответствующий completion status в очередь.
Хотелось бы сделать что-нить типа (вычитывать данные, которые драйвер вернул синхронно, сразу же)
while ( read((LPBYTE)m_buffer + m_bytes_done, m_bytes_left) )
{
// completed synchronously
m_io_status = IOSTATUS_COMPLETED_SYNCHRONOUSLY;
DWORD async_done = (DWORD) get_overlapped()->InternalHigh;
m_bytes_done += async_done;
m_bytes_left -= async_done;
if ( 0 == m_bytes_left)
{
// reading is completed
m_io_status = IOSTATUS_COMPLETED;
return true;
}
}
DWORD err = ::GetLastError();
if (err == ERROR_IO_PENDING )
{
// operation will complete in the future
m_io_status = IOSTATUS_PENDING;
return true;
}
else
{
m_io_status = IOSTATUS_ERROR;
return false;
}
---
Не работает ... Данные завершения синхронных операций "портятся" последующими вызовами GetQueuedCompletionStatus. Проблема в том, что для операций, которые queued на IOCP, и завершились синхронно, IOCP всё равно поставит соответстуючие issues в свою очередь. Так что следующие вызовы GetQueuedCompletionStatus будут продолжать возвращать данные которые уже были получены.
Это можно побороть?
Спасибо !
|
- [Win32] простой вопрос по iocp - void 20.08.08 09:56 [1890]
|
|
|