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

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

async select fix

File size: 7.2 KB
Line 
1/* $Id: asyncthread.cpp,v 1.4 2000-04-15 09:23:36 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) {
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 //cancel pending select in async select thread (if any)
199 so_cancel(s);
200
201 //unblock async thread if it was waiting
202 pThreadInfo->u.asyncselect.asyncSem->post();
203 }
204 asyncThreadMutex.leave();
205 return(pThreadInfo != NULL);
206}
207//******************************************************************************
208//******************************************************************************
209void EnableAsyncEvent(SOCKET s, ULONG flags)
210{
211 PASYNCTHREADPARM pThreadInfo;
212
213 asyncThreadMutex.enter();
214 pThreadInfo = FindAsyncEvent(s);
215 if(pThreadInfo) {
216 pThreadInfo->u.asyncselect.lEventsPending |= (pThreadInfo->u.asyncselect.lEvents & flags);
217 //unblock async thread if it was waiting
218 pThreadInfo->u.asyncselect.asyncSem->post();
219
220 //cancel pending select in async select thread (if any)
221 so_cancel(s);
222 }
223 asyncThreadMutex.leave();
224}
225//******************************************************************************
226//******************************************************************************
227BOOL QueryAsyncEvent(SOCKET s, HWND *pHwnd, int *pMsg, ULONG *plEvent)
228{
229 PASYNCTHREADPARM pThreadInfo;
230
231 asyncThreadMutex.enter();
232 pThreadInfo = FindAsyncEvent(s);
233 if(pThreadInfo) {
234 *pHwnd = pThreadInfo->hwnd;
235 *pMsg = pThreadInfo->msg;
236 *plEvent = pThreadInfo->u.asyncselect.lEvents;
237 }
238 asyncThreadMutex.leave();
239 return(pThreadInfo != NULL);
240}
241//******************************************************************************
242//******************************************************************************
Note: See TracBrowser for help on using the repository browser.