Why would you want to have threads "compete to read from buffer"? The data can be easily partitioned as it's read by the thread doing the reading. Contending to get data from a buffer gains nothing while likely wasting both CPU and wall clock time.
Since you're processing line-by-line, just read lines from the file and pass the buffers by pointer to the worker threads.
Assuming you're running on a POSIX-compliant system, something like this:
#include <unistd.h>
#include <pthread.h>
#define MAX_LINE_LEN 1024
#define NUM_THREADS 8
// linePipe holds pointers to lines sent to
// worker threads
static int linePipe[ 2 ];
// bufferPipe holds pointers to buffers returned
// from worker threads and used to read data
static int bufferPipe[ 2 ];
// thread function that actually does the work
void *threadFunc( void *arg )
{
const char *linePtr;
for ( ;; )
{
// get a pointer to a line from the pipe
read( linePipe[ 1 ], &linePtr, sizeof( linePtr ) );
// end loop on NULL linePtr value
if ( !linePtr )
{
break;
}
// process line
// return the buffer
write( bufferPipe[ 0 ], &linePtr, sizeof( linePtr ) );
}
return( NULL );
}
int main( int argc, char **argv )
{
pipe( linePipe );
pipe( bufferPipe );
// create buffers and load them into the buffer pipe for reading
for ( int ii = 0; ii < ( 2 * NUM_THREADS ); ii++ )
{
char *buffer = malloc( MAX_LINE_LEN );
write( bufferPipe[ 0 ], &buffer, sizeof( buffer ) );
}
pthread_t tids[ NUM_THREADS ];
for ( int ii = 0; ii < NUM_THREADS; ii++ )
{
pthread_create( &( tids[ ii ] ), NULL, thread_func, NULL );
}
FILE *fp = ...
for ( ;; )
{
char *linePtr;
// get the pointer to a buffer from the buffer pipe
read( bufferPipe[ 1 ], &linePtr, sizeof( linePtr ) );
// read a line from the current file into the buffer
char *result = fgets( linePtr, MAX_LINE_LEN, fp );
if ( result )
{
// send the line to the worker threads
write( linePipe, &linePtr, sizeof( linePtr ) );
}
else
{
// either end loop, or open another file
fclose( fp );
fp = fopen( ... );
}
}
// clean up and exit
// send NULL to cause worker threads to stop
char *nullPtr = NULL;
for ( int ii = 0; ii < NUM_THREADS; ii++ )
{
write( linePipe[ 0 ], &nullPtr, sizeof( nullPtr ) );
}
// wait for worker threads to stop
for ( int ii = 0; ii < NUM_THREADS; ii++ )
{
pthread_join( tids[ ii ], NULL );
}
return( 0 );
}