///////////////////////////////////////////////////////////////////////////////
// threaddemo.cpp                  (mobydisk@mobydisk.com, http://mobydisk.com)
//
// - Quickie demonstration of pthreads on linux
//
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2004 William Garrison, All Rights Reserved
///////////////////////////////////////////////////////////////////////////////

#include <pthread.h>
#include <iostream>
#include "kbhit.cpp"

// On Linux, you must compile with the -D_REENTRANT option.  This tells
// the C/C++ libraries that the functions must be thread-safe
#ifndef _REENTRANT
#error ACK! You need to compile with _REENTRANT defined since this uses threads
#endif

using namespace std;

// Set this to true to stop the threads
// - The volatile keyword tells the compiler that this value may change at any
//   time, since another thread may write to it, and that it should not be
//   included in any optimizations.
volatile int bStop = false;

////////////////////////////////////////////////////////////////////////////////
// Starting point for a thread
////////////////////////////////////////////////////////////////////////////////
void * runMe(void *generic_pointer)
{
   // Do this until we are told to stop
   while (!bStop)
   {
      // Output some text
      cout << static_cast<char *>(generic_pointer) << ",";
      // Relenquish the CPU for another thread
      pthread_yield();
   }
   
   return NULL;
}

////////////////////////////////////////////////////////////////////////////////
// Main program starting point
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
   // These variables holD the IDs of the threads
   pthread_t nThreadID1, nThreadID2;

   // Messages to display
   char szMessage1[] = "ping";
   char szMessage2[] = "pong";
   
   // Create two threads
   // - The first thread will be passed szMessage1, the other gets szMessage2
   pthread_create(&nThreadID1, NULL, runMe, szMessage1);
   pthread_create(&nThreadID2, NULL, runMe, szMessage2);

   // Wait until the user presses a key
   // - The _kbhit function is defined in _kbhit.cpp
   while (!_kbhit())
   {
      // This gives the two threads time to do work.
      pthread_yield();
   }

   // Stop the threads
   bStop = true;

   // Wait for them to exit
   pthread_join(nThreadID1, NULL);
   pthread_join(nThreadID2, NULL);

   // We are done!   
   std::cout << "\nDone!" << std::endl;
   return 0;
}
