#include "srswq.h"
#include <stdlib.h>

struct _yrtag_SRSWQ
{
	void** data;
	size_t size;
	volatile size_t write;
	volatile size_t read;
};

yrSRSWQ* yrSRSWQ_create(size_t capacity)
{
	yrSRSWQ* out = malloc(sizeof(yrSRSWQ));
	if(!out) return NULL;

	out->data = malloc((capacity + 1) * sizeof(void*));
	if(!out->data) {
		free(out);
		return NULL;
	}
	out->size = capacity + 1;
	out->read = 0;
	out->write = 0;
	return out;
}

void yrSRSWQ_destroy(yrSRSWQ* q)
{
	if(!q) return;
	free(q->data);
	free(q);
}

void* yrSRSWQ_read(yrSRSWQ* q)
{
	if(q->read == q->write) return NULL;
	void* out = *(q->data + q->read);
	q->read = (q->read + 1) % q->size;
	return out;
}

void yrSRSWQ_write_block(yrSRSWQ* q, void* item)
{
	while(yrSRSWQ_isfull(q));//spinwait
	*(q->data + q->write) = item;
	q->write = (q->write + 1) % q->size;
}

int yrSRSWQ_write(yrSRSWQ* q, void* item)
{
	if(yrSRSWQ_isfull(q)) return 0;
	*(q->data + q->write) = item;
	q->write = (q->write + 1) % q->size;
	return 1;
}

int yrSRSWQ_isfull(yrSRSWQ* q)
{
	return ((q->write + 1) % q->size) == q->read;
}

float yrSRSWQ_getload(yrSRSWQ* q)
{
	size_t items = (q->write + q->size - q->read) % q->size;
	return items/(float)(q->size - 1);
}