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().
#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();
}
}
}