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

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

YD: fixes for opera

File size: 8.1 KB
Line 
1/* $Id: asyncthread.cpp,v 1.7 2001-04-28 16:15:18 sandervl 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;
26static VMutex 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 DosExit(EXIT_THREAD, 0);
45}
46//******************************************************************************
47//******************************************************************************
48ULONG QueueAsyncJob(ASYNCTHREADPROC asyncproc, PASYNCTHREADPARM pThreadParm, BOOL fSetBlocking)
49{
50 TID tid;
51
52 pThreadParm->asyncProc = asyncproc;
53 pThreadParm->fActive = TRUE;
54 pThreadParm->fCancelled = FALSE;
55 pThreadParm->next = NULL;
56 pThreadParm->hAsyncTaskHandle = 0;
57
58 pThreadParm->hThread = GetCurrentThread();
59 AddToQueue(pThreadParm);
60
61 if(fSetBlocking) WSASetBlocking(TRUE);
62
63 tid = _beginthread(AsyncThread, NULL, 16384, (PVOID)pThreadParm);
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//******************************************************************************
195static PASYNCTHREADPARM 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, HWND hwnd, int msg, ULONG lEvent)
211{
212 PASYNCTHREADPARM pThreadInfo;
213
214 asyncThreadMutex.enter();
215 pThreadInfo = FindAsyncEvent(s);
216 if(pThreadInfo) {
217 pThreadInfo->u.asyncselect.lEvents = lEvent;
218 pThreadInfo->u.asyncselect.lEventsPending = lEvent;
219 pThreadInfo->hwnd = hwnd;
220 pThreadInfo->msg = msg;
221 if(lEvent == 0) {
222 //make sure this thread isn't used anymore
223 pThreadInfo->fRemoved = TRUE;
224 }
225 if(pThreadInfo->fWaitSelect) {
226 //cancel pending select in async select thread (if any)
227 so_cancel(s);
228 }
229
230 //unblock async thread if it was waiting
231 pThreadInfo->u.asyncselect.asyncSem->post();
232 }
233 asyncThreadMutex.leave();
234 return(pThreadInfo != NULL);
235}
236//******************************************************************************
237//******************************************************************************
238void EnableAsyncEvent(SOCKET s, ULONG flags)
239{
240 PASYNCTHREADPARM pThreadInfo;
241
242 asyncThreadMutex.enter();
243 pThreadInfo = FindAsyncEvent(s);
244 if(pThreadInfo) {
245 pThreadInfo->u.asyncselect.lEventsPending |= (pThreadInfo->u.asyncselect.lEvents & flags);
246 //unblock async thread if it was waiting
247 pThreadInfo->u.asyncselect.asyncSem->post();
248
249 //cancel pending select in async select thread (if any)
250 if(pThreadInfo->fWaitSelect) {
251 so_cancel(s);
252 }
253 }
254 asyncThreadMutex.leave();
255}
256//******************************************************************************
257//******************************************************************************
258BOOL QueryAsyncEvent(SOCKET s, HWND *pHwnd, int *pMsg, ULONG *plEvent)
259{
260 PASYNCTHREADPARM pThreadInfo;
261
262 asyncThreadMutex.enter();
263 pThreadInfo = FindAsyncEvent(s);
264 if(pThreadInfo) {
265 *pHwnd = pThreadInfo->hwnd;
266 *pMsg = pThreadInfo->msg;
267 *plEvent = pThreadInfo->u.asyncselect.lEvents;
268 }
269 asyncThreadMutex.leave();
270 return(pThreadInfo != NULL);
271}
272//******************************************************************************
273//******************************************************************************
Note: See TracBrowser for help on using the repository browser.