2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
14 #include <afs/param.h>
18 #include <WINNT/afsapplib.h>
22 * VARIABLES __________________________________________________________________
26 static LPTASKQUEUE_PARAMS ptqp = NULL;
28 typedef struct TASKQUEUEITEM
30 struct TASKQUEUEITEM *pNext;
34 } TASKQUEUEITEM, *LPTASKQUEUEITEM;
36 static LPTASKQUEUEITEM pTaskQueuePop = NULL;
37 static LPTASKQUEUEITEM pTaskQueuePushAfter = NULL;
38 static CRITICAL_SECTION csTaskQueue;
40 static size_t nThreadsRunning = 0;
41 static size_t nRequestsActive = 0;
46 * PROTOTYPES _________________________________________________________________
50 DWORD WINAPI Task_ThreadProc (PVOID lp);
54 * ROUTINES ___________________________________________________________________
58 void AfsAppLib_InitTaskQueue (LPTASKQUEUE_PARAMS lpp)
66 if (lpp && lpp->fnCreateTaskPacket && lpp->fnPerformTask && lpp->fnFreeTaskPacket)
68 ptqp = New (TASKQUEUE_PARAMS);
69 memcpy (ptqp, lpp, sizeof(TASKQUEUE_PARAMS));
74 void StartTask (int idTask, HWND hReply, PVOID lpUser)
79 static BOOL fStarted = FALSE;
83 InitializeCriticalSection (&csTaskQueue);
86 // Then push this notification onto our TaskQueue, so that the task
87 // thread will pop off each request in turn and take a look at it.
88 // Ideally, PostThreadMessage() and GetMessage() would implement all this
89 // garbage, but that doesn't work properly for some reason...
91 EnterCriticalSection (&csTaskQueue);
93 if ((++nRequestsActive) > nThreadsRunning)
95 if ((!ptqp->nThreadsMax) || (nThreadsRunning < (size_t)(ptqp->nThreadsMax)))
99 if ((hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)Task_ThreadProc, 0, 0, &dwThreadID)) != NULL)
101 SetThreadPriority (hThread, THREAD_PRIORITY_BELOW_NORMAL);
107 LPTASKQUEUEITEM lptqi = New (TASKQUEUEITEM);
109 lptqi->idTask = idTask;
110 lptqi->hReply = hReply;
111 lptqi->lpUser = lpUser;
113 if (pTaskQueuePushAfter != NULL)
114 pTaskQueuePushAfter->pNext = lptqi;
115 pTaskQueuePushAfter = lptqi;
117 if (pTaskQueuePop == NULL)
118 pTaskQueuePop = lptqi;
120 LeaveCriticalSection (&csTaskQueue);
124 DWORD WINAPI Task_ThreadProc (PVOID lp)
126 BOOL fJustDidTask = FALSE;
133 EnterCriticalSection (&csTaskQueue);
138 fJustDidTask = FALSE;
141 if (pTaskQueuePop != NULL)
143 LPTASKQUEUEITEM lptqiNext = pTaskQueuePop->pNext;
144 tqi = *pTaskQueuePop;
145 Delete (pTaskQueuePop);
146 if (pTaskQueuePushAfter == pTaskQueuePop)
147 pTaskQueuePushAfter = NULL;
148 pTaskQueuePop = lptqiNext;
153 // is this thread unnecessary?--that is, if we couldn't find anything
154 // to do, then kill off all threads.
159 LeaveCriticalSection (&csTaskQueue);
163 LeaveCriticalSection (&csTaskQueue);
168 if ((ptp = (*ptqp->fnCreateTaskPacket)(tqi.idTask, tqi.hReply, tqi.lpUser)) != NULL)
170 (*ptqp->fnPerformTask)(ptp);
173 if (tqi.hReply && IsWindow (tqi.hReply))
175 PostMessage (tqi.hReply, WM_ENDTASK, 0, (LPARAM)ptp);
177 else if (ptp != NULL)
179 (*ptqp->fnFreeTaskPacket)(ptp);