QUEUE.C
/*++ 
 
Copyright (c) 1995 Intel Corp 
 
Module Name: 
 
    queue.h 
 
Abstract: 
 
    Implementation of functions supplied by this queue manager module. 
 
--*/ 
 
#include <stdio.h> 
#include <malloc.h> 
#include "queue.h" 
 
 
 
  
PQUEUE 
QCreate(void) 
/*++ 
 
Routine Description: 
 
    Creates a new QUEUE, initializes it, and returns it. Returns NULL 
    if memory cannot be allocated in the heap. 
 
Arguments: 
 
    None. 
 
Return Value: 
 
    NULL if memory allocation fails; else a pointer to a new queue. 
 
--*/ 
{ 
 
    PQUEUE Queue; // points to the new queue 
 
    // Allocate space for a new queue. 
    Queue = (PQUEUE)malloc(sizeof(QUEUE)); 
    if (Queue != NULL){ 
 
        // Initialize the new queue. 
        Queue->Head = Q_NULL; 
        Queue->Tail = Q_NULL; 
        InitializeCriticalSection(&Queue->CrSec); 
    } 
    return(Queue); 
} 
 
 
 
  
void 
QFree(PQUEUE Queue) 
/*++ 
 
Routine Description: 
 
    This function removes any items left on the queue, frees them, and 
    then frees the queue itself. 
 
Arguments: 
 
    Queue -- Pointer to the queue to free. 
 
Return Value: 
 
    None. 
 
--*/ 
{ 
 
    LPVOID Object; // points to objects we pull off the queue 
 
    EnterCriticalSection(&Queue->CrSec); 
 
    // Free everything on the queue. 
    Object = QRemove(Queue); 
    while (Object) { 
        free(Object); 
        Object = QRemove(Queue); 
    } 
 
    LeaveCriticalSection(&Queue->CrSec); 
 
    // Free the queue itself. 
    free(Queue); 
} 
 
 
 
  
LPVOID 
QRemove(PQUEUE Queue) 
/*++ 
 
Routine Description: 
 
    This function dequeues one object from Queue and returns a generic 
    pointer to the object.  It is up to the calling function to know 
    the size and type of the object dequeued. 
 
Arguments: 
 
    Queue -- The queue from which to dequeue the object. 
 
Return Value: 
 
    NULL if the queue is empty; else, a pointer to the dequeued object. 
 
--*/ 
{ 
 
    LPVOID Data;    // points to the object we pull off the queue 
 
    EnterCriticalSection(&Queue->CrSec); 
 
    if (Queue->Head == Q_NULL){ 
 
        // If the queue is empty, we will return NULL. 
        Data = NULL; 
 
    } else { 
 
        // Get the pointer, NULL it in the QueueArray. 
        Data = Queue->QueueArray[Queue->Head]; 
        Queue->QueueArray[Queue->Head] = NULL; 
 
        // Check to see if we've just emptied the queue; if so, set 
        // the Head and Tail indices to Q_NULL.  If not, set the Head 
        // index to the right value. 
        if (Queue->Head == Queue->Tail) { 
            Queue->Head = Queue->Tail = Q_NULL; 
        } else { 
            Queue->Head = (Queue->Head + 1) % MAX_QUEUE_SIZE; 
        } 
    } 
 
    LeaveCriticalSection(&Queue->CrSec); 
    return(Data); 
} 
 
 
 
 
  
BOOL 
QInsert( 
    PQUEUE Queue, 
    LPVOID Object) 
/*++ 
 
Routine Description: 
 
    This function enqueues one item into Queue, if there is room for 
    it. 
 
Arguments: 
 
    Queue -- The queue onto which to enqueue Object. 
 
    Object -- A void pointer to the object being enqueued. 
 
Return Value: 
 
    TRUE -- The object was successfully enqueued. 
 
    FALSE -- There were too many items already in the queue; one item 
    must be removed in order to insert another. 
 
--*/ 
{ 
    BOOL ReturnValue; // holds the return value 
 
    EnterCriticalSection(&Queue->CrSec); 
 
    // If the queue is full, set the return value to FALSE and do 
    // nothing; if not, update the indices appropriately and set the 
    // return value to TRUE. 
    if(((Queue->Tail + 1) % MAX_QUEUE_SIZE == Queue->Head) 
       && (Queue->Head != Q_NULL)) { 
 
        ReturnValue = FALSE; 
 
    } else { 
 
        Queue->Tail = (Queue->Tail + 1) % MAX_QUEUE_SIZE; 
        Queue->QueueArray[Queue->Tail] = Object; 
        if (Queue->Head == Q_NULL){ 
            Queue->Head = 0; 
        } 
        ReturnValue = TRUE; 
    } 
 
    LeaveCriticalSection(&Queue->CrSec); 
    return(ReturnValue); 
} 
 
 
 
  
BOOL 
QInsertAtHead( 
    PQUEUE Queue, 
    LPVOID Object) 
/*++ 
 
Routine Description: 
 
    This function inserts one item at the HEAD of the queue.  Of 
    course, this violates queue semantics...but this can be useful at 
    times. 
 
Arguments: 
 
    Queue -- The queue into which to insert Object. 
 
    Object -- A void pointer to the object being inserted. 
 
Return Value: 
 
    TRUE -- The object was successfully inserted at the head of the 
    queue. 
 
    FALSE -- There were too many items already in the queue; one item 
    must be removed in order to insert another. 
 
--*/ 
{ 
 
    BOOL ReturnValue; // holds the return value 
 
    EnterCriticalSection(&Queue->CrSec); 
 
    // If the queue is full, set the return value to FALSE and do 
    // nothing; if not, update the indices appropriately and set the 
    // return value to TRUE. 
    if(((Queue->Tail + 1) % MAX_QUEUE_SIZE == Queue->Head) 
       && (Queue->Head != Q_NULL)) { 
 
        ReturnValue = FALSE; 
 
    } else { 
 
        if (Queue->Head == Q_NULL) { 
 
            // The queue was empty, so just use QInsert. 
            QInsert(Queue, Object); 
        } 
 
        if (Queue->Head == 0) { 
            Queue->Head = MAX_QUEUE_SIZE - 1; 
        } else { 
            Queue->Head = Queue->Head - 1; 
        } 
 
        Queue->QueueArray[Queue->Head] = Object; 
        ReturnValue = TRUE; 
    } 
 
    LeaveCriticalSection(&Queue->CrSec); 
    return(ReturnValue); 
} 
 
 
 
  
BOOL 
QIsEmpty(PQUEUE Queue) 
/*++ 
 
Routine Description: 
 
    This function tells the caller if the queue in question contains 
    any items. 
 
Arguments: 
 
    Queue -- The queue which we want to query. 
 
Return Value: 
 
    TRUE -- The queue is empty. 
 
    FALSE -- The queue contains at least one item. 
 
--*/ 
{ 
    return(Queue->Head == Q_NULL ? TRUE : FALSE); 
}