/*++
Copyright (c) 1997 Microsoft Corporation
Module Name: ThreadPool.c
Abstract:
Work queue management functions.
--*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <httpext.h>
#include "threadpool.h"
//
// Structure to create simple linked list
//
typedef struct {
EXTENSION_CONTROL_BLOCK *pECB; // Data for list entry
DWORD dwNextEntry; // Pointer to next entry
} ECB_QUEUE_ENTRY;
//
// Array that is a simple linked list
//
ECB_QUEUE_ENTRY ECBqueue[WORK_QUEUE_ENTRIES];
//
// Index of next ECBqueue entry to use, and last Entry in use.
//
DWORD dwCurrentEntry, dwLastEntry;
//
// Flag to indicate that there are no other entries in the ECBqueue
//
BOOL fQueueEmpty;
BOOL
InitThreadPool(
void
)
/*++
Purpose:
Initialize our thread pool.
--*/
{
DWORD i;
DWORD dwThreadID;
//
// Create Semaphore in nonsignaled state
//
if ( (hWorkSem = CreateSemaphore( NULL, 0, 0x7fffffff, NULL )) == NULL ) {
return FALSE;
}
InitializeCriticalSection( &csQueueLock );
fQueueEmpty = TRUE;
//
// Create Pool Threads
//
for ( i = 0; i < POOL_THREADS; i++ ) {
if ( CreateThread(
NULL,
0,
WorkerFunction,
(LPVOID) i,
0,
&dwThreadID
) == NULL ) {
return FALSE;
}
}
//
// Clear work queue
//
ZeroMemory( ECBqueue, WORK_QUEUE_ENTRIES * sizeof (ECB_QUEUE_ENTRY) );
return TRUE;
}
BOOL
AddWorkQueueEntry(
IN EXTENSION_CONTROL_BLOCK * pECB
)
/*++
Purpose:
Add single work unit to the queue
Arguments:
pECB - pointer to the extension control block
Returns:
TRUE if the unit was successfully queued
FALSE if queue is full
--*/
{
DWORD i;
for ( i = 0; i < WORK_QUEUE_ENTRIES; i++ ) {
if ( ECBqueue[i].pECB == NULL ) {
if ( fQueueEmpty ) {
dwCurrentEntry = i;
fQueueEmpty = FALSE;
} else {
ECBqueue[dwLastEntry].dwNextEntry = i;
}
ECBqueue[i].pECB = pECB;
dwLastEntry = i;
return TRUE;
}
}
// If no NULL queue entry found, indicate failure
return FALSE;
}
BOOL
GetWorkQueueEntry(
OUT EXTENSION_CONTROL_BLOCK ** ppECB
)
/*++
Purpose:
Arguments:
Returns:
--*/
{
if ( (*ppECB = ECBqueue[dwCurrentEntry].pECB) == NULL ) {
return FALSE;
} else {
ECBqueue[dwCurrentEntry].pECB = NULL;
if (dwCurrentEntry == dwLastEntry)// If this is only pending item
fQueueEmpty = TRUE;
else
dwCurrentEntry = ECBqueue[dwCurrentEntry].dwNextEntry;
}
return TRUE;
}