source: trunk/src/kernel32/overlappedio.cpp@ 22018

Last change on this file since 22018 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 24.2 KB
Line 
1/* $Id: overlappedio.cpp,v 1.21 2003-07-28 11:35:32 sandervl Exp $ */
2
3/*
4 * Win32 overlapped IO class
5 *
6 * Copyright 2001 Sander van Leeuwen <sandervl@xs4all.nl>
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 */
11
12
13
14#include <os2win.h>
15#include <string.h>
16#include <handlemanager.h>
17#include <heapstring.h>
18#include <overlappedio.h>
19#include "oslibdos.h"
20
21#define DBG_LOCALLOG DBG_overlappedio
22#include "dbglocal.h"
23
24
25//******************************************************************************
26//******************************************************************************
27OverlappedIOHandler::OverlappedIOHandler(LPOVERLAPPED_HANDLER lpReadHandler,
28 LPOVERLAPPED_HANDLER lpWriteHandler,
29 LPOVERLAPPED_HANDLER lpPollHandler,
30 BOOL fFullDuplex) :
31 hThreadRead(0), hThreadWrite(0), hThreadPoll(0), refCount(0)
32{
33 OverlappedIOError errcode = OutOfMemory;
34
35 this->fFullDuplex = fFullDuplex;
36
37 if(lpReadHandler == NULL) {
38 throw(InvalidParameter);
39 }
40
41 pending[ASYNC_INDEX_READ] = pending[ASYNC_INDEX_WRITE] = NULL;
42 pending [ASYNC_INDEX_POLL] = pending [ASYNC_INDEX_BUSY] = NULL;
43
44 this->lpReadHandler = lpReadHandler;
45 this->lpWriteHandler = lpWriteHandler;
46 this->lpPollHandler = lpPollHandler;
47
48 ::InitializeCriticalSection(&critsect);
49 //poll, read & write event semaphores are auto-reset (one thread wakes up
50 //after a SetEvent call)
51 hEventPoll = ::CreateEventA(NULL, FALSE, FALSE, NULL);
52 hEventRead = ::CreateEventA(NULL, FALSE, FALSE, NULL);
53 hEventWrite = ::CreateEventA(NULL, FALSE, FALSE, NULL);
54
55 dprintf(("OverlappedIOThread: hEventRead %x hEventWrite %x hEventPoll %x", hEventRead, hEventWrite, hEventPoll));
56
57 //the exit & cancel event semaphores are manual reset, because these events
58 //must be able to wake up multiple threads
59 hEventExit = ::CreateEventA(NULL, TRUE, FALSE, NULL);
60 hEventCancel = ::CreateEventA(NULL, TRUE, FALSE, NULL);
61 if(!hEventPoll || !hEventRead || !hEventWrite || !hEventExit || !hEventCancel)
62 {
63 DebugInt3();
64 errcode = EventCreationFailed;
65 goto failed;
66 }
67
68 DWORD dwThreadId;
69 LPOVERLAPPED_THREAD_PARAM threadparam;
70
71 dwAsyncType = (lpWriteHandler && fFullDuplex) ? ASYNCIO_READ : ASYNCIO_READWRITE;
72 threadparam = (LPOVERLAPPED_THREAD_PARAM)malloc(sizeof(OVERLAPPED_THREAD_PARAM));
73 if(!threadparam) goto outofmem;
74 threadparam->dwOperation = dwAsyncType;
75 threadparam->lpOverlappedObj = this;
76 hThreadRead = ::CreateThread(NULL, 32*1024, OverlappedIOThread, (LPVOID)threadparam, 0, &dwThreadId);
77 if(hThreadRead) {//thread uses this object; keep reference count to avoid premature destruction
78 AddRef();
79 }
80
81 if(lpWriteHandler && fFullDuplex) {
82 dwAsyncType |= ASYNCIO_WRITE;
83
84 threadparam = (LPOVERLAPPED_THREAD_PARAM)malloc(sizeof(OVERLAPPED_THREAD_PARAM));
85 if(!threadparam) goto outofmem;
86 threadparam->dwOperation = ASYNCIO_WRITE;
87 threadparam->lpOverlappedObj = this;
88 hThreadWrite = ::CreateThread(NULL, 32*1024, OverlappedIOThread, (LPVOID)threadparam, 0, &dwThreadId);
89 SetThreadPriority(hThreadWrite, THREAD_PRIORITY_TIME_CRITICAL);
90 if(hThreadWrite) {//thread uses this object; keep reference count to avoid premature destruction
91 AddRef();
92 }
93 }
94
95 if(lpPollHandler) {
96 dwAsyncType |= ASYNCIO_POLL;
97
98 threadparam = (LPOVERLAPPED_THREAD_PARAM)malloc(sizeof(OVERLAPPED_THREAD_PARAM));
99 if(!threadparam) goto outofmem;
100 threadparam->dwOperation = ASYNCIO_POLL;
101 threadparam->lpOverlappedObj = this;
102 hThreadPoll = ::CreateThread(NULL, 32*1024, OverlappedIOThread, (LPVOID)threadparam, 0, &dwThreadId);
103 SetThreadPriority(hThreadPoll, THREAD_PRIORITY_TIME_CRITICAL);
104 if(hThreadPoll) {//thread uses this object; keep reference count to avoid premature destruction
105 AddRef();
106 }
107 }
108
109 if((lpPollHandler && !hThreadPoll) || !hThreadRead || (lpWriteHandler && fFullDuplex && !hThreadWrite))
110 {
111 DebugInt3();
112 errcode = ThreadCreationFailed;
113 goto failed;
114 }
115 return;
116
117outofmem:
118 errcode = OutOfMemory;
119 //fall through
120failed:
121 //SvL: NOTE: We might not fail gracefully when threads have already been
122 // created. (thread accessing memory that has been freed)
123 // Don't feel like wasting time to fix this as this should never
124 // happen anyway.
125 if(hEventExit) {
126 ::SetEvent(hEventExit);
127 ::CloseHandle(hEventExit);
128 }
129
130 if(hEventRead) ::CloseHandle(hEventRead);
131 if(hEventWrite) ::CloseHandle(hEventWrite);
132 if(hEventPoll) ::CloseHandle(hEventPoll);
133
134 if(hThreadRead) ::CloseHandle(hThreadRead);
135 if(hThreadPoll) ::CloseHandle(hThreadPoll);
136 if(hThreadWrite) ::CloseHandle(hThreadWrite);
137 ::DeleteCriticalSection(&critsect);
138
139 throw(errcode);
140}
141//******************************************************************************
142//******************************************************************************
143OverlappedIOHandler::~OverlappedIOHandler()
144{
145 dprintf(("~OverlappedIOHandler: signalling overlapped threads"));
146 ::SetEvent(hEventExit);
147
148 ::CloseHandle(hEventExit);
149 ::CloseHandle(hEventRead);
150 ::CloseHandle(hEventWrite);
151 ::CloseHandle(hEventPoll);
152
153 ::CloseHandle(hThreadRead);
154 if(hThreadPoll) ::CloseHandle(hThreadPoll);
155 if(hThreadWrite) ::CloseHandle(hThreadWrite);
156
157 DeleteCriticalSection(&critsect);
158}
159//******************************************************************************
160//******************************************************************************
161DWORD OverlappedIOHandler::AddRef()
162{
163 return InterlockedIncrement(&refCount);
164}
165//******************************************************************************
166//******************************************************************************
167DWORD OverlappedIOHandler::Release(BOOL fSignalExit)
168{
169 if(fSignalExit) {
170 ::SetEvent(hEventExit);
171 }
172 if(InterlockedDecrement(&refCount) == 0) {
173 dprintf(("OverlappedIOHandler::Release -> delete now"));
174 delete this;
175 return 0;
176 }
177 return refCount;
178}
179//******************************************************************************
180//******************************************************************************
181DWORD CALLBACK OverlappedIOHandler::OverlappedIOThread(LPVOID lpThreadParam)
182{
183 LPOVERLAPPED_THREAD_PARAM threadparam = (LPOVERLAPPED_THREAD_PARAM)lpThreadParam;
184 DWORD dwOperation;
185 OverlappedIOHandler *lpOverlappedObj;
186
187 if(threadparam == NULL || threadparam->lpOverlappedObj == NULL) {
188 DebugInt3();
189 return 0;
190 }
191 lpOverlappedObj = threadparam->lpOverlappedObj;
192 dwOperation = threadparam->dwOperation;
193 //free thread parameter first
194 free(threadparam);
195
196 return lpOverlappedObj->threadHandler(dwOperation);
197}
198//******************************************************************************
199//******************************************************************************
200DWORD OverlappedIOHandler::threadHandler(DWORD dwOperation)
201{
202 LPASYNCIOREQUEST lpRequest;
203 LPOVERLAPPED lpOverlapped;
204 HANDLE hEvents[2];
205 HANDLE hEventsWait[2];
206 HANDLE hHandle;
207 DWORD ret, dwTimeOut, dwResult;
208 int index;
209
210 dprintf(("OverlappedIOThread: started for event %d", dwOperation));
211 switch(dwOperation) {
212 case ASYNCIO_READ:
213 case ASYNCIO_READWRITE:
214 hEvents[0] = hEventRead;
215 index = ASYNC_INDEX_READ;
216 break;
217
218 case ASYNCIO_WRITE:
219 hEvents[0] = hEventWrite;
220 index = ASYNC_INDEX_WRITE;
221 break;
222
223 case ASYNCIO_POLL:
224 hEvents[0] = hEventPoll;
225 index = ASYNC_INDEX_POLL;
226 break;
227 default:
228 DebugInt3();
229 }
230 hEvents[1] = hEventExit;
231
232 while(TRUE)
233 {
234 ret = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
235 if(ret == WAIT_FAILED) {
236 dprintf(("!WARNING!: WaitForMultipleObjects -> WAIT_FAILED!"));
237 break;
238 }
239 //if hEventExit has been signalled, then we are told to exit
240 if(ret == (WAIT_OBJECT_0+1)) {
241 dprintf(("end of threadHandler signalled"));
242 break;
243 }
244 //process all pending jobs
245 while(TRUE)
246 {
247 ::EnterCriticalSection(&critsect);
248 if(pending[index] == NULL) {
249 ::LeaveCriticalSection(&critsect);
250 break;
251 }
252 lpRequest = pending[index];
253 pending[index] = lpRequest->next;
254
255 //add to the head of process list
256 lpRequest->next = pending[ASYNC_INDEX_BUSY];
257 pending[ASYNC_INDEX_BUSY] = lpRequest;
258 ::LeaveCriticalSection(&critsect);
259
260 lpOverlapped = lpRequest->lpOverlapped;;
261 hHandle = lpRequest->hHandle;
262
263#ifdef DEBUG
264 switch(lpRequest->dwAsyncType) {
265 case ASYNCIO_READ:
266 case ASYNCIO_WRITE:
267 case ASYNCIO_POLL:
268 break;
269 default:
270 DebugInt3();
271 break;
272 }
273#endif
274 switch(dwOperation) {
275 case ASYNCIO_READ:
276 case ASYNCIO_READWRITE:
277 case ASYNCIO_WRITE:
278 if(lpRequest->dwAsyncType == ASYNCIO_READ || lpWriteHandler == NULL) {
279 lpRequest->dwLastError = lpReadHandler(lpRequest, &dwResult, NULL);
280 }
281 else lpRequest->dwLastError = lpWriteHandler(lpRequest, &dwResult, NULL);
282
283 if(!lpRequest->fCancelled)
284 {
285 lpOverlapped->Internal = lpRequest->dwLastError;
286 lpOverlapped->InternalHigh = dwResult;
287
288 //must NOT store result in specified location!!! (stack corruption)
289 //if(lpRequest->lpdwResult) {
290 // *lpRequest->lpdwResult = dwResult;
291 //}
292#ifdef DEBUG
293 if(lpRequest->dwAsyncType == ASYNCIO_READ) {
294 dprintf(("ASYNCIO_READ %x finished; result %x, last error %d", lpOverlapped, dwResult, lpRequest->dwLastError));
295 }
296 else dprintf(("ASYNCIO_WRITE %x finished; result %x, last error %d", lpOverlapped, dwResult, lpRequest->dwLastError));
297#endif
298 //wake up user thread
299 ::SetEvent(lpOverlapped->hEvent);
300 }
301 break;
302
303 case ASYNCIO_POLL:
304 hEventsWait[0] = hEventCancel;
305 hEventsWait[1] = hEventExit;
306 ret = WAIT_TIMEOUT;
307 while(TRUE)
308 {
309 dwTimeOut = 0;
310 lpRequest->dwLastError = lpPollHandler(lpRequest, &dwResult, &dwTimeOut);
311 if(lpRequest->dwLastError != ERROR_IO_PENDING) {
312 break;
313 }
314 if(dwTimeOut == 0) {
315 dprintf(("!ERROR!: lpPollHandler returned timeout 0!!"));
316 DebugInt3();
317 break;
318 }
319 //sleep a while to avoid wasting too many cpu cycles; we are woken up when a timeout occurs,
320 //when the operation is cancelled or when the process exits
321 ret = WaitForMultipleObjects(2, hEventsWait, FALSE, dwTimeOut);
322 if(ret != WAIT_TIMEOUT) {
323 dprintf(("ASYNCIO_POLL: WaitForSingleObject didn't time out, abort (ret = %x)", ret));
324 break;
325 }
326 }
327 //Don't access the overlapped & result memory when CancelIo was used to cancel the operation
328 if(ret == WAIT_TIMEOUT && !lpRequest->fCancelled)
329 {
330 dprintf(("ASYNCIO_POLL %x: result %x, last error %d", lpOverlapped, dwResult, lpRequest->dwLastError));
331 lpOverlapped->Internal = lpRequest->dwLastError;
332 lpOverlapped->InternalHigh = dwResult;
333 if(lpRequest->lpdwResult) {
334 *lpRequest->lpdwResult = dwResult;
335 }
336 //wake up user thread
337 ::SetEvent(lpOverlapped->hEvent);
338 }
339 break;
340 }
341 //remove from in-process list and delete async request object
342 removeRequest(ASYNC_INDEX_BUSY, lpRequest);
343 delete lpRequest;
344 } //while(TRUE)
345 }
346 Release(); //decrease reference count
347 return 0;
348}
349//******************************************************************************
350//******************************************************************************
351BOOL OverlappedIOHandler::WriteFile(HANDLE hHandle,
352 LPCVOID lpBuffer,
353 DWORD nNumberOfBytesToWrite,
354 LPDWORD lpNumberOfBytesWritten,
355 LPOVERLAPPED lpOverlapped,
356 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
357 DWORD dwUserData,
358 DWORD dwTimeOut)
359{
360 LPASYNCIOREQUEST lpRequest, current;
361 int index;
362
363 if(!lpOverlapped || lpOverlapped->hEvent == 0) {
364 ::SetLastError(ERROR_INVALID_PARAMETER);
365 return FALSE;
366 }
367
368 lpRequest = new ASYNCIOREQUEST;
369 if(lpRequest == NULL) {
370 ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
371 return FALSE;
372 }
373 lpRequest->dwAsyncType = ASYNCIO_WRITE;
374 lpRequest->hHandle = hHandle;
375 lpRequest->lpBuffer = lpBuffer;
376 lpRequest->nNumberOfBytes = nNumberOfBytesToWrite;
377 //must NOT store result in specified location!!! (stack corruption)
378//// lpRequest->lpdwResult = lpNumberOfBytesWritten;
379 lpRequest->lpdwResult = NULL;
380 lpRequest->lpOverlapped = lpOverlapped;
381 lpRequest->lpCompletionRoutine = lpCompletionRoutine;
382 lpRequest->dwUserData = dwUserData;
383 lpRequest->dwTimeOut = dwTimeOut;
384 lpRequest->next = NULL;
385
386 if(dwAsyncType & ASYNCIO_READWRITE) {
387 index = ASYNC_INDEX_READ;
388 }
389 else index = ASYNC_INDEX_WRITE;
390
391 lpOverlapped->Internal = STATUS_PENDING;
392 lpOverlapped->InternalHigh = 0;
393 //reset overlapped semaphore to non-signalled
394 ::ResetEvent(lpOverlapped->hEvent);
395
396 //Add request to queue; must make sure we do this right before waking the async thread
397 addRequest(index, lpRequest);
398
399 //wake up async thread
400 ::SetEvent((dwAsyncType & ASYNCIO_READWRITE) ? hEventRead : hEventWrite);
401
402 ::SetLastError(ERROR_IO_PENDING);
403 return FALSE;
404}
405//******************************************************************************
406//******************************************************************************
407BOOL OverlappedIOHandler::ReadFile(HANDLE hHandle,
408 LPCVOID lpBuffer,
409 DWORD nNumberOfBytesToRead,
410 LPDWORD lpNumberOfBytesRead,
411 LPOVERLAPPED lpOverlapped,
412 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
413 DWORD dwUserData,
414 DWORD dwTimeOut)
415{
416 LPASYNCIOREQUEST lpRequest, current;
417
418 if(!lpOverlapped || lpOverlapped->hEvent == 0) {
419 ::SetLastError(ERROR_INVALID_PARAMETER);
420 return FALSE;
421 }
422
423 lpRequest = new ASYNCIOREQUEST;
424 if(lpRequest == NULL) {
425 ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
426 return FALSE;
427 }
428 lpRequest->dwAsyncType = ASYNCIO_READ;
429 lpRequest->hHandle = hHandle;
430 lpRequest->lpBuffer = lpBuffer;
431 lpRequest->nNumberOfBytes = nNumberOfBytesToRead;
432 //must NOT store result in specified location!!! (stack corruption)
433//// lpRequest->lpdwResult = lpNumberOfBytesRead;
434 lpRequest->lpdwResult = NULL;
435 lpRequest->lpOverlapped = lpOverlapped;
436 lpRequest->lpCompletionRoutine = lpCompletionRoutine;
437 lpRequest->dwUserData = dwUserData;
438 lpRequest->dwTimeOut = dwTimeOut;
439 lpRequest->next = NULL;
440
441 lpOverlapped->Internal = STATUS_PENDING;
442 lpOverlapped->InternalHigh = 0;
443 //reset overlapped semaphore to non-signalled
444 ::ResetEvent(lpOverlapped->hEvent);
445
446 //Add request to queue; must make sure we do this right before waking the async thread
447 addRequest(ASYNC_INDEX_READ, lpRequest);
448
449 //wake up async thread
450 ::SetEvent(hEventRead);
451 ::SetLastError(ERROR_IO_PENDING);
452 return FALSE;
453}
454//******************************************************************************
455//******************************************************************************
456BOOL OverlappedIOHandler::WaitForEvent(HANDLE hHandle,
457 DWORD dwEventMask,
458 LPDWORD lpfdwEvtMask,
459 LPOVERLAPPED lpOverlapped,
460 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
461 DWORD dwUserData,
462 DWORD dwTimeOut)
463{
464 LPASYNCIOREQUEST lpRequest, current;
465 DWORD dwLastError, dwResult;
466
467 if(!lpOverlapped || lpOverlapped->hEvent == 0) {
468 ::SetLastError(ERROR_INVALID_PARAMETER);
469 return FALSE;
470 }
471 if(!lpPollHandler) {
472 DebugInt3();
473 ::SetLastError(ERROR_INVALID_PARAMETER);
474 return FALSE;
475 }
476
477 lpRequest = new ASYNCIOREQUEST;
478 if(lpRequest == NULL) {
479 ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
480 return FALSE;
481 }
482 lpRequest->dwAsyncType = ASYNCIO_POLL;
483 lpRequest->hHandle = hHandle;
484 lpRequest->lpBuffer = NULL;
485 lpRequest->nNumberOfBytes = 0;
486 //must store result also in specified location
487 lpRequest->lpdwResult = lpfdwEvtMask;
488 lpRequest->lpOverlapped = lpOverlapped;
489 lpRequest->lpCompletionRoutine = lpCompletionRoutine;
490 lpRequest->dwUserData = dwUserData;
491 lpRequest->dwTimeOut = dwTimeOut;
492 lpRequest->dwEventMask = dwEventMask;
493 lpRequest->next = NULL;
494
495 lpOverlapped->Internal = STATUS_PENDING;
496 lpOverlapped->InternalHigh = 0;
497 //reset overlapped semaphore to non-signalled
498 ::ResetEvent(lpOverlapped->hEvent);
499
500 //first check if the event has already occured; if so, return result
501 //immediately
502 dwLastError = lpPollHandler(lpRequest, &dwResult, &dwTimeOut);
503 if(dwLastError != ERROR_IO_PENDING)
504 {
505 dprintf(("OverlappedIOHandler::WaitForEvent %x: result %x, last error %d", lpOverlapped, dwResult, dwLastError));
506 lpOverlapped->Internal = dwLastError;
507 lpOverlapped->InternalHigh = dwResult;
508 if(lpfdwEvtMask) {
509 *lpfdwEvtMask = dwResult;
510 }
511 //wake up user thread
512 ::SetEvent(lpOverlapped->hEvent);
513
514 delete lpRequest;
515 ::SetLastError(dwLastError);
516 return (dwLastError == ERROR_SUCCESS);
517 }
518
519 //add request to list; must make sure we do this right before waking the async thread
520 addRequest(ASYNC_INDEX_POLL, lpRequest);
521
522 //wake up async thread
523 ::SetEvent(hEventPoll);
524 ::SetLastError(ERROR_IO_PENDING);
525 return FALSE;
526}
527//******************************************************************************
528//******************************************************************************
529BOOL OverlappedIOHandler::CancelIo(HANDLE hHandle)
530{
531 LPASYNCIOREQUEST lpRequest;
532
533 for(int i=ASYNC_INDEX_READ;i<NR_ASYNC_OPERATIONS;i++)
534 {
535 while(TRUE)
536 {
537 lpRequest = findAndRemoveRequest(i, hHandle);
538
539 if(lpRequest) {
540 //TODO: This doesn't work if multiple handles share the
541 // same OverlappedIOHandler
542 lpRequest->fCancelled = TRUE;
543 //GetOverlappedResult must return this error after the request
544 //has been cancelled!
545 lpRequest->lpOverlapped->Internal = ERROR_OPERATION_ABORTED;
546 ::SetEvent(hEventCancel); //cancel pending operation
547 if(i != ASYNC_INDEX_BUSY) {//thread that handles the request will delete it
548 delete lpRequest;
549 }
550 }
551 else break;
552 }
553 }
554 //TODO: return error if there were no pending requests???
555 ::SetLastError(ERROR_SUCCESS);
556 return TRUE;
557}
558//******************************************************************************
559//******************************************************************************
560BOOL OverlappedIOHandler::GetOverlappedResult(HANDLE hHandle,
561 LPOVERLAPPED lpOverlapped,
562 LPDWORD lpcbTransfer,
563 BOOL fWait)
564{
565 DWORD ret;
566
567 ret = ::WaitForSingleObject(lpOverlapped->hEvent, (fWait) ? INFINITE : 0);
568
569 if(lpcbTransfer)
570 *lpcbTransfer = lpOverlapped->InternalHigh;
571
572 ::SetLastError(lpOverlapped->Internal);
573
574 dprintf(("GetOverlappedResult %x -> result %d last error %d", hHandle, lpOverlapped->InternalHigh, lpOverlapped->Internal));
575 return (ret == WAIT_OBJECT_0);
576}
577//******************************************************************************
578//******************************************************************************
579LPASYNCIOREQUEST OverlappedIOHandler::findAndRemoveRequest(int index, HANDLE hHandle)
580{
581 LPASYNCIOREQUEST lpRequest, lpFound = NULL;
582
583 ::EnterCriticalSection(&critsect);
584 if(pending[index])
585 {
586 if(pending[index]->hHandle != hHandle)
587 {
588 lpRequest = pending[index];
589 while(lpRequest->next) {
590 if(lpRequest->next->hHandle == hHandle) {
591 lpFound = lpRequest->next;
592 lpRequest->next = lpFound->next;
593 break;
594 }
595 lpRequest = lpRequest->next;
596 }
597 }
598 else {
599 lpFound = pending[index];
600 pending[index] = lpFound->next;
601 }
602 }
603 ::LeaveCriticalSection(&critsect);
604 return lpFound;
605}
606//******************************************************************************
607//******************************************************************************
608void OverlappedIOHandler::addRequest(int index, LPASYNCIOREQUEST lpRequest)
609{
610 LPASYNCIOREQUEST current;
611
612 ::EnterCriticalSection(&critsect);
613 if(pending[index]) {
614 current = pending[index];
615 while(current->next) {
616 current = current->next;
617 }
618 current->next = lpRequest;
619 }
620 else pending[index] = lpRequest;
621 ::LeaveCriticalSection(&critsect);
622}
623//******************************************************************************
624//******************************************************************************
625void OverlappedIOHandler::removeRequest(int index, LPASYNCIOREQUEST lpRequest)
626{
627 LPASYNCIOREQUEST current;
628
629 ::EnterCriticalSection(&critsect);
630 if(pending[index]) {
631 if(pending[index] == lpRequest) {
632 pending[index] = lpRequest->next;
633 }
634 else {
635 current = pending[index];
636 while(current->next && current->next != lpRequest) {
637 current = current->next;
638 }
639 if(current->next) {
640 current->next = lpRequest->next;
641 }
642 else {
643 dprintf(("!ERROR!: request %x not found!!!!!!", lpRequest));
644 DebugInt3();
645 }
646 }
647 }
648 //else removed from list by cancelio
649 ::LeaveCriticalSection(&critsect);
650}
651//******************************************************************************
652//******************************************************************************
653
Note: See TracBrowser for help on using the repository browser.