Back to TILs

C++ pthread 01

Date: 2024-01-21Last modified: 2024-02-26

Table of contents

// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
void *joinable_thread_callback( void *heap_argument )
{
  int local_argument = *(int *)heap_argument;
  free( heap_argument );

  printf( "Received %d as parameter\n", local_argument );

  // Simulating some time consuming task
  int rc = 1;
  while( rc <= local_argument ) {
    printf( "Thread (%d/%d) doing some work...\n", rc, local_argument );
    sleep( 1 );
    rc++;
  }

  printf( "Thread #%d finished\n", local_argument );

  // Allocate memory for return the result
  int *heap_result = (int *)calloc( 1, sizeof( int ) );
  *heap_result     = local_argument * local_argument;
  return (void *)heap_result;
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
void create_a_joinable_thread( pthread_t *thread_handler, int local_argument )
{
  pthread_attr_t attr;
  pthread_attr_init( &attr );
  pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );

  // Allocate memory for the arguments
  int *heap_argument = (int *)calloc( 1, sizeof( int ) );
  *heap_argument     = local_argument;

  // POSIX thread creation
  pthread_create( thread_handler, &attr, &joinable_thread_callback, (void *)heap_argument );
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
void *detached_thread_callback( void *heap_argument )
{
  int local_argument = *(int *)heap_argument;
  free( heap_argument );

  printf( "Received %d as parameter\n", local_argument );

  // Simulating some time consuming task
  int rc = 1;
  while( rc <= local_argument ) {
    printf( "Detached thread (%d/%d) doing some work...\n", rc, local_argument );
    sleep( 1 );
    rc++;
  }

  printf( "Detached thread #%d finished\n", local_argument );

  pthread_exit( (void *)"return pointer" );
  return NULL;
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
void create_a_detached_thread( pthread_t *thread_handler, int local_argument )
{
  pthread_attr_t attr;
  pthread_attr_init( &attr );
  pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );

  // Allocate memory for the arguments
  int *heap_argument = (int *)calloc( 1, sizeof( int ) );
  *heap_argument     = local_argument;

  // POSIX thread creation
  pthread_create( thread_handler, &attr, &detached_thread_callback, (void *)heap_argument );
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
int main( [[maybe_unused]] int argc, [[maybe_unused]] char **argv )
{
  pthread_t t1;
  pthread_t t2;
  pthread_t t3;
  pthread_t t4;

  void *heap_result_t1;
  void *heap_result_t2;
  void *heap_result_t3;

  create_a_joinable_thread( &t1, 4 );
  create_a_joinable_thread( &t2, 3 );
  create_a_joinable_thread( &t3, 2 );

  create_a_detached_thread( &t4, 6 );

  // Block main thread waiting for child threads finishes
  pthread_join( t1, &heap_result_t1 );
  pthread_join( t2, &heap_result_t2 );
  pthread_join( t3, &heap_result_t3 );

  if( heap_result_t1 ) {
    printf( "Result t1=%d\n", *(int *)heap_result_t1 );
    free( heap_result_t1 );
  }

  if( heap_result_t2 ) {
    printf( "Result t2=%d\n", *(int *)heap_result_t2 );
    free( heap_result_t2 );
  }

  if( heap_result_t3 ) {
    printf( "Result t3=%d\n", *(int *)heap_result_t3 );
    free( heap_result_t3 );
  }

  // Give chance to the detached thread finishes
  sleep( 3 );
  printf( "main finished\n" );
  return 0;
}

Possible output

Received 2 as parameter
Thread (1/2) doing some work...
Received 4 as parameter
Thread (1/4) doing some work...
Received 6 as parameter
Detached thread (1/6) doing some work...
Received 3 as parameter
Thread (1/3) doing some work...
Thread (2/4) doing some work...
Thread (2/2) doing some work...
Detached thread (2/6) doing some work...
Thread (2/3) doing some work...
Thread (3/4) doing some work...
Thread #2 finished
Detached thread (3/6) doing some work...
Thread (3/3) doing some work...
Thread (4/4) doing some work...
Detached thread (4/6) doing some work...
Thread #3 finished
Thread #4 finished
Detached thread (5/6) doing some work...
Result t1=16
Result t2=9
Result t3=4
Detached thread (6/6) doing some work...
Detached thread #6 finished
main finished

References