view src/Queue.c @ 14:5f65da34f4f3

add runnable pthread mode.
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Sat, 09 Jan 2010 18:13:49 +0900
parents 07fab8c367b2
children d31f9a0f9024
line wrap: on
line source

#include <stdlib.h>
#include <pthread.h>
/* TODO: malloc.  */
#include "List.h"
#include "Queue.h"

/*
 *
 *  Usage:
 *
 *          |Blocks|Unblocks|
 * ---------+------+--------+
 *   Insert | put  | offer  |
 *   Remove | take | poll   |
 *   Examine| peek |        |
 *
 *  But, insert operation dosen't block in this implementation.
 *
 */


Queue *
createQueue(int blocking)
{
	Queue *newQ;
	newQ = malloc(sizeof(struct _Queue));
	newQ->head = NULL;
	newQ->tail = NULL;
	//newQ->mutex = PTHREAD_MUTEX_INITIALIZER;
	pthread_mutex_init(&newQ->mutex, NULL);
	pthread_cond_init(&newQ->cond, NULL);
	return newQ;
}

void
destroyQueue(Queue *queue)
{
	List *l;
	l = queue->head;
	while (l) {
		List *n;
		n = l->next;
		free(l);
		l = n;
	}
	pthread_mutex_destroy(&queue->mutex);
	pthread_cond_destroy(&queue->cond);
	free(queue);
}

void
queuePut(Queue *queue, void *data)
{
	List *oldhead, *newlist;

	newlist = malloc(sizeof(struct _List));
	newlist->data = data;
	pthread_mutex_lock(&queue->mutex);

	oldhead = queue->head;
	if (oldhead) {
		oldhead->prev = newlist;
	} else {
		queue->tail = newlist;
	}
	newlist->next = oldhead;
	newlist->prev = NULL;
	queue->head = newlist;
	queue->length++;

	pthread_cond_broadcast(&queue->cond);
	pthread_mutex_unlock(&queue->mutex);
	return ;
}

void *
queueTake(Queue *queue)
{
	List *first, *second;
	void *data;

	pthread_mutex_lock(&queue->mutex);

	while (!queue->tail) {
		pthread_cond_wait(&queue->cond, &queue->mutex);
	}

	first = queue->tail;
	second = first->prev;
	data = first->data;
	free(first);

	if (second) {
		second->next = NULL;
	} else {
		queue->head = NULL;
	}
	queue->tail = second;
	queue->length--;

	pthread_mutex_unlock(&queue->mutex);
	return data;
}

void
queueOffer(Queue *queue, void *data)
{
	queuePut(queue, data);
}

void *
queuePoll(Queue *queue)
{
	List *first, *second;
	void *data;

	pthread_mutex_lock(&queue->mutex);

	if (!queue->tail) {
		pthread_mutex_unlock(&queue->mutex);
		return NULL;
	}

	first = queue->tail;
	second = first->prev;
	data = first->data;
	free(first);

	if (second) {
		second->next = NULL;
	} else {
		queue->head = NULL;
	}
	queue->tail = second;
	queue->length--;

	pthread_mutex_unlock(&queue->mutex);
	return data;
}

void *
queuePeek(Queue *queue)
{
	List *first, *second;
	void *data;

	pthread_mutex_lock(&queue->mutex);

	if (!queue->tail) {
		data = NULL;
	} else {
		data = queue->tail->data;
	}

	pthread_mutex_unlock(&queue->mutex);
	return data;
}