/***************************************************************************
 *   Copyright (C) 2005 by Brian Lauber   *
 *   bml8@case.edu   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#define _REENTRANT

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>

// These are the arguments that will be passed to the Car thread.
struct CarArgs
{
  pthread_t  tID;
  sem_t     *CarWait;
};


// This is the function that the Car thread will immediate execute
void* Car(void *args)
{
  // All pthread functions accept a pointer to a void structure.  This is great because it allows you
  // to pass any type of argument to a pthread function; unfortunately, this also means that you will
  // need to recast the void pointer to the type of structure that it actually represents.  In this
  // instance, args is actually a CarArgs structure, so we recast it into a CarArgs pointer as follows:
  struct CarArgs *myArgs = (struct CarArgs *) args;
  int i = 0;

  // Wait for the semaphore, and then print a kewl message
  for(i = 0; i < 10; ++i)
  {
    sem_wait(myArgs->CarWait);
    printf("id:%u Vroom Vroom! %i\n", myArgs->tID, i);
  }

  // Because this thread had a long day, it's going to go ahead and exit now.
  pthread_exit(NULL);

  // This code should never execute because the car thread is lazy and already left
  while(1)
    printf("I shouldn't be here!!\n");
}



int main(int argc, char *argv[])
{
  struct CarArgs theArgs;  // These are the arguments that will be passed to the car thread
  sem_t          theSem;   // This is the semaphore that the car and main process will share
  int i;

  sem_init(&theSem, 0, 0);    // Initialize the semaphore.  Note that the last 0 initializes the semaphore to 0
  theArgs.CarWait = &theSem;  // We are creating a pointer to the semaphore that the car will have access to (from its args)

  pthread_create( &(theArgs.tID), NULL, Car, &theArgs); // Create the thread; execute Car function
                                                        // The first argument is passing the
                                                        // thread id to the car thread

  printf("Created thread with id %u\n", theArgs.tID);   // Print a happy message!

  // Once every second, signal theSem and allow the car to do its thing
  for(i = 0; i < 10; ++i)
  {
    sleep(1);
    sem_post(&theSem);
  }

  printf("I'm done!\n");

  pthread_join(theArgs.tID, NULL); // Wait for the thread to exit
  return EXIT_SUCCESS;             // Now it's my turn to exit
}

