#include <stdio.h>
#include <stdlib.h>
#include "queue.h"

void Queue_addItem(Queue *list,QueueItem *item) {
    if ( pthread_mutex_lock( &list->mutex ) ) {
	perror( "FATAL" );
	exit( 1 );
    }
    item->next = 0; // just in case
    if ( list->last ) {
	list->last->next = item;
    } else {
	list->head = item;
    }
    list->last = item;
    if ( sem_post( &list->count ) ) {
	perror( "FATAL" );
	exit( 1 );
    }
    if ( pthread_mutex_unlock( &list->mutex ) ) {
	perror( "FATAL" );
	exit( 1 );
    }
}

QueueItem *Queue_getItem(Queue *list) {
    QueueItem *item;
    if ( sem_wait( &list->count ) ) {
	perror( "FATAL" );
	exit( 1 );
    }
    if ( pthread_mutex_lock( &list->mutex ) ) {
	perror( "FATAL" );
	exit( 1 );
    }
    item = list->head;
    list->head = item->next;
    if ( list->head == 0 ) {
	list->last = 0;
    }
    if ( pthread_mutex_unlock( &list->mutex ) ) {
	perror( "FATAL" );
	exit( 1 );
    }
    return item;
}

void Queue_initialize(Queue *list,int n,size_t size) {
    if ( pthread_mutex_lock( &list->mutex ) ) {
        perror( "FATAL" );
        exit( 1 );
    }
    if ( list->head == 0 ) {
	int i = 0;
	for ( ; i < n; i++ ) {
	    QueueItem *x = (QueueItem *) calloc( 1, size );
	    if ( list->head ) {
		list->last->next = x;
	    } else {
		list->head = x;
	    }
	    list->last = x;
	}
	sem_init( &list->count, 0, n );
    }
    if ( pthread_mutex_unlock( &list->mutex ) ) {
        perror( "FATAL" );
        exit( 1 );
    }
}
