GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 17-Jan-2005, 05:51
pablowablo pablowablo is offline
New Member
 
Join Date: Apr 2004
Posts: 24
pablowablo is on a distinguished road

Bounded Buffering?


Is it absolutely necessary to use semaphores in a bounded buffering scenarrio involving two threads? (1 thread write, 1 thread read).

Also is a semaphore a special variable or could just be any integer value? I'm asking because I'm trying out a streaming application, and on some occasions my application crashes, probably due to accessing same buffers at the same time...

For those who are bored here's my code.... Do I need semaphores here? I assumed from the start that my write buffer can never be my read buffer... Basically, Fill_Buffers() is the write thread, and the read thread operates through Get_Byte().

CPP / C++ / C Code:
#include "Buffer.h"
#include "Out_Buffer.h"
#include "Memory.h"
#include "PNOHeader.h"

#define SEEK_SET 1
#define SEEK_CUR 2
#define SEEK_END 3

File_Struct* g_file;
Buffer_Struct *in_buffers;
UInt32 g_num_inBuffers=0;
extern char g_streamStat;
static UInt16 atBuffer;	//index of the active read buffer
static UInt16 toBuffer;	//index of the active write buffer
static Buffer_Struct *activeBuf; //buffer to be emptied
static Buffer_Struct *nextBuf;	//buffer to be filled
extern soundType *userData;

static inline Buffer_Struct *Get_Next_Full_Buffer();
static inline Buffer_Struct *Get_Next_Empty_Buffer();
static inline void 	Read_File();

/***************************************************************************
	Name: Open_File
	Author: Pablo
	Description: Temporary... opens an mp3 file, then initializes the file
				 structure ... wala pa streaming.. 
				 malamang tatanggalin pag streaming na..papalitan ng CONNECT
	Parameters: path of the file
	Return: pointer Structure of the file
****************************************************************************/
STATUS Open_File(char* filename)
{
	File_Struct file1;
	
	if(!filename || VFSFileOpen(1, filename, vfsModeRead, &file1.ref))
		return 0;
	
	VFSFileSize(file1.ref, &(file1.fileSize));
	file1.bytesRead = 0;
	g_file = (File_Struct*)MemPtrNew(sizeof(File_Struct));
	
	if(!g_file)
	{
		VFSFileClose(file1.ref);
		return ERROR;
	}
	MemMove(g_file, &file1, sizeof(File_Struct));
	
	return OK;
}


/***************************************************************************
	Name: Close_File
	Author: Pablo
	Description: Closes the file and frees the buffers
	Parameters: NONE
	Return: NONE
****************************************************************************/
void Close_File()
{
	if(!g_file)return;
	
	VFSFileClose(g_file->ref);
	MemPtrFree(g_file);
	for(UInt16 i=0;i<g_num_inBuffers;i++)
		MemPtrFree(in_buffers[i].buf);
	MemPtrFree(in_buffers);
}


/***************************************************************************
	Name: Read_File
	Author: Pablo
	Description: fills the buffer
	Parameters: NONE
	Return: NONE
****************************************************************************/
static inline void Read_File()
{
	VFSFileRead(g_file->ref, IN_BUFFER_SIZE, nextBuf->buf, &nextBuf->bufSize);
	nextBuf->bufPos = 0;
	nextBuf->isFull = 1;
}


/***************************************************************************
	Name: Get_File_Pos
	Author: Pablo
	Description: returns the position of the file pointer
	Parameters: NONE
	Return: NONE

****************************************************************************/
UInt32 Get_File_Pos()
{
	if(!g_file)
		return 0;
		
	return (g_file->bytesRead);
}


/***************************************************************************
	Name: Get_Next_Full_Buffer()
	Author: Pablo
	Description: looks for the next available buffer
	Parameters: NONE
	Return: pointer to the available buffer

****************************************************************************/
static inline Buffer_Struct *Get_Next_Full_Buffer()
{
	if(atBuffer == (g_num_inBuffers -1))	//if at the last buffer
	{
		while(!in_buffers[0].isFull && !Is_EOF()); //wait while next buffer is empty
		atBuffer = 0; //set active buffer to first buffer
		return &in_buffers[0];
	}
	
	while(!in_buffers[atBuffer + 1].isFull && !Is_EOF()); //wait while next buffer is empty
	atBuffer = atBuffer + 1; //set active buffer to next buffer
	return &in_buffers[atBuffer];	
}

