THREADPOOL.C
/*++ 
 
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; 
}