Implement overlapped completion routines.

Don't use lpOverlapped->OffsetHigh to store bytes to transfer.
This commit is contained in:
Mike McCormack 2001-07-12 22:29:41 +00:00 committed by Alexandre Julliard
parent 1fc39be64f
commit e61ad3a9f3
4 changed files with 39 additions and 19 deletions

View File

@ -2912,6 +2912,8 @@ static BOOL COMM_WaitCommEvent(
ovp->func = COMM_WaitCommEventService; ovp->func = COMM_WaitCommEventService;
ovp->buffer = (char *)lpdwEvents; ovp->buffer = (char *)lpdwEvents;
ovp->fd = fd; ovp->fd = fd;
ovp->count = 0;
ovp->completion_func = 0;
ovp->next = NtCurrentTeb()->pending_list; ovp->next = NtCurrentTeb()->pending_list;
ovp->prev = NULL; ovp->prev = NULL;

View File

@ -1268,7 +1268,7 @@ static void FILE_AsyncReadService(async_private *ovp, int events)
/* check to see if the data is ready (non-blocking) */ /* check to see if the data is ready (non-blocking) */
result = read(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh], result = read(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
lpOverlapped->OffsetHigh - lpOverlapped->InternalHigh); ovp->count - lpOverlapped->InternalHigh);
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR))) if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
{ {
@ -1286,9 +1286,9 @@ static void FILE_AsyncReadService(async_private *ovp, int events)
} }
lpOverlapped->InternalHigh += result; 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; r = STATUS_PENDING;
else else
r = STATUS_SUCCESS; r = STATUS_SUCCESS;
@ -1334,8 +1334,6 @@ BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
return FALSE; return FALSE;
} }
overlapped->Offset = 0;
overlapped->OffsetHigh = bytesToRead; /* FIXME: wrong */
overlapped->Internal = STATUS_PENDING; overlapped->Internal = STATUS_PENDING;
overlapped->InternalHigh = 0; overlapped->InternalHigh = 0;
@ -1375,6 +1373,8 @@ BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
return FALSE; return FALSE;
} }
ovp->lpOverlapped = overlapped; ovp->lpOverlapped = overlapped;
ovp->count = bytesToRead;
ovp->completion_func = lpCompletionRoutine;
ovp->timeout = timeout; ovp->timeout = timeout;
gettimeofday(&ovp->tv,NULL); gettimeofday(&ovp->tv,NULL);
add_timeout(&ovp->tv,timeout); add_timeout(&ovp->tv,timeout);
@ -1463,7 +1463,7 @@ static void FILE_AsyncWriteService(struct async_private *ovp, int events)
/* write some data (non-blocking) */ /* write some data (non-blocking) */
result = write(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh], result = write(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
lpOverlapped->OffsetHigh-lpOverlapped->InternalHigh); ovp->count-lpOverlapped->InternalHigh);
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR))) if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
{ {
@ -1480,9 +1480,9 @@ static void FILE_AsyncWriteService(struct async_private *ovp, int events)
lpOverlapped->InternalHigh += result; 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; r = STATUS_PENDING;
else else
r = STATUS_SUCCESS; r = STATUS_SUCCESS;
@ -1510,8 +1510,6 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
return FALSE; return FALSE;
} }
overlapped->Offset = 0;
overlapped->OffsetHigh = bytesToWrite;
overlapped->Internal = STATUS_PENDING; overlapped->Internal = STATUS_PENDING;
overlapped->InternalHigh = 0; overlapped->InternalHigh = 0;
@ -1545,6 +1543,8 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
ovp->event = POLLOUT; ovp->event = POLLOUT;
ovp->func = FILE_AsyncWriteService; ovp->func = FILE_AsyncWriteService;
ovp->buffer = (LPVOID) buffer; ovp->buffer = (LPVOID) buffer;
ovp->count = bytesToWrite;
ovp->completion_func = lpCompletionRoutine;
ovp->fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE ); ovp->fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
if(ovp->fd <0) if(ovp->fd <0)
{ {

View File

@ -43,6 +43,8 @@ typedef struct async_private
int event; int event;
char *buffer; char *buffer;
async_handler func; async_handler func;
int count;
LPOVERLAPPED_COMPLETION_ROUTINE completion_func;
struct async_private *next; struct async_private *next;
struct async_private *prev; struct async_private *prev;
} async_private; } async_private;

View File

@ -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))); ((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 */ /* remove it from the active list */
if(ovp->prev) if(ovp->prev)
ovp->prev->next = ovp->next; ovp->prev->next = ovp->next;
@ -60,7 +79,7 @@ static void finish_async(async_private *ovp)
close(ovp->fd); close(ovp->fd);
NtSetEvent(ovp->lpOverlapped->hEvent,NULL); 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) if(ovp->lpOverlapped->Internal!=STATUS_PENDING)
{ {
ovp->lpOverlapped->Internal=STATUS_UNSUCCESSFUL; finish_async(ovp,STATUS_UNSUCCESSFUL);
finish_async(ovp);
continue; continue;
} }
if(ovp->timeout && time_before(&ovp->tv,&now)) if(ovp->timeout && time_before(&ovp->tv,&now))
{ {
ovp->lpOverlapped->Internal=STATUS_TIMEOUT; finish_async(ovp,STATUS_TIMEOUT);
finish_async(ovp);
continue; continue;
} }
@ -135,8 +152,7 @@ static void check_async_list(void)
if( r==0 ) if( r==0 )
{ {
timeout_user->lpOverlapped->Internal = STATUS_TIMEOUT; finish_async(timeout_user, STATUS_TIMEOUT);
finish_async(timeout_user);
continue; continue;
} }
@ -147,7 +163,7 @@ static void check_async_list(void)
user[i]->func(user[i],fds[i].revents); user[i]->func(user[i],fds[i].revents);
if(user[i]->lpOverlapped->Internal!=STATUS_PENDING) if(user[i]->lpOverlapped->Internal!=STATUS_PENDING)
finish_async(user[i]); finish_async(user[i],user[i]->lpOverlapped->Internal);
} }
if(fds[0].revents == POLLIN) if(fds[0].revents == POLLIN)