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

Last change on this file since 5087 was 3557, checked in by sandervl, 25 years ago

don't always call so_cancel

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