Files
selfcare/proxy_c/utils_queue.c
2025-03-03 11:40:37 +08:00

139 lines
2.9 KiB
C

/*
* File: queue.c
* Author: Robert I. Pitts <rip@cs.bu.edu>
* Last Modified: March 9, 2000
* Topic: Queue - Array Implementation
* ----------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include<pthread.h>
#include "utils_queue.h"
/*
* struct queueCDT gives the implementation of a queue.
* It holds the information that we need for each queue.
*/
typedef struct queueCDT {
queueElementT *contents;
int front;
int count;
int elem_size;
pthread_rwlock_t queueRWLock;
}queueCDT;
queueADT QueueCreate(const int elem_size)
{
queueADT queue;
queue = (queueADT)malloc(sizeof(queueCDT));
if(queue == NULL) {
fprintf(stderr, "Insufficient Memory for new Queue.\n");
return NULL; /* Exit program, returning error code. */
}
queue->contents = (queueElementT*)malloc(elem_size * sizeof(queueElementT));
if(queue == NULL) {
fprintf(stderr, "Insufficient Memory for QueueElems.\n");
return NULL; /* Exit program, returning error code. */
}
queue->front = 0;
queue->count = 0;
queue->elem_size = elem_size;
pthread_rwlock_init(&(queue->queueRWLock), NULL);
return queue;
}
void QueueDestroy(queueADT queue)
{
free(queue->contents);
free(queue);
}
int QueueEnter(queueADT queue, queueElementT element)
{
int newElementIndex;
pthread_rwlock_wrlock(&queue->queueRWLock);
if (queue->count >= queue->elem_size) {
fprintf(stderr, "QueueEnter on Full Queue.\n");
pthread_rwlock_unlock(&queue->queueRWLock);
return ERROR_QUEUE; /* Exit program, returning error code. */
}
/*
* Calculate index at which to put
* next element.
*/
newElementIndex = (queue->front + queue->count) % queue->elem_size;
queue->contents[newElementIndex] = element;
queue->count++;
pthread_rwlock_unlock(&queue->queueRWLock);
return SUCCESS_QUEUE;
}
queueElementT QueueDelete(queueADT queue)
{
queueElementT oldElement;
pthread_rwlock_wrlock(&queue->queueRWLock);
if (queue->count <= 0) {
fprintf(stderr, "QueueDelete on Empty Queue.\n");
pthread_rwlock_unlock(&queue->queueRWLock);
return NULL; /* Exit program, returning error code. */
}
/* Save the element so we can return it. */
oldElement = queue->contents[queue->front];
/*
* Advance the index of the front,
* making sure it wraps around the
* array properly.
*/
queue->front++;
queue->front %= queue->elem_size;
queue->count--;
pthread_rwlock_unlock(&queue->queueRWLock);
return oldElement;
}
int QueueIsEmpty(queueADT queue)
{
int rc;
pthread_rwlock_rdlock(&queue->queueRWLock);
rc = queue->count <= 0;
pthread_rwlock_unlock(&queue->queueRWLock);
return rc;
}
int QueueIsFull(queueADT queue)
{
int rc;
pthread_rwlock_rdlock(&queue->queueRWLock);
rc = queue->count >= queue->elem_size;
pthread_rwlock_unlock(&queue->queueRWLock);
return rc;
}