Optimize overlapped I/O for files and pipes on Windows.
* file_io/win32/open.c
(read_with_timeout, apr_file_write): Check that overlapped I/O operation
already completed by macro HasOverlappedIoCompleted() before calling kernel
via WaitForSingleObject().
@@ -80,6 +80,15 @@ static apr_status_t read_with_timeout(apr_file_t *file, void *buf, apr_size_t le
else {
rv = apr_get_os_error();
if (rv == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) {
+ /* It seems that ReadFile() return ERROR_IO_PENDING even
+ * when I/O operation completed syncronously.
+ * Use fast macro to check that overlapped I/O already
+ * completed to avoid kernel call.
+ */
+ if (HasOverlappedIoCompleted(file->pOverlapped)) {
+ res = WAIT_OBJECT_0;
+ }
+ else {
/* Wait for the pending i/o, timeout converted from us to ms
* Note that we loop if someone gives up the event.
*
@@ -88,6 +97,7 @@ static apr_status_t read_with_timeout(apr_file_t *file, void *buf, apr_size_t le
*/
res = apr_wait_for_single_object(file->pOverlapped->hEvent,
file->timeout);
+ }
/* There is one case that represents entirely
* successful operations, otherwise we will cancel
@@ -489,8 +499,18 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, a
DWORD res;
+ /* It seems that WriteFile() return ERROR_IO_PENDING even
+ * when I/O operation completed syncronously.
+ * Use fast macro to check that overlapped I/O already
+ * completed to avoid kernel call.
+ */
+ if (HasOverlappedIoCompleted(thefile->pOverlapped)) {
+ res = WAIT_OBJECT_0;
+ }
+ else {
res = apr_wait_for_single_object(thefile->pOverlapped->hEvent,
thefile->timeout);
+ }
/* There is one case that represents entirely
* successful operations, otherwise we will cancel