/***************************************************************************
	Name: Get_Byte
	Author: Pablo
	Description: returns a byte from the buffer
	Parameters: pointer to the file structure 
	Return: one byte from the buffer
****************************************************************************/
UInt32 Get_Byte()
{
	UInt32 byte;
	UInt32 bytesRead;
	
	if(activeBuf->bufPos >= activeBuf->bufSize) //if current buffer is empty
	{
		activeBuf->isFull = 0;
		activeBuf = Get_Next_Full_Buffer();
	}
		
	if(Is_EOF())
		return TEMP_EOF;

	byte = activeBuf->buf[activeBuf->bufPos];
	activeBuf->bufPos++;
	g_file->bytesRead++;
			
	return byte & 0xff;
}

/***************************************************************************
	Name: Get_Num_Bytes
	Author: Pablo
	Description: gets specied number of bytes from the buffer
	Parameters: pointer to the file structure, number of bytes to get
				array to contain the bytes 
	Return: OK if numbytes were taken else ERROR
****************************************************************************/
STATUS Get_Num_Bytes(UInt32 numBytes, UInt32 byteArray[])
{
	UInt32 i, temp;
	
	for(i = 0; i < numBytes; i++)
	{
		if(!Is_EOF())
		{
			temp = Get_Byte();
			byteArray[i] = temp;
			
		}
		else return ERROR;
	}
	return OK;
}


/***************************************************************************
	Name: Is_EOF
	Author: Pablo
	Description: checks end of file status of file... are all bytes read?
	Parameters: pointer to the file structure 
	Return: true if done reading file.. otherwise false
****************************************************************************/
BOOLEAN Is_EOF()
{
		
	//if( VFSFileEOF(file->ref == vfsErrFileEOF) && file->bufPos >= file->bufSize )
	if(g_file->bytesRead >= g_file->fileSize)
		return TRUE;
	else
		return FALSE;
}


/***************************************************************************
	Name: Get_Ref
	Author: Pablo
	Description: returns the file reference
	Parameters: NONE
	Return: pointer to the file reference

****************************************************************************/

FileRef* Get_Ref()
{
	if(g_file)
		return &g_file->ref;
	return 0;
}


/***************************************************************************
	Name: Init_Buffers()
	Author: Pablo
	Description: Allocates the initial buffers.  Calls Read_File() to fill buffers
	Parameters: NONE
	Return: OK if all buffers were allocated, ERROR otherwise

****************************************************************************/

STATUS Init_Buffers(UInt32 num_buffers)
{
	UInt32 freeMemory = Get_Heap_Info(1);
	
	while(num_buffers * IN_BUFFER_SIZE > freeMemory - OUT_BUFFER_MAX_SIZE) //while requested buffer size is greater than
		num_buffers--; //available memory(save OUTBSIZE for output buffers) reduce buffer size
		
	atBuffer = 0;
	toBuffer = 0;
	g_num_inBuffers = num_buffers;
	in_buffers = (Buffer_Struct*)MemPtrNew(sizeof(Buffer_Struct) * g_num_inBuffers);
	
	if(!in_buffers)
		return ERROR;
	
	for(UInt16 i=0;i<g_num_inBuffers;i++)
	{
		in_buffers[i].buf = (unsigned char*)MemPtrNew(IN_BUFFER_SIZE);	//allocate buffers
		if(!in_buffers[i].buf)
			return ERROR;
		
		nextBuf = &in_buffers[i];	//set active buffer
		Read_File();	//fill active buffer		
	}

	activeBuf = &in_buffers[0];
	nextBuf   = &in_buffers[0];
	atBuffer = 0;
	toBuffer = 0;
	
	return OK;
}


/***************************************************************************
	Name: Get_Next_Empty_Buffer
	Author: Pablo
	Description: looks for the next empty buffer.  This buffer will be filled
	Parameters: NONE
	Return: pointer to the empty buffer

****************************************************************************/

static inline Buffer_Struct* Get_Next_Empty_Buffer()
{
	if(toBuffer == (g_num_inBuffers - 1))
	{
		while(in_buffers[0].isFull && !Is_EOF()); //wait
		toBuffer = 0;
		return &in_buffers[0];
	}
	
	while(in_buffers[toBuffer+1].isFull&& !Is_EOF());
	toBuffer = toBuffer + 1;
	return &in_buffers[toBuffer];
}


/***************************************************************************
	Name: Fill_Buffers
	Author: Pablo
	Description: currently the buffering loop.. may be subject to change..
				 looks for empty buffers then fill it.
	Parameters: NONE
	Return: NONE

****************************************************************************/

void Fill_Buffers()
{
	while(g_streamStat)
	{
		DbgMsgInt(atBuffer, 100,20);
		DbgMsgInt(toBuffer, 100,30);
	
		if(!nextBuf->isFull)
		{
			Read_File();
			nextBuf = Get_Next_Empty_Buffer();
		}
	}
}
Last edited by dsmith : 17-Jan-2005 at 08:54. Reason: Please use [c] & [/c] for posting C code.
 
 

Recent GIDBlogPython ebook by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 17:01.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.