#include <cstdlib>
#include <pthread.h>
#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "episode-timer.h"


static void t(episode_timer &, unsigned)
static void p(episode_timer &, unsigned)
static void time_it(void (* p)(episode_timer &, unsigned), unsigned)


int main(int argc, const char * const argv[]) {

  unsigned n = 50

  if (argc == 2)
    n = static_cast<unsigned>(atoi(argv[1]))

  time_it(t, n)
  time_it(p, n)

  exit(EXIT_SUCCESS)
  }


static void * null_thread(void * a) {

  pthread_exit(NULL);  

  return 0
  }


static void t(episode_timer & et, unsigned n) {

  pthread_t tid
  int s
  
  while (n > 0) {
    n--
    et.start()
    s = pthread_create(&tid, NULL, null_thread, NULL)
    if (s  0) {
      std::cerr << "pthread_create() failed, returning " << s << ".\n"
      exit(EXIT_FAILURE)
      }

    s = pthread_join(tid, NULL)
    if (s  0) {
      std::cerr << "pthread_join() failed, returning " << s << ".\n"
      exit(EXIT_FAILURE)
      }
    et.stop()
    }
  }


static void time_it(void (* p)(episode_timer &, unsigned), unsigned n) {
  
  episode_timer et

  p(et, n)

  std::cout << "n = " << et.count() 
	    << ", avg = " << et.average()
	    << ", stddev = " << et.stddev()
	    << ".\n"
  }


static void p(episode_timer & et, unsigned n) {

  pid_t pid

  while (n > 0) {
    n--
    et.start()
    switch (pid = fork()) {

      case 0: {
	char * const * strs = { 0 }
	execve("null-process", strs, strs)
	}

      case -1: {
	const int e = errno
	std::cerr << "fork() failed, returning " << e << ".\n"
	exit(EXIT_FAILURE)
	}

      default: {
	int status
	const pid_t p = waitpid(-1, &status, 0)
	if (p == -1) {
	  const int e = errno
	  std::cerr << "waitpid() failed, errno = " << e << ".\n"
	  exit(EXIT_FAILURE)
	  }
	if (p  pid) {
	  std::cerr << "waitpid() returned unexpected pid.\n"
	  exit(EXIT_FAILURE)
	  }
	}
      }
    et.stop()
    }
  }


// $Log:$


syntax highlighted by Code2HTML, v. 0.9.1