source: trunk/src/wsock32/asyncthread.cpp@ 6502

Last change on this file since 6502 was 6201, checked in by achimha, 24 years ago

implemented WSAEventSelect

File size: 8.2 KB
Line 
1/* $Id: asyncthread.cpp,v 1.11 2001-07-07 14:29:40 achimha Exp $ */
2
3/*
4 * Async thread help functions
5 *
6 * Copyright 2000 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * TODO: Not everything is 100% thread safe (i.e. async parameter updates)
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 */
13#define INCL_BASE
14#include <os2wrap.h>
15#include <os2sel.h>
16#include <stdlib.h>
17#include <wprocess.h>
18#include <win32api.h>
19#include <misc.h>
20#include <string.h>
21#include <vmutex.h>
22#include "wsock32.h"
23#include "asyncthread.h"
24
25static PASYNCTHREADPARM threadList = NULL;
26VMutex asyncThreadMutex;
27
28static void AddToQueue(PASYNCTHREADPARM pThreadParm);
29
30//******************************************************************************
31//******************************************************************************
32static void _Optlink AsyncThread(void *arg)
33{
34 PASYNCTHREADPARM pThreadParm = (PASYNCTHREADPARM)arg;
35
36 pThreadParm->asyncProc((PVOID)arg);
37
38//only for blocking hooks (currently not implemented)
39//// if(pThreadParm->request == ASYNC_BLOCKHOOK)
40//// WSASetBlocking(FALSE, pThreadParm->hThread);
41
42 free((PVOID)pThreadParm);
43}
44//******************************************************************************
45//******************************************************************************
46ULONG QueueAsyncJob(ASYNCTHREADPROC asyncproc, PASYNCTHREADPARM pThreadParm, BOOL fSetBlocking)
47{
48 TID tid;
49
50 pThreadParm->asyncProc = asyncproc;
51 pThreadParm->fActive = TRUE;
52 pThreadParm->fCancelled = FALSE;
53 pThreadParm->next = NULL;
54 pThreadParm->hAsyncTaskHandle = 0;
55
56 pThreadParm->hThread = GetCurrentThread();
57 AddToQueue(pThreadParm);
58
59 if(fSetBlocking) WSASetBlocking(TRUE);
60
61 USHORT sel = GetFS();
62 tid = _beginthread(AsyncThread, NULL, 16384, (PVOID)pThreadParm);
63 SetFS(sel);
64 if (tid == -1) {
65 dprintf(("QueueAsyncJob: _beginthread failed"));
66 if(fSetBlocking) WSASetBlocking(FALSE);
67 RemoveFromQueue(pThreadParm);
68 WSASetLastError(WSAEFAULT);
69 return 0;
70 }
71 pThreadParm->hAsyncTaskHandle = tid;
72 WSASetLastError(NO_ERROR);
73 return pThreadParm->hAsyncTaskHandle;
74}
75//******************************************************************************
76//******************************************************************************
77void AddToQueue(PASYNCTHREADPARM pThreadParm)
78{
79 asyncThreadMutex.enter();
80 pThreadParm->next = threadList;
81 threadList = pThreadParm;
82 asyncThreadMutex.leave();
83}
84//******************************************************************************
85//******************************************************************************
86void RemoveFromQueue(PASYNCTHREADPARM pThreadParm)
87{
88 PASYNCTHREADPARM pThreadInfo;
89
90 asyncThreadMutex.enter();
91 pThreadInfo = threadList;
92
93 if(pThreadInfo == pThreadParm) {
94 threadList = pThreadParm->next;
95 }
96 else {
97 while(pThreadInfo->next) {
98 if(pThreadInfo->next == pThreadParm) {
99 pThreadInfo->next = pThreadParm->next;
100 break;
101 }
102 pThreadInfo = pThreadInfo->next;
103 }
104 if(pThreadInfo == NULL) {
105 dprintf(("RemoveFromQueue: parm %x not found!!", pThreadParm));
106 DebugInt3();
107 }
108 }
109 memset(pThreadParm, 0, sizeof(*pThreadParm));
110 asyncThreadMutex.leave();
111}
112//******************************************************************************
113//******************************************************************************
114int WIN32API WSACancelAsyncRequest(LHANDLE hAsyncTaskHandle)
115{
116 PASYNCTHREADPARM pThreadInfo;
117 BOOL found = FALSE;
118
119 dprintf(("WSACancelAsyncRequest: cancel task %x", hAsyncTaskHandle));
120 asyncThreadMutex.enter();
121 pThreadInfo = threadList;
122
123 while(pThreadInfo) {
124 if(pThreadInfo->hAsyncTaskHandle == hAsyncTaskHandle) {
125 pThreadInfo->fCancelled = TRUE;
126 found = TRUE;
127 break;
128 }
129 pThreadInfo = pThreadInfo->next;
130 }
131 asyncThreadMutex.leave();
132 if(found == FALSE) {
133 WSASetLastError(WSAEINVAL);
134 dprintf(("WSACancelAsyncRequest: task not found!!"));
135 }
136 return (found) ? NO_ERROR : SOCKET_ERROR;
137}
138//******************************************************************************
139//Only to cancel blocking hooks
140//******************************************************************************
141int WIN32API WSACancelBlockingCall()
142{
143 HANDLE hThread = GetCurrentThread();
144
145 dprintf(("WSACancelBlockingCall"));
146#if 0
147 asyncThreadMutex.enter();
148 pThreadInfo = threadList;
149
150 while(pThreadInfo) {
151 if(pThreadInfo->hThread == hThread) {
152 pThreadInfo->fCancelled = TRUE;
153
154 if(pThreadInfo->request == ASYNC_BLOCKHOOK) {
155 ret = so_cancel(pThreadInfo->blockedsocket);
156 }
157
158 found = TRUE;
159 break;
160 }
161 pThreadInfo = pThreadInfo->next;
162 }
163 asyncThreadMutex.leave();
164#endif
165 return SOCKET_ERROR;
166}
167//******************************************************************************
168//dump queue
169//******************************************************************************
170void DumpQueue(void)
171{
172 HANDLE hThread = GetCurrentThread();
173 PASYNCTHREADPARM pThreadInfo;
174
175 dprintf(("DumpQueue"));
176
177 asyncThreadMutex.enter();
178 pThreadInfo = threadList;
179
180 while(pThreadInfo) {
181 dprintf(( "SOCKET %08xh thread#%d events %xh pending %xh, select %d",
182 pThreadInfo->u.asyncselect.s,
183 pThreadInfo->hAsyncTaskHandle,
184 pThreadInfo->u.asyncselect.lEvents,
185 pThreadInfo->u.asyncselect.lEventsPending,
186 pThreadInfo->fWaitSelect));
187 pThreadInfo = pThreadInfo->next;
188 }
189 asyncThreadMutex.leave();
190 dprintf(("DumpQueue done"));
191}
192//******************************************************************************
193//Assumes caller owns async thread mutex!
194//******************************************************************************
195PASYNCTHREADPARM FindAsyncEvent(SOCKET s)
196{
197 PASYNCTHREADPARM pThreadInfo;
198
199 pThreadInfo = threadList;
200 while(pThreadInfo) {
201 if(pThreadInfo->u.asyncselect.s == s && !pThreadInfo->fRemoved) {
202 return pThreadInfo;
203 }
204 pThreadInfo = pThreadInfo->next;
205 }
206 return NULL;
207}
208//******************************************************************************
209//******************************************************************************
210BOOL FindAndSetAsyncEvent(SOCKET s, int mode, int notifyHandle, int notifyData, ULONG lEventMask)
211{
212 PASYNCTHREADPARM pThreadInfo;
213
214 asyncThreadMutex.enter();
215 pThreadInfo = FindAsyncEvent(s);
216 if(pThreadInfo) {
217 pThreadInfo->u.asyncselect.mode = mode;
218 pThreadInfo->u.asyncselect.lEvents = lEventMask;
219 pThreadInfo->u.asyncselect.lEventsPending = lEventMask;
220 pThreadInfo->notifyHandle = notifyHandle;
221 pThreadInfo->notifyData = notifyData;
222 if(lEventMask == 0) {
223 //make sure this thread isn't used anymore
224 pThreadInfo->fRemoved = TRUE;
225 }
226 if(pThreadInfo->fWaitSelect) {
227 //cancel pending select in async select thread (if any)
228 so_cancel(s);
229 }
230
231 //unblock async thread if it was waiting
232 pThreadInfo->u.asyncselect.asyncSem->post();
233 }
234 asyncThreadMutex.leave();
235 return(pThreadInfo != NULL);
236}
237//******************************************************************************
238//******************************************************************************
239void EnableAsyncEvent(SOCKET s, ULONG flags)
240{
241 PASYNCTHREADPARM pThreadInfo;
242
243 asyncThreadMutex.enter();
244 pThreadInfo = FindAsyncEvent(s);
245 if(pThreadInfo) {
246 pThreadInfo->u.asyncselect.lEventsPending |= (pThreadInfo->u.asyncselect.lEvents & flags);
247 //unblock async thread if it was waiting
248 pThreadInfo->u.asyncselect.asyncSem->post();
249
250 //cancel pending select in async select thread (if any)
251 if(pThreadInfo->fWaitSelect) {
252 so_cancel(s);
253 }
254 }
255 asyncThreadMutex.leave();
256}
257//******************************************************************************
258//******************************************************************************
259BOOL QueryAsyncEvent(SOCKET s, HWND *pHwnd, int *pMsg, ULONG *plEvent)
260{
261 PASYNCTHREADPARM pThreadInfo;
262
263 asyncThreadMutex.enter();
264 pThreadInfo = FindAsyncEvent(s);
265 if(pThreadInfo) {
266 *pHwnd = (HWND)pThreadInfo->notifyHandle;
267 *pMsg = pThreadInfo->notifyData;
268 *plEvent = pThreadInfo->u.asyncselect.lEvents;
269 }
270 asyncThreadMutex.leave();
271 return(pThreadInfo != NULL);
272}
273//******************************************************************************
274//******************************************************************************
Note: See TracBrowser for help on using the repository browser.