Skip to content

Instantly share code, notes, and snippets.

@Pacheco95
Forked from rtv/cond.c
Created January 30, 2019 21:15
Show Gist options
  • Save Pacheco95/8a7ea3a3accd7d866b1a00829d16c469 to your computer and use it in GitHub Desktop.
Save Pacheco95/8a7ea3a3accd7d866b1a00829d16c469 to your computer and use it in GitHub Desktop.
An example of using pthread's condition variables, showing how to block a main thread while waiting for worker threads to finish their work, without joining the threads. This could be useful if you want to loop the threads, for example.
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
/* Compile like this:
gcc --std=c99 -lpthread cond.c -o cond
*/
const size_t NUMTHREADS = 20;
/* a global count of the number of threads finished working. It will
be protected by mutex and changes to it will be signalled to the
main thread via cond */
int done = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
/* Note: error checking on pthread_X calls ommitted for clarity - you
should always check the return values in real code. */
/* Note: passing the thread id via a void pointer is cheap and easy,
* but the code assumes pointers and long ints are the same size
* (probably 64bits), which is a little hacky. */
void* ThreadEntry( void* id )
{
const int myid = (long)id; // force the pointer to be a 64bit integer
const int workloops = 5;
for( int i=0; i<workloops; i++ )
{
printf( "[thread %d] working (%d/%d)\n", myid, i, workloops );
sleep(1); // simulate doing some costly work
}
// we're going to manipulate done and use the cond, so we need the mutex
pthread_mutex_lock( &mutex );
// increase the count of threads that have finished their work.
done++;
printf( "[thread %d] done is now %d. Signalling cond.\n", myid, done );
// wait up the main thread (if it is sleeping) to test the value of done
pthread_cond_signal( &cond );
pthread_mutex_unlock( & mutex );
return NULL;
}
int main( int argc, char** argv )
{
puts( "[thread main] starting" );
pthread_t threads[NUMTHREADS];
for( int t=0; t<NUMTHREADS; t++ )
pthread_create( &threads[t], NULL, ThreadEntry, (void*)(long)t );
// we're going to test "done" so we need the mutex for safety
pthread_mutex_lock( &mutex );
// are the other threads still busy?
while( done < NUMTHREADS )
{
printf( "[thread main] done is %d which is < %d so waiting on cond\n",
done, (int)NUMTHREADS );
/* block this thread until another thread signals cond. While
blocked, the mutex is released, then re-aquired before this
thread is woken up and the call returns. */
pthread_cond_wait( & cond, & mutex );
puts( "[thread main] wake - cond was signalled." );
/* we go around the loop with the lock held */
}
printf( "[thread main] done == %d so everyone is done\n", (int)NUMTHREADS );
pthread_mutex_unlock( & mutex );
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment