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

Last change on this file since 7554 was 7552, checked in by sandervl, 24 years ago

overlapped io updates

File size: 11.9 KB
Line 
1/* $Id: overlappedio.cpp,v 1.4 2001-12-05 19:24:37 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 hThreadRead(0), hThreadWrite(0), hThreadPoll(0)
31{
32 OverlappedIOError errcode = OutOfMemory;
33
34 if(lpReadHandler == NULL || lpPollHandler == NULL) {
35 throw(InvalidParameter);
36 }
37
38 pending[ASYNC_INDEX_READ] = pending[ASYNC_INDEX_WRITE] = pending [ASYNC_INDEX_POLL] = NULL;
39
40 this->lpReadHandler = lpReadHandler;
41 this->lpWriteHandler = lpWriteHandler;
42 this->lpPollHandler = lpPollHandler;
43
44 ::InitializeCriticalSection(&critsect);
45 //poll, read & write event semaphores are auto-reset (one thread wakes up
46 //after a SetEvent call)
47 hEventPoll = ::CreateEventA(NULL, FALSE, FALSE, NULL);
48 hEventRead = ::CreateEventA(NULL, FALSE, FALSE, NULL);
49 hEventWrite = ::CreateEventA(NULL, FALSE, FALSE, NULL);
50
51 //the exit event semaphore is manual reset, because signalling this event
52 //must be able to wake up multiple threads
53 hEventExit = ::CreateEventA(NULL, TRUE, FALSE, NULL);
54 if(!hEventPoll || !hEventRead || !hEventWrite || !hEventExit)
55 {
56 DebugInt3();
57 errcode = EventCreationFailed;
58 goto failed;
59 }
60
61 DWORD dwThreadId;
62 LPOVERLAPPED_THREAD_PARAM threadparam;
63
64 dwAsyncType = (lpWriteHandler) ? ASYNCIO_READ : ASYNCIO_READWRITE;
65 threadparam = (LPOVERLAPPED_THREAD_PARAM)malloc(sizeof(OVERLAPPED_THREAD_PARAM));
66 if(!threadparam) goto outofmem;
67 threadparam->dwOperation = dwAsyncType;
68 threadparam->lpOverlappedObj = this;
69 hThreadRead = ::CreateThread(NULL, 32*1024, OverlappedIOThread, (LPVOID)threadparam, 0, &dwThreadId);
70
71 if(lpWriteHandler) {
72 dwAsyncType |= ASYNCIO_WRITE;
73
74 threadparam = (LPOVERLAPPED_THREAD_PARAM)malloc(sizeof(OVERLAPPED_THREAD_PARAM));
75 if(!threadparam) goto outofmem;
76 threadparam->dwOperation = ASYNCIO_WRITE;
77 threadparam->lpOverlappedObj = this;
78 hThreadWrite = ::CreateThread(NULL, 32*1024, OverlappedIOThread, (LPVOID)threadparam, 0, &dwThreadId);
79 }
80
81 if(lpPollHandler) {
82 dwAsyncType |= ASYNCIO_POLL;
83
84 threadparam = (LPOVERLAPPED_THREAD_PARAM)malloc(sizeof(OVERLAPPED_THREAD_PARAM));
85 if(!threadparam) goto outofmem;
86 threadparam->dwOperation = ASYNCIO_POLL;
87 threadparam->lpOverlappedObj = this;
88 hThreadPoll = ::CreateThread(NULL, 32*1024, OverlappedIOThread, (LPVOID)threadparam, 0, &dwThreadId);
89 }
90
91 if((lpPollHandler && !hThreadPoll) || !hThreadRead || (lpWriteHandler && !hThreadWrite))
92 {
93 DebugInt3();
94 errcode = ThreadCreationFailed;
95 goto failed;
96 }
97 return;
98
99outofmem:
100 errcode = OutOfMemory;
101 //fall through
102failed:
103 //SvL: NOTE: We might not fail gracefully when threads have already been
104 // created. (thread accessing memory that has been freed)
105 // Don't feel like wasting time to fix this as this should never
106 // happen anyway.
107 if(hEventExit) {
108 ::SetEvent(hEventExit);
109 ::CloseHandle(hEventExit);
110 }
111
112 if(hEventRead) ::CloseHandle(hEventRead);
113 if(hEventWrite) ::CloseHandle(hEventWrite);
114 if(hEventPoll) ::CloseHandle(hEventPoll);
115
116 if(hThreadRead) ::CloseHandle(hThreadRead);
117 if(hThreadPoll) ::CloseHandle(hThreadPoll);
118 if(hThreadWrite) ::CloseHandle(hThreadWrite);
119 ::DeleteCriticalSection(&critsect);
120
121 throw(errcode);
122}
123//******************************************************************************
124//******************************************************************************
125OverlappedIOHandler::~OverlappedIOHandler()
126{
127 dprintf(("~OverlappedIOHandler: signalling overlapped threads"));
128 ::SetEvent(hEventExit);
129
130 ::CloseHandle(hEventExit);
131 ::CloseHandle(hEventRead);
132 ::CloseHandle(hEventWrite);
133 ::CloseHandle(hEventPoll);
134
135 ::CloseHandle(hThreadRead);
136 if(hThreadPoll) ::CloseHandle(hThreadPoll);
137 if(hThreadWrite) ::CloseHandle(hThreadWrite);
138
139 DeleteCriticalSection(&critsect);
140}
141//******************************************************************************
142//******************************************************************************
143DWORD CALLBACK OverlappedIOThread(LPVOID lpThreadParam)
144{
145 LPOVERLAPPED_THREAD_PARAM threadparam = (LPOVERLAPPED_THREAD_PARAM)lpThreadParam;
146 DWORD dwOperation;
147 OverlappedIOHandler *lpOverlappedObj;
148
149 if(threadparam == NULL) {
150 DebugInt3();
151 return 0;
152 }
153 lpOverlappedObj = threadparam->lpOverlappedObj;
154 dwOperation = threadparam->dwOperation;
155 //free thread parameter first
156 free(threadparam);
157
158 return lpOverlappedObj->threadHandler(dwOperation);
159}
160//******************************************************************************
161//******************************************************************************
162DWORD OverlappedIOHandler::threadHandler(DWORD dwOperation)
163{
164 LPASYNCIOREQUEST lpRequest;
165 HANDLE hEvents[2];
166 DWORD ret;
167 int index;
168
169 dprintf(("OverlappedIOThread: started for event %d", dwOperation));
170 switch(dwOperation) {
171 case ASYNCIO_READ:
172 case ASYNCIO_READWRITE:
173 hEvents[0] = hEventRead;
174 index = ASYNC_INDEX_READ;
175 break;
176
177 case ASYNCIO_WRITE:
178 hEvents[0] = hEventWrite;
179 index = ASYNC_INDEX_WRITE;
180 break;
181
182 case ASYNCIO_POLL:
183 hEvents[0] = hEventPoll;
184 index = ASYNC_INDEX_POLL;
185 break;
186 default:
187 DebugInt3();
188 }
189 hEvents[1] = hEventExit;
190
191 while(TRUE) {
192 ret = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
193 if(ret == WAIT_FAILED) {
194 dprintf(("!WARNING!: WaitForMultipleObjects -> WAIT_FAILED!"));
195 break;
196 }
197 if(ret == WAIT_FAILED) {
198 dprintf(("!WARNING!: WaitForMultipleObjects -> WAIT_FAILED!"));
199 break;
200 }
201 //if hEventExit has been signalled, then we are told to exit
202 if(ret == (WAIT_OBJECT_0+1)) {
203 dprintf(("end of threadHandler signalled"));
204 break;
205 }
206 ::EnterCriticalSection(&critsect);
207 if(pending[index] == NULL) {
208 //oh, oh
209 ::LeaveCriticalSection(&critsect);
210 dprintf(("!ERROR!: overlapped thread woken up, but no tasks pending!!"));
211 DebugInt3();
212 continue;
213 }
214 lpRequest = pending[index];
215 pending[index] = lpRequest->next;
216 lpRequest->next = NULL;
217 ::LeaveCriticalSection(&critsect);
218
219 switch(dwOperation) {
220 case ASYNCIO_READ:
221 case ASYNCIO_READWRITE:
222 lpReadHandler(lpRequest);
223 break;
224
225 case ASYNCIO_WRITE:
226 lpWriteHandler(lpRequest);
227 break;
228
229 case ASYNCIO_POLL:
230 lpPollHandler(lpRequest);
231 break;
232 }
233 }
234 return 0;
235}
236//******************************************************************************
237//******************************************************************************
238BOOL OverlappedIOHandler::WriteFile(HANDLE hOS2Handle,
239 LPCVOID lpBuffer,
240 DWORD nNumberOfBytesToWrite,
241 LPDWORD lpNumberOfBytesWritten,
242 LPOVERLAPPED lpOverlapped,
243 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
244 DWORD dwUserData)
245{
246 LPASYNCIOREQUEST lpRequest, current;
247 int index;
248
249 lpRequest = new ASYNCIOREQUEST;
250 if(lpRequest == NULL) {
251 ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
252 return FALSE;
253 }
254 lpRequest->dwAsyncType = ASYNCIO_WRITE;
255 lpRequest->hOS2Handle = hOS2Handle;
256 lpRequest->lpBuffer = lpBuffer;
257 lpRequest->nNumberOfBytes = nNumberOfBytesToWrite;
258 lpRequest->lpResult = lpNumberOfBytesWritten;
259 lpRequest->lpOverlapped = lpOverlapped;
260 lpRequest->lpCompletionRoutine = lpCompletionRoutine;
261 lpRequest->dwUserData = dwUserData;
262 lpRequest->next = NULL;
263
264 if(dwAsyncType == ASYNCIO_READWRITE) {
265 index = ASYNC_INDEX_READ;
266 }
267 else index = ASYNC_INDEX_WRITE;
268
269 ::EnterCriticalSection(&critsect);
270 if(pending[index]) {
271 current = pending[index];
272 while(current->next) {
273 current = current->next;
274 }
275 current->next = lpRequest;
276 }
277 else pending[index] = lpRequest;
278 ::LeaveCriticalSection(&critsect);
279
280 //wake up async thread
281 ::SetEvent((dwAsyncType == ASYNCIO_READWRITE) ? hEventRead : hEventWrite);
282
283 ::SetLastError(ERROR_IO_PENDING);
284 return FALSE;
285}
286//******************************************************************************
287//******************************************************************************
288BOOL OverlappedIOHandler::ReadFile(HANDLE hOS2Handle,
289 LPCVOID lpBuffer,
290 DWORD nNumberOfBytesToRead,
291 LPDWORD lpNumberOfBytesRead,
292 LPOVERLAPPED lpOverlapped,
293 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
294 DWORD dwUserData)
295{
296 LPASYNCIOREQUEST lpRequest, current;
297
298 lpRequest = new ASYNCIOREQUEST;
299 if(lpRequest == NULL) {
300 ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
301 return FALSE;
302 }
303 lpRequest->dwAsyncType = ASYNCIO_READ;
304 lpRequest->hOS2Handle = hOS2Handle;
305 lpRequest->lpBuffer = lpBuffer;
306 lpRequest->nNumberOfBytes = nNumberOfBytesToRead;
307 lpRequest->lpResult = lpNumberOfBytesRead;
308 lpRequest->lpOverlapped = lpOverlapped;
309 lpRequest->lpCompletionRoutine = lpCompletionRoutine;
310 lpRequest->dwUserData = dwUserData;
311 lpRequest->next = NULL;
312
313 ::EnterCriticalSection(&critsect);
314 if(pending[ASYNC_INDEX_READ]) {
315 current = pending[ASYNC_INDEX_READ];
316 while(current->next) {
317 current = current->next;
318 }
319 current->next = lpRequest;
320 }
321 else pending[ASYNC_INDEX_READ] = lpRequest;
322 ::LeaveCriticalSection(&critsect);
323
324 //wake up async thread
325 ::SetEvent(hEventRead);
326 ::SetLastError(ERROR_IO_PENDING);
327 return FALSE;
328}
329//******************************************************************************
330//******************************************************************************
331BOOL OverlappedIOHandler::CancelIo(HANDLE hOS2Handle)
332{
333 return FALSE;
334}
335//******************************************************************************
336//******************************************************************************
337BOOL OverlappedIOHandler::GetOverlappedResult(HANDLE hOS2Handle,
338 LPOVERLAPPED lpoOverlapped,
339 LPDWORD lpcbTransfer,
340 DWORD dwTimeout)
341{
342 return FALSE;
343}
344//******************************************************************************
345//******************************************************************************
Note: See TracBrowser for help on using the repository browser.