/* 
 * 
 */

#include "main.h"
#include <pthread.h>
#include <sched.h>

/*
 * Producer.
 * 
 * Birth function for thread that performs the producer behavior
 */
void* 
producer_birthFn( void* _params )
 {
   cpu_set_t cpuinfo;
   int lastTupleIter, oldConsumerReceivedACKNum;
    
   ProducerParams *params = (ProducerParams *)_params;
    
   lastTupleIter = 0; //compared to global tupleIter while waiting
   
   /* --------------------------------------------------
    * Pin thread to core, the producers are divided
    * equally over all cores. Pinning prohibits the
    * switching of cores so that perf counter and TSC values remain
    * from the same core between readings.  Pinning shouldn't 
    * affect results.. may be odd case when num thds doesn't divide into
    * num Cores
    * --------------------------------------------------
    */
 /*
   CPU_ZERO( &cpuinfo );
   CPU_SET( params->coreID, &cpuinfo );
   pthread_setaffinity_np( pthread_self(), sizeof(cpuinfo), &cpuinfo );
   pthread_yield(); //get off the core, so next can be created on it
   uint32_t cpuid = sched_getcpu();
  */
   
       
   /*Protocol:
    * wait for change in tupleIter (save updated tuple num for next time)
    * Get queue lock 
    * write into queue
    * release queue lock
    * if not done, repeat
    */
   while( lastTupleIter < params->numTuplesToCreate )
    {
      //wait for change in tupleNum (save updated tuple num for next time)
      pthread_mutex_lock(     &tupleIterLock  );
      while( lastTupleIter == tupleIter )
       {
         pthread_cond_wait( &tupleIterCond,
                            &tupleIterLock );
       }
      pthread_mutex_unlock( &tupleIterLock  );
      
      lastTupleIter = tupleIter; //save for next time through loop
      
      DEBUG__printf2("Producer: %d starting tuple: %d\n", params->producerID, tupleIter);
      
      //Q used to comm with consumer, protected with a lock  

      //Get producer lock
      pthread_mutex_lock( &queueAccessLock );
      writePrivQ( params, commQ ); //params is just a dummy pointer 
      pthread_mutex_unlock( &queueAccessLock );
    } //if not done, do again  

   //Shutdown producer
   pthread_exit(NULL);
    
 }

