///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Copyright (C) 2006 by Intel Corporation and Carnegie Mellon University    //
// Contacts: casey.j.helfrich @ intel.com                                    //
//           bdr @ cs.cmu.edu                                                //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#ifndef __SMARTYIELD_HXX
#define __SMARTYIELD_HXX

#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <iostream>
#include <vector>

using namespace std;

typedef struct _pt_yield {
  int nthreads;

  int nyielded;

  pthread_mutex_t mutex;         // this is the lock on which all threads 
                                 // sleep, tied to condvar below

  pthread_cond_t condvar[2];     // when the threads yield, they wait on this 
                                 // condition, until the master wakes them

  int currentcondvar;            // selects between the two condvars; may
                                 // need this due to race condition between 
                                 // wake and blocking for next yield by 
                                 // another thread

  pthread_cond_t all_yielded;    // this is for the last thread to wake up 
                                 // master

  pthread_cond_t resumemaster;   // this is for next_time_step to resume 
                                 // master after halt_all

  pthread_cond_t master_yielded; // this is for halt_all to wait for all 
                                 // threads *including* master thread

  int pausemaster;
} pt_yield;

void init_yield(int nthreads, pt_yield *yield);
void incr_nthreads( pt_yield *yield);
void decr_nthreads( pt_yield *yield);
void destroy_yield(pt_yield *yield);
void do_yield(pt_yield *yield);
void do_master_yield(pt_yield *yield);
void halt_all(pt_yield *yield, vector<pthread_t> &catomThreadList);
void next_time_step(pt_yield *yield, vector<pthread_t> &catomThreadList);
void signal_handler(int sig);

#endif
