/*****************************************************************************
* FILE: join.c
* DESCRIPTION:
*   This example demonstrates how to "wait" for thread completions by using
*   the Pthread join routine.  Since not all current implementations of
*   Pthreads create threads in a joinable state, the threads in this
*   example are explicitly created in a joinable state so that they can
*   be joined later. Threads also pass back their result via the pthread_exit
*   status argument - something which is a little tricky because result is
*   a double - which is larger than a void pointer. Compare with detached.c.
* AUTHOR: 8/98 Blaise Barney
* LAST REVISED:  07/06/05
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS	4

void *BusyWork(void *t)
{
   int i, tid;
   double result=0.0;
   tid = (int)t;
   printf("Thread %d starting...\n",tid);
   for (i=0; i<1000000; i++)
   {
     result = result + (double)random();
   }
   printf("Thread %d done. Result = %e\n",tid, result);
   pthread_exit((void *) &result);
}

int main(int argc, char *argv[])
{
pthread_t thread[NUM_THREADS];
pthread_attr_t attr;
int rc, t;
void *status;
double finalresult=0.0, thisresult;

/* Initialize and set thread joinable attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

for(t=0;t<NUM_THREADS;t++) {
   printf("Main: creating thread %d\n", t);
   rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t); 
   if (rc) {
     printf("ERROR; return code from pthread_create() is %d\n", rc);
     exit(-1);
     }
  }

/* Free attribute and join with worker threads */
pthread_attr_destroy(&attr);
for(t=0;t<NUM_THREADS;t++) {
  rc = pthread_join(thread[t], &status);
  if (rc) {
    printf("ERROR return code from pthread_join() is %d\n", rc);
    exit(-1);
    }
  printf("Main: completed join with thread %d ",t);
  thisresult = *(double*)status; 
  printf("this result=%e\n",thisresult);
  finalresult += thisresult;
  }

printf("Main: final result = %e.\n", finalresult);
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
