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);
}