13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Stream Library
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ---------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Thread safe ringbuffer
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRingbuffer.h"
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSemaphore.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <stdlib.h>
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <stdio.h>
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct deRingbuffer_s
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deInt32			blockSize;
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deInt32			blockCount;
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deInt32*		blockUsage;
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8*		buffer;
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSemaphore		emptyCount;
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSemaphore		fullCount;
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deInt32			outBlock;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deInt32			outPos;
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deInt32			inBlock;
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deInt32			inPos;
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deBool			stopNotified;
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deBool			consumerStopping;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
523c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeRingbuffer* deRingbuffer_create (deInt32 blockSize, deInt32 blockCount)
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deRingbuffer* ringbuffer = (deRingbuffer*)deCalloc(sizeof(deRingbuffer));
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(ringbuffer);
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(blockCount > 0);
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(blockSize > 0);
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->blockSize	= blockSize;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->blockCount	= blockCount;
62f096bcea8008dac1cb75d09ee03164321dc6ad14Jarkko Pöyry	ringbuffer->buffer		= (deUint8*)deMalloc(sizeof(deUint8) * (size_t)blockSize * (size_t)blockCount);
63f096bcea8008dac1cb75d09ee03164321dc6ad14Jarkko Pöyry	ringbuffer->blockUsage	= (deInt32*)deMalloc(sizeof(deUint32) * (size_t)blockCount);
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->emptyCount	= deSemaphore_create(ringbuffer->blockCount, DE_NULL);
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->fullCount	= deSemaphore_create(0, DE_NULL);
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!ringbuffer->buffer		||
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!ringbuffer->blockUsage	||
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!ringbuffer->emptyCount	||
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!ringbuffer->fullCount)
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ringbuffer->emptyCount)
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deSemaphore_destroy(ringbuffer->emptyCount);
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ringbuffer->fullCount)
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deSemaphore_destroy(ringbuffer->fullCount);
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFree(ringbuffer->buffer);
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFree(ringbuffer->blockUsage);
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFree(ringbuffer);
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
82f096bcea8008dac1cb75d09ee03164321dc6ad14Jarkko Pöyry	memset(ringbuffer->blockUsage, 0, sizeof(deInt32) * (size_t)blockCount);
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->outBlock	= 0;
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->outPos		= 0;
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->inBlock		= 0;
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->inPos		= 0;
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->stopNotified		= DE_FALSE;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->consumerStopping	= DE_FALSE;
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ringbuffer;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deRingbuffer_stop (deRingbuffer* ringbuffer)
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Set notify to true and increment fullCount to let consumer continue */
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->stopNotified = DE_TRUE;
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSemaphore_increment(ringbuffer->fullCount);
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deRingbuffer_destroy (deRingbuffer* ringbuffer)
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSemaphore_destroy(ringbuffer->emptyCount);
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSemaphore_destroy(ringbuffer->fullCount);
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	free(ringbuffer->buffer);
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	free(ringbuffer->blockUsage);
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	free(ringbuffer);
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deStreamResult producerStream_write (deStreamData* stream, const void* buf, deInt32 bufSize, deInt32* written)
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deRingbuffer* ringbuffer = (deRingbuffer*)stream;
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(stream);
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* If ringbuffer is stopping return error on write */
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (ringbuffer->stopNotified)
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_STREAMRESULT_ERROR;
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*written = 0;
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Write while more data available */
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (*written < bufSize)
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deInt32		writeSize	= 0;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8*	src			= DE_NULL;
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8*	dst			= DE_NULL;
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* If between blocks accuire new block */
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ringbuffer->inPos == 0)
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deSemaphore_decrement(ringbuffer->emptyCount);
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeSize	= deMin32(ringbuffer->blockSize - ringbuffer->inPos, bufSize - *written);
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst			= ringbuffer->buffer + ringbuffer->blockSize * ringbuffer->inBlock + ringbuffer->inPos;
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		src			= (deUint8*)buf + *written;
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
144f096bcea8008dac1cb75d09ee03164321dc6ad14Jarkko Pöyry		deMemcpy(dst, src, (size_t)writeSize);
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ringbuffer->inPos += writeSize;
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*written += writeSize;
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ringbuffer->blockUsage[ringbuffer->inBlock] += writeSize;
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Block is full move to next one (or "between" this and next block) */
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ringbuffer->inPos == ringbuffer->blockSize)
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ringbuffer->inPos = 0;
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ringbuffer->inBlock++;
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ringbuffer->inBlock == ringbuffer->blockCount)
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ringbuffer->inBlock = 0;
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deSemaphore_increment(ringbuffer->fullCount);
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_STREAMRESULT_SUCCESS;
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deStreamResult producerStream_flush (deStreamData* stream)
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deRingbuffer* ringbuffer = (deRingbuffer*)stream;
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(stream);
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* No blocks reserved by producer */
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (ringbuffer->inPos == 0)
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_STREAMRESULT_SUCCESS;
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->inPos		= 0;
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ringbuffer->inBlock++;
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (ringbuffer->inBlock == ringbuffer->blockCount)
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ringbuffer->inBlock = 0;
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSemaphore_increment(ringbuffer->fullCount);
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_STREAMRESULT_SUCCESS;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deStreamResult producerStream_deinit (deStreamData* stream)
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(stream);
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	producerStream_flush(stream);
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* \note mika Stream doesn't own ringbuffer, so it's not deallocated */
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_STREAMRESULT_SUCCESS;
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deStreamResult consumerStream_read (deStreamData* stream, void* buf, deInt32 bufSize, deInt32* read)
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deRingbuffer* ringbuffer = (deRingbuffer*)stream;
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(stream);
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*read = 0;
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(ringbuffer);
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (*read < bufSize)
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deInt32		writeSize	= 0;
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8*	src			= DE_NULL;
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8*	dst			= DE_NULL;
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* If between blocks accuire new block */
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ringbuffer->outPos == 0)
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			/* If consumer is set to stop after everything is consumed,
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 * do not block if there is no more input left
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 */
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ringbuffer->consumerStopping)
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				/* Try to accuire new block, if can't there is no more input */
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!deSemaphore_tryDecrement(ringbuffer->fullCount))
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return DE_STREAMRESULT_END_OF_STREAM;
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				/* If not stopping block until there is more input */
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deSemaphore_decrement(ringbuffer->fullCount);
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				/* Ringbuffer was set to stop */
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ringbuffer->stopNotified)
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ringbuffer->consumerStopping = DE_TRUE;
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeSize	= deMin32(ringbuffer->blockUsage[ringbuffer->outBlock] - ringbuffer->outPos, bufSize - *read);
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		src			= ringbuffer->buffer + ringbuffer->blockSize * ringbuffer->outBlock + ringbuffer->outPos;
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst			= (deUint8*)buf + *read;
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
241f096bcea8008dac1cb75d09ee03164321dc6ad14Jarkko Pöyry		deMemcpy(dst, src, (size_t)writeSize);
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ringbuffer->outPos += writeSize;
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*read += writeSize;
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Block is consumed move to next one (or "between" this and next block) */
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ringbuffer->outPos == ringbuffer->blockUsage[ringbuffer->outBlock])
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ringbuffer->blockUsage[ringbuffer->outBlock] = 0;
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ringbuffer->outPos = 0;
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ringbuffer->outBlock++;
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ringbuffer->outBlock == ringbuffer->blockCount)
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ringbuffer->outBlock = 0;
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deSemaphore_increment(ringbuffer->emptyCount);
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_STREAMRESULT_SUCCESS;
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deStreamResult consumerStream_deinit (deStreamData* stream)
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(stream);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(stream);
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_STREAMRESULT_SUCCESS;
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/* There are no sensible errors so status is always good */
2733c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeStreamStatus dummy_getStatus (deStreamData* stream)
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(stream);
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_STREAMSTATUS_GOOD;
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/* There are no sensible errors in ringbuffer */
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* dummy_getError (deStreamData* stream)
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(stream);
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(stream);
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_NULL;
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const deIOStreamVFTable producerStreamVFTable = {
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_NULL,
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	producerStream_write,
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dummy_getError,
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	producerStream_flush,
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	producerStream_deinit,
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dummy_getStatus
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const deIOStreamVFTable consumerStreamVFTable = {
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	consumerStream_read,
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_NULL,
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dummy_getError,
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_NULL,
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	consumerStream_deinit,
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dummy_getStatus
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deProducerStream_init (deOutStream* stream, deRingbuffer* buffer)
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stream->ioStream.streamData = (deStreamData*)buffer;
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stream->ioStream.vfTable = &producerStreamVFTable;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deConsumerStream_init (deInStream* stream, deRingbuffer* buffer)
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stream->ioStream.streamData = (deStreamData*)buffer;
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	stream->ioStream.vfTable = &consumerStreamVFTable;
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
317