Implement overlapped completion routines.
Don't use lpOverlapped->OffsetHigh to store bytes to transfer.
This commit is contained in:
parent
1fc39be64f
commit
e61ad3a9f3
|
@ -2912,6 +2912,8 @@ static BOOL COMM_WaitCommEvent(
|
|||
ovp->func = COMM_WaitCommEventService;
|
||||
ovp->buffer = (char *)lpdwEvents;
|
||||
ovp->fd = fd;
|
||||
ovp->count = 0;
|
||||
ovp->completion_func = 0;
|
||||
|
||||
ovp->next = NtCurrentTeb()->pending_list;
|
||||
ovp->prev = NULL;
|
||||
|
|
20
files/file.c
20
files/file.c
|
@ -1268,7 +1268,7 @@ static void FILE_AsyncReadService(async_private *ovp, int events)
|
|||
|
||||
/* check to see if the data is ready (non-blocking) */
|
||||
result = read(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
|
||||
lpOverlapped->OffsetHigh - lpOverlapped->InternalHigh);
|
||||
ovp->count - lpOverlapped->InternalHigh);
|
||||
|
||||
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
|
||||
{
|
||||
|
@ -1286,9 +1286,9 @@ static void FILE_AsyncReadService(async_private *ovp, int events)
|
|||
}
|
||||
|
||||
lpOverlapped->InternalHigh += result;
|
||||
TRACE("read %d more bytes %ld/%ld so far\n",result,lpOverlapped->InternalHigh,lpOverlapped->OffsetHigh);
|
||||
TRACE("read %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,ovp->count);
|
||||
|
||||
if(lpOverlapped->InternalHigh < lpOverlapped->OffsetHigh)
|
||||
if(lpOverlapped->InternalHigh < ovp->count)
|
||||
r = STATUS_PENDING;
|
||||
else
|
||||
r = STATUS_SUCCESS;
|
||||
|
@ -1334,8 +1334,6 @@ BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
overlapped->Offset = 0;
|
||||
overlapped->OffsetHigh = bytesToRead; /* FIXME: wrong */
|
||||
overlapped->Internal = STATUS_PENDING;
|
||||
overlapped->InternalHigh = 0;
|
||||
|
||||
|
@ -1375,6 +1373,8 @@ BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
|
|||
return FALSE;
|
||||
}
|
||||
ovp->lpOverlapped = overlapped;
|
||||
ovp->count = bytesToRead;
|
||||
ovp->completion_func = lpCompletionRoutine;
|
||||
ovp->timeout = timeout;
|
||||
gettimeofday(&ovp->tv,NULL);
|
||||
add_timeout(&ovp->tv,timeout);
|
||||
|
@ -1463,7 +1463,7 @@ static void FILE_AsyncWriteService(struct async_private *ovp, int events)
|
|||
|
||||
/* write some data (non-blocking) */
|
||||
result = write(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
|
||||
lpOverlapped->OffsetHigh-lpOverlapped->InternalHigh);
|
||||
ovp->count-lpOverlapped->InternalHigh);
|
||||
|
||||
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
|
||||
{
|
||||
|
@ -1480,9 +1480,9 @@ static void FILE_AsyncWriteService(struct async_private *ovp, int events)
|
|||
|
||||
lpOverlapped->InternalHigh += result;
|
||||
|
||||
TRACE("wrote %d more bytes %ld/%ld so far\n",result,lpOverlapped->InternalHigh,lpOverlapped->OffsetHigh);
|
||||
TRACE("wrote %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,ovp->count);
|
||||
|
||||
if(lpOverlapped->InternalHigh < lpOverlapped->OffsetHigh)
|
||||
if(lpOverlapped->InternalHigh < ovp->count)
|
||||
r = STATUS_PENDING;
|
||||
else
|
||||
r = STATUS_SUCCESS;
|
||||
|
@ -1510,8 +1510,6 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
overlapped->Offset = 0;
|
||||
overlapped->OffsetHigh = bytesToWrite;
|
||||
overlapped->Internal = STATUS_PENDING;
|
||||
overlapped->InternalHigh = 0;
|
||||
|
||||
|
@ -1545,6 +1543,8 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
|
|||
ovp->event = POLLOUT;
|
||||
ovp->func = FILE_AsyncWriteService;
|
||||
ovp->buffer = (LPVOID) buffer;
|
||||
ovp->count = bytesToWrite;
|
||||
ovp->completion_func = lpCompletionRoutine;
|
||||
ovp->fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
|
||||
if(ovp->fd <0)
|
||||
{
|
||||
|
|
|
@ -43,6 +43,8 @@ typedef struct async_private
|
|||
int event;
|
||||
char *buffer;
|
||||
async_handler func;
|
||||
int count;
|
||||
LPOVERLAPPED_COMPLETION_ROUTINE completion_func;
|
||||
struct async_private *next;
|
||||
struct async_private *prev;
|
||||
} async_private;
|
||||
|
|
|
@ -44,8 +44,27 @@ static inline int time_before( struct timeval *t1, struct timeval *t2 )
|
|||
((t1->tv_sec == t2->tv_sec) && (t1->tv_usec < t2->tv_usec)));
|
||||
}
|
||||
|
||||
static void finish_async(async_private *ovp)
|
||||
static void CALLBACK call_completion_routine(ULONG_PTR data)
|
||||
{
|
||||
async_private* ovp = (async_private*)data;
|
||||
|
||||
ovp->completion_func(ovp->lpOverlapped->Internal,
|
||||
ovp->lpOverlapped->InternalHigh,
|
||||
ovp->lpOverlapped);
|
||||
ovp->completion_func=NULL;
|
||||
HeapFree(GetProcessHeap(), 0, ovp);
|
||||
}
|
||||
|
||||
static void finish_async(async_private *ovp, DWORD status)
|
||||
{
|
||||
ovp->lpOverlapped->Internal=status;
|
||||
|
||||
/* call ReadFileEx/WriteFileEx's overlapped completion function */
|
||||
if(ovp->completion_func)
|
||||
{
|
||||
QueueUserAPC(call_completion_routine,GetCurrentThread(),(ULONG_PTR)ovp);
|
||||
}
|
||||
|
||||
/* remove it from the active list */
|
||||
if(ovp->prev)
|
||||
ovp->prev->next = ovp->next;
|
||||
|
@ -60,7 +79,7 @@ static void finish_async(async_private *ovp)
|
|||
|
||||
close(ovp->fd);
|
||||
NtSetEvent(ovp->lpOverlapped->hEvent,NULL);
|
||||
HeapFree(GetProcessHeap(), 0, ovp);
|
||||
if(!ovp->completion_func) HeapFree(GetProcessHeap(), 0, ovp);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -96,15 +115,13 @@ static void check_async_list(void)
|
|||
|
||||
if(ovp->lpOverlapped->Internal!=STATUS_PENDING)
|
||||
{
|
||||
ovp->lpOverlapped->Internal=STATUS_UNSUCCESSFUL;
|
||||
finish_async(ovp);
|
||||
finish_async(ovp,STATUS_UNSUCCESSFUL);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ovp->timeout && time_before(&ovp->tv,&now))
|
||||
{
|
||||
ovp->lpOverlapped->Internal=STATUS_TIMEOUT;
|
||||
finish_async(ovp);
|
||||
finish_async(ovp,STATUS_TIMEOUT);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -135,8 +152,7 @@ static void check_async_list(void)
|
|||
|
||||
if( r==0 )
|
||||
{
|
||||
timeout_user->lpOverlapped->Internal = STATUS_TIMEOUT;
|
||||
finish_async(timeout_user);
|
||||
finish_async(timeout_user, STATUS_TIMEOUT);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -147,7 +163,7 @@ static void check_async_list(void)
|
|||
user[i]->func(user[i],fds[i].revents);
|
||||
|
||||
if(user[i]->lpOverlapped->Internal!=STATUS_PENDING)
|
||||
finish_async(user[i]);
|
||||
finish_async(user[i],user[i]->lpOverlapped->Internal);
|
||||
}
|
||||
|
||||
if(fds[0].revents == POLLIN)
|
||||
|
|
Loading…
Reference in New Issue