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

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

DosExit call no longer necessary

File size: 8.1 KB
Line 
1/* $Id: asyncthread.cpp,v 1.8 2001-04-29 15:42:26 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//******************************************************************************
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 tid = _beginthread(AsyncThread, NULL, 16384, (PVOID)pThreadParm);
62 if (tid == -1) {
63 dprintf(("QueueAsyncJob: _beginthread failed"));
64 if(fSetBlocking) WSASetBlocking(FALSE);
65 RemoveFromQueue(pThreadParm);
66 WSASetLastError(WSAEFAULT);
67 return 0;
68 }
69 pThreadParm->hAsyncTaskHandle = tid;
70 WSASetLastError(NO_ERROR);
71 return pThreadParm->hAsyncTaskHandle;
72}
73//******************************************************************************
74//******************************************************************************
75void AddToQueue(PASYNCTHREADPARM pThreadParm)
76{
77 asyncThreadMutex.enter();
78 pThreadParm->next = threadList;
79 threadList = pThreadParm;
80 asyncThreadMutex.leave();
81}
82//******************************************************************************
83//******************************************************************************
84void RemoveFromQueue(PASYNCTHREADPARM pThreadParm)
85{
86 PASYNCTHREADPARM pThreadInfo;
87
88 asyncThreadMutex.enter();
89 pThreadInfo = threadList;
90
91 if(pThreadInfo == pThreadParm) {
92 threadList = pThreadParm->next;
93 }
94 else {
95 while(pThreadInfo->next) {
96 if(pThreadInfo->next == pThreadParm) {
97 pThreadInfo->next = pThreadParm->next;
98 break;
99 }
100 pThreadInfo = pThreadInfo->next;
101 }
102 if(pThreadInfo == NULL) {
103 dprintf(("RemoveFromQueue: parm %x not found!!", pThreadParm));
104 DebugInt3();
105 }
106 }
107 memset(pThreadParm, 0, sizeof(*pThreadParm));
108 asyncThreadMutex.leave();
109}
110//******************************************************************************
111//******************************************************************************
112int WIN32API WSACancelAsyncRequest(LHANDLE hAsyncTaskHandle)
113{
114 PASYNCTHREADPARM pThreadInfo;
115 BOOL found = FALSE;
116
117 dprintf(("WSACancelAsyncRequest: cancel task %x", hAsyncTaskHandle));
118 asyncThreadMutex.enter();
119 pThreadInfo = threadList;
120
121 while(pThreadInfo) {
122 if(pThreadInfo->hAsyncTaskHandle == hAsyncTaskHandle) {
123 pThreadInfo->fCancelled = TRUE;
124 found = TRUE;
125 break;
126 }
127 pThreadInfo = pThreadInfo->next;
128 }
129 asyncThreadMutex.leave();
130 if(found == FALSE) {
131 WSASetLastError(WSAEINVAL);
132 dprintf(("WSACancelAsyncRequest: task not found!!"));
133 }
134 return (found) ? NO_ERROR : SOCKET_ERROR;
135}
136//******************************************************************************
137//Only to cancel blocking hooks
138//******************************************************************************
139int WIN32API WSACancelBlockingCall()
140{
141 HANDLE hThread = GetCurrentThread();
142
143 dprintf(("WSACancelBlockingCall"));
144#if 0
145 asyncThreadMutex.enter();
146 pThreadInfo = threadList;
147
148 while(pThreadInfo) {
149 if(pThreadInfo->hThread == hThread) {
150 pThreadInfo->fCancelled = TRUE;
151
152 if(pThreadInfo->request == ASYNC_BLOCKHOOK) {
153 ret = so_cancel(pThreadInfo->blockedsocket);
154 }
155
156 found = TRUE;
157 break;
158 }
159 pThreadInfo = pThreadInfo->next;
160 }
161 asyncThreadMutex.leave();
162#endif
163 return SOCKET_ERROR;
164}
165//******************************************************************************
166//dump queue
167//******************************************************************************
168void DumpQueue(void)
169{
170 HANDLE hThread = GetCurrentThread();
171 PASYNCTHREADPARM pThreadInfo;
172
173 dprintf(("DumpQueue"));
174
175 asyncThreadMutex.enter();
176 pThreadInfo = threadList;
177
178 while(pThreadInfo) {
179 dprintf(( "SOCKET %08xh thread#%d events %xh pending %xh, select %d",
180 pThreadInfo->u.asyncselect.s,
181 pThreadInfo->hAsyncTaskHandle,
182 pThreadInfo->u.asyncselect.lEvents,
183 pThreadInfo->u.asyncselect.lEventsPending,
184 pThreadInfo->fWaitSelect));
185 pThreadInfo = pThreadInfo->next;
186 }
187 asyncThreadMutex.leave();
188 dprintf(("DumpQueue done"));
189}
190//******************************************************************************
191//Assumes caller owns async thread mutex!
192//******************************************************************************
193static PASYNCTHREADPARM FindAsyncEvent(SOCKET s)
194{
195 PASYNCTHREADPARM pThreadInfo;
196
197 pThreadInfo = threadList;
198 while(pThreadInfo) {
199 if(pThreadInfo->u.asyncselect.s == s && !pThreadInfo->fRemoved) {
200 return pThreadInfo;
201 }
202 pThreadInfo = pThreadInfo->next;
203 }
204 return NULL;
205}
206//******************************************************************************
207//******************************************************************************
208BOOL FindAndSetAsyncEvent(SOCKET s, HWND hwnd, int msg, ULONG lEvent)
209{
210 PASYNCTHREADPARM pThreadInfo;
211
212 asyncThreadMutex.enter();
213 pThreadInfo = FindAsyncEvent(s);
214 if(pThreadInfo) {
215 pThreadInfo->u.asyncselect.lEvents = lEvent;
216 pThreadInfo->u.asyncselect.lEventsPending = lEvent;
217 pThreadInfo->hwnd = hwnd;
218 pThreadInfo->msg = msg;
219 if(lEvent == 0) {
220 //make sure this thread isn't used anymore
221 pThreadInfo->fRemoved = TRUE;
222 }
223 if(pThreadInfo->fWaitSelect) {
224 //cancel pending select in async select thread (if any)
225 so_cancel(s);
226 }
227
228 //unblock async thread if it was waiting
229 pThreadInfo->u.asyncselect.asyncSem->post();
230 }
231 asyncThreadMutex.leave();
232 return(pThreadInfo != NULL);
233}
234//******************************************************************************
235//******************************************************************************
236void EnableAsyncEvent(SOCKET s, ULONG flags)
237{
238 PASYNCTHREADPARM pThreadInfo;
239
240 asyncThreadMutex.enter();
241 pThreadInfo = FindAsyncEvent(s);
242 if(pThreadInfo) {
243 pThreadInfo->u.asyncselect.lEventsPending |= (pThreadInfo->u.asyncselect.lEvents & flags);
244 //unblock async thread if it was waiting
245 pThreadInfo->u.asyncselect.asyncSem->post();
246
247 //cancel pending select in async select thread (if any)
248 if(pThreadInfo->fWaitSelect) {
249 so_cancel(s);
250 }
251 }
252 asyncThreadMutex.leave();
253}
254//******************************************************************************
255//******************************************************************************
256BOOL QueryAsyncEvent(SOCKET s, HWND *pHwnd, int *pMsg, ULONG *plEvent)
257{
258 PASYNCTHREADPARM pThreadInfo;
259
260 asyncThreadMutex.enter();
261 pThreadInfo = FindAsyncEvent(s);
262 if(pThreadInfo) {
263 *pHwnd = pThreadInfo->hwnd;
264 *pMsg = pThreadInfo->msg;
265 *plEvent = pThreadInfo->u.asyncselect.lEvents;
266 }
267 asyncThreadMutex.leave();
268 return(pThreadInfo != NULL);
269}
270//******************************************************************************
271//******************************************************************************
Note: See TracBrowser for help on using the repository browser.