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
11 #include <afs/param.h>
15 #include <WINNT/afsapplib.h>
19 * VARIABLES __________________________________________________________________
23 static LPTASKQUEUE_PARAMS ptqp = NULL;
25 typedef struct TASKQUEUEITEM
27 struct TASKQUEUEITEM *pNext;
31 } TASKQUEUEITEM, *LPTASKQUEUEITEM;
33 static LPTASKQUEUEITEM pTaskQueuePop = NULL;
34 static LPTASKQUEUEITEM pTaskQueuePushAfter = NULL;
35 static CRITICAL_SECTION csTaskQueue;
37 static size_t nThreadsRunning = 0;
38 static size_t nRequestsActive = 0;
43 * PROTOTYPES _________________________________________________________________
47 DWORD WINAPI Task_ThreadProc (PVOID lp);
51 * ROUTINES ___________________________________________________________________
55 void AfsAppLib_InitTaskQueue (LPTASKQUEUE_PARAMS lpp)
63 if (lpp && lpp->fnCreateTaskPacket && lpp->fnPerformTask && lpp->fnFreeTaskPacket)
65 ptqp = New (TASKQUEUE_PARAMS);
66 memcpy (ptqp, lpp, sizeof(TASKQUEUE_PARAMS));
71 void StartTask (int idTask, HWND hReply, PVOID lpUser)
76 static BOOL fStarted = FALSE;
80 InitializeCriticalSection (&csTaskQueue);
83 // Then push this notification onto our TaskQueue, so that the task
84 // thread will pop off each request in turn and take a look at it.
85 // Ideally, PostThreadMessage() and GetMessage() would implement all this
86 // garbage, but that doesn't work properly for some reason...
88 EnterCriticalSection (&csTaskQueue);
90 if ((++nRequestsActive) > nThreadsRunning)
92 if ((!ptqp->nThreadsMax) || (nThreadsRunning < (size_t)(ptqp->nThreadsMax)))
96 if ((hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)Task_ThreadProc, 0, 0, &dwThreadID)) != NULL)
98 SetThreadPriority (hThread, THREAD_PRIORITY_BELOW_NORMAL);
104 LPTASKQUEUEITEM lptqi = New (TASKQUEUEITEM);
106 lptqi->idTask = idTask;
107 lptqi->hReply = hReply;
108 lptqi->lpUser = lpUser;
110 if (pTaskQueuePushAfter != NULL)
111 pTaskQueuePushAfter->pNext = lptqi;
112 pTaskQueuePushAfter = lptqi;
114 if (pTaskQueuePop == NULL)
115 pTaskQueuePop = lptqi;
117 LeaveCriticalSection (&csTaskQueue);
121 DWORD WINAPI Task_ThreadProc (PVOID lp)
123 BOOL fJustDidTask = FALSE;
130 EnterCriticalSection (&csTaskQueue);
135 fJustDidTask = FALSE;
138 if (pTaskQueuePop != NULL)
140 LPTASKQUEUEITEM lptqiNext = pTaskQueuePop->pNext;
141 tqi = *pTaskQueuePop;
142 Delete (pTaskQueuePop);
143 if (pTaskQueuePushAfter == pTaskQueuePop)
144 pTaskQueuePushAfter = NULL;
145 pTaskQueuePop = lptqiNext;
150 // is this thread unnecessary?--that is, if we couldn't find anything
151 // to do, then kill off all threads.
156 LeaveCriticalSection (&csTaskQueue);
160 LeaveCriticalSection (&csTaskQueue);
165 if ((ptp = (*ptqp->fnCreateTaskPacket)(tqi.idTask, tqi.hReply, tqi.lpUser)) != NULL)
167 (*ptqp->fnPerformTask)(ptp);
170 if (tqi.hReply && IsWindow (tqi.hReply))
172 PostMessage (tqi.hReply, WM_ENDTASK, 0, (LPARAM)ptp);
174 else if (ptp != NULL)
176 (*ptqp->fnFreeTaskPacket)(ptp);