<commit_before>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <globals.h>
#include <prototypes.h>
#include <pthread.h>
#include <iostream.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>           // DT: 3/97 needed for time function
#include "../rtstuff/heap/heap.h"
#include "../rtstuff/rtdefs.h"
#include "../H/dbug.h"

//#define TBUG
//#define ALLBUG

double baseTime;
long elapsed;

IBusClass checkClass(BusSlot *slot) {
  if (slot == NULL)
	return UNKNOWN;
  if ((slot->auxin_count > 0) && (slot->auxout_count > 0))
	return AUX_TO_AUX;
  if ((slot->auxout_count > 0) && (slot->out_count > 0))
	return TO_AUX_AND_OUT;
  if (slot->auxout_count > 0)
	return TO_AUX;
  if (slot->out_count > 0)
	return TO_OUT;
  return UNKNOWN;
}

extern "C" {
  void *inTraverse(void *arg)
  {
    short rtInst;
    short playEm;
    int i,j,chunksamps;
    int heapSize,rtQSize,allQSize;
    int offset,endsamp;
    int keepGoing;
    int dummy;
	short bus_q_offset;

    Instrument *Iptr;

    unsigned long bufEndSamp;
    unsigned long chunkStart;
    unsigned long heapChunkStart;

    struct timeval tv;
    struct timezone tz;
    double sec,usec;

	Bool aux_pb_done,frame_done;
	short bus,bus_count,play_bus,busq,endbus,t_bus,t_count;
	IBusClass bus_class,qStatus,t_class;
	BusType bus_type;

    // cout << "ENTERING inTraverse() FUNCTION *****\n";

    // Wait for the ok to go ahead
    if (!audio_config) {
      cout << "inTraverse():  waiting for audio_config . . . ";
    }

    while (!audio_config) {
      // Do nothing
    }

    if (audio_config && rtInteractive) {
      cout << "audio set.\n\n";
    }

    gettimeofday(&tv, &tz);
    sec = (double)tv.tv_sec;
    usec = (double)tv.tv_usec;
    baseTime = (sec * 1e6) + usec;

    // Initialize everything

    bufStartSamp = 0;  // current end sample for buffer
    bufEndSamp = RTBUFSAMPS;
    chunkStart = 0;
    heapSize = 0;
    chunkStart = 0;
    elapsed = 0;
    rtInst = 0;
    playEm = 0;

    // printf("ENTERING inTraverse() FUNCTION\n");

    // NOTE: audioin, aux and output buffers are zero'd during allocation

    // read in an input buffer (if audio input is active)
    if (audio_on) {
      rtgetsamps();
      rtsendzeros(0);  // send a buffer of zeros to audio device
    }

    if (rtsetparams_called)         // otherwise, disk-based only
      playEm = 1;

    while(playEm) { // the big loop ==========================================

      pthread_mutex_lock(&heapLock);
      heapSize = rtHeap.getSize();
      if (heapSize > 0) {
		heapChunkStart = rtHeap.getTop();
      }
      pthread_mutex_unlock(&heapLock);

      // Pop elements off rtHeap and insert into rtQueue ----------------------
      while ((heapChunkStart < bufEndSamp) && (heapSize > 0)) {
        rtInst = 1;
        pthread_mutex_lock(&heapLock);
		Iptr = rtHeap.deleteMin();  // get next instrument off heap
		pthread_mutex_unlock(&heapLock);
		if (!Iptr)
		  break;

#ifdef TBUG
		if ((Bus_Configed == NO) && (print_is_on)) {
		  printf("WARNING:  no bus_configs defined, using default\n");
		}
#endif

		// DJT Now we push things onto different queues
		bus_class = checkClass(Iptr->bus_config);
		switch (bus_class) {
		case TO_AUX:
		  bus_count = Iptr->bus_config->auxout_count;
		  bus_q_offset = 0;
		  for(i=0;i<bus_count;i++) {
			bus = Iptr->bus_config->auxout[i];
			busq = bus+bus_q_offset;
#ifdef TBUG
			cout << "Pushing on TO_AUX[" << busq << "] rtQueue\n";
#endif
			rtQueue[busq].push(Iptr,heapChunkStart);
		  }
		  break;
		case AUX_TO_AUX:
		  bus_count = Iptr->bus_config->auxout_count;
		  bus_q_offset = MAXBUS;
		  for(i=0;i<bus_count;i++) {
			bus = Iptr->bus_config->auxout[i];
			busq = bus+bus_q_offset;
#ifdef TBUG
			cout << "Pushing on AUX_TO_AUX[" << busq << "] rtQueue\n";
#endif
			rtQueue[busq].push(Iptr,heapChunkStart);
		  }
		  break;
		case TO_OUT:
		  bus_count = Iptr->bus_config->out_count;
		  bus_q_offset = MAXBUS*2;
		  for(i=0;i<bus_count;i++) {
			bus = Iptr->bus_config->out[i];
			busq = bus+bus_q_offset;
#ifdef TBUG
			cout << "Pushing on TO_OUT[" << busq << "] rtQueue\n";
#endif
			rtQueue[busq].push(Iptr,heapChunkStart);
		  }
		  break;
		case TO_AUX_AND_OUT:
		  bus_count = Iptr->bus_config->out_count;
		  bus_q_offset = MAXBUS;
		  for(i=0;i<bus_count;i++) {
			bus = Iptr->bus_config->out[i];
			busq = bus+bus_q_offset;
#ifdef TBUG
			cout << "Pushing on TO_OUT2[" << busq << "] rtQueue\n";
#endif
			rtQueue[busq].push(Iptr,heapChunkStart);
		  }
		  bus_count = Iptr->bus_config->auxout_count;
		  bus_q_offset = 2*MAXBUS;
		  for(i=0;i<bus_count;i++) {
			bus = Iptr->bus_config->auxout[i];
			busq = bus+bus_q_offset;
#ifdef TBUG
			cout << "Pushing on TO_AUX2[" << busq << "] rtQueue\n";
#endif
			rtQueue[busq].push(Iptr,heapChunkStart);
		  }
		  break;
		default:
		  cout << "ERROR (intraverse): unknown bus_class\n";
		  break;
		}

		pthread_mutex_lock(&heapLock);
		heapSize = rtHeap.getSize();
		if (heapSize > 0)
		  heapChunkStart = rtHeap.getTop();
        pthread_mutex_unlock(&heapLock);
	  }

	  qStatus = TO_AUX;
	  play_bus = 0;
	  aux_pb_done = NO;
	  allQSize = 0;

	  // rtQueue[] playback shuffling ----------------------------------------
	  while (!aux_pb_done) {

		switch (qStatus) {
		case TO_AUX:
		  bus_q_offset = 0;
		  bus_type = BUS_AUX_OUT;
		  bus = ToAuxPlayList[play_bus++];
		  break;
		case AUX_TO_AUX:
		  bus_q_offset = MAXBUS;
		  bus = AuxToAuxPlayList[play_bus++];
		  bus_type = BUS_AUX_OUT;
		  break;
		case TO_OUT:
		  bus_q_offset = MAXBUS*2;
		  bus = ToOutPlayList[play_bus++];
		  bus_type = BUS_OUT;
		  break;
		default:
		  cout << "ERROR (intraverse): unknown bus_class\n";
		  break;
		}

		if (bus != -1)
		  busq = bus+bus_q_offset;
		else
		  busq = bus;
		if (bus == -1) {
		  switch (qStatus) {
		  case TO_AUX:
			qStatus = AUX_TO_AUX;
			play_bus = 0;
			break;
		  case AUX_TO_AUX:
			qStatus = TO_OUT;
			play_bus = 0;
			break;
		  case TO_OUT:
#ifdef TBUG
			cout << "aux_pb_done\n";
#endif
			aux_pb_done = YES;
			break;
		  default:
			cout << "ERROR (intraverse): unknown bus_class\n";
			break;
		  }
		}
#ifdef TBUG
		cout << "bus: " << bus << endl;
		cout << "busq:  " << busq << endl;
#endif
		if (busq != -1) {
		  rtQSize = rtQueue[busq].getSize();
		  if (rtQSize > 0) {
			chunkStart = rtQueue[busq].nextChunk();
		  }
		}

		// Play elements on queue (insert back in if needed) - - - - - - - -
		while ((rtQSize > 0) && (chunkStart < bufEndSamp) && (bus != -1)) {

#ifdef ALLBUG
		  cout << "Begin iteration==========\n";
		  cout << "Q-chunkStart:  " << chunkStart << endl;
		  cout << "bufEndSamp:  " << bufEndSamp << endl;
		  cout << "RTBUFSAMPS:  " << RTBUFSAMPS << endl;
#endif
		  Iptr = rtQueue[busq].pop();  // get next instrument off queue

		  endsamp = Iptr->getendsamp();

		  // difference in sample start (countdown)
		  offset = chunkStart - bufStartSamp;

		  if (offset < 0) { // BGG: added this trap for robustness
			cout << "WARNING: the scheduler is behind the queue!" << endl;
			offset = 0;
		  }

		  Iptr->set_output_offset(offset);

		  if (endsamp < bufEndSamp) {  // compute # of samples to write
			chunksamps = endsamp-chunkStart;
		  }
		  else {
			chunksamps = bufEndSamp-chunkStart;
		  }

		  Iptr->setchunk(chunksamps);  // set "chunksamps"
#ifdef TBUG
		  cout << "Iptr->exec(" << bus_type << "," << bus << ")\n";
#endif
		  Iptr->exec(bus_type, bus);    // write the samples * * * * * * * * *

#ifdef TBUG
		  cout << "endbus " << endbus << endl;
#endif
		  // ReQueue or delete - - - - - - - - - - - - - - - - - - -
		  if (endsamp > bufEndSamp) {
#ifdef ALLBUG
			cout << "inTraverse():  re queueing instrument\n";
#endif
			rtQueue[busq].push(Iptr,chunkStart+chunksamps);   // put back onto queue
		  }
		  else {
			t_class = checkClass(Iptr->bus_config);
			switch (t_class) {
			case TO_AUX:
			  t_count = Iptr->bus_config->auxout_count;
			  endbus = Iptr->bus_config->auxout[t_count];
			  break;
			case AUX_TO_AUX:
			  t_count = Iptr->bus_config->auxout_count;
			  endbus = Iptr->bus_config->auxout[t_count];
			  break;
			case TO_AUX_AND_OUT:
			  if (qStatus == TO_OUT) {
				t_count = Iptr->bus_config->out_count;
				endbus = Iptr->bus_config->out[t_count];
			  }
			  else
				endbus = 1000;  /* can never equal this */
			  break;
			case TO_OUT:
			  t_count = Iptr->bus_config->out_count;
			  endbus = Iptr->bus_config->out[t_count];
			  break;
			default:
			  cout << "ERROR (intraverse): unknown bus_class\n";
			  break;
			}
			if ((qStatus == t_class) && (bus == endbus) && (endsamp >= bufEndSamp))
			  delete Iptr;
 		  }

		  // DJT:  not sure this check before new chunkStart is necessary
		  rtQSize = rtQueue[busq].getSize();
		  if (rtQSize) {
			chunkStart = rtQueue[busq].nextChunk();
			allQSize += rtQSize;
		  }
#ifdef TBUG
		  cout << "rtQSize: " << rtQSize << endl;
		  cout << "chunkStart:  " << chunkStart << endl;
		  cout << "chunksamps:  " << chunksamps << endl;
		  cout << "Iteration done==========\n";
#endif
		}
	  }

	  // Write buf to audio device -------------------------------------------
#ifdef ALLBUG
	  cout << "Writing samples----------\n";
	  cout << "Q-chunkStart:  " << chunkStart << endl;
	  cout << "bufEndSamp:  " << bufEndSamp << endl;
#endif

	  rtsendsamps();

	  // zero the buffers
	  clear_aux_buffers();
	  clear_output_buffers();

	  // read in an input buffer (if audio input is active)
	  if (audio_on) {
		// cout << "Reading data from audio port\n";
		rtgetsamps();
	  }

	  gettimeofday(&tv, &tz);
	  sec = (double)tv.tv_sec;
	  usec = (double)tv.tv_usec;
	  baseTime = (sec * 1e6) + usec;
	  elapsed += RTBUFSAMPS;
	  bufStartSamp += RTBUFSAMPS;
	  bufEndSamp += RTBUFSAMPS;

      if (!rtInteractive) {  // Ending condition
		if ((heapSize == 0) && (allQSize == 0)) {
#ifdef TBUG
		  cout << "heapSize:  " << heapSize << endl;
		  cout << "rtQSize:  " << rtQSize << endl;
		  cout << "PLAYEM = 0\n";
		  cout << "The end\n\n";
#endif
		  playEm = 0;
		}
      }
    } // end playEm =========================================================

	if (rtsetparams_called) {
	  if (play_audio) {             // Play zero'd buffers to avoid clicks
		int count = NCHANS * 4;  // DJT:  clicks on my box with 2
		for (j = 0; j < count; j++)
		  rtsendzeros(0);
      }
	  close_audio_ports();
	  rtreportstats();
	  rtcloseout();
	}

	cout << "\n";
	// cout << "EXITING inTraverse() FUNCTION *****\n";
	// exit(1);
  }

} /* extern "C" */
<commit_msg>More fixes to Iptr deletion.<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <globals.h>
#include <prototypes.h>
#include <pthread.h>
#include <iostream.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>           // DT: 3/97 needed for time function
#include "../rtstuff/heap/heap.h"
#include "../rtstuff/rtdefs.h"
#include "../H/dbug.h"

//#define TBUG
//#define ALLBUG

double baseTime;
long elapsed;

IBusClass checkClass(BusSlot *slot) {
  if (slot == NULL)
	return UNKNOWN;
  if ((slot->auxin_count > 0) && (slot->auxout_count > 0))
	return AUX_TO_AUX;
  if ((slot->auxout_count > 0) && (slot->out_count > 0))
	return TO_AUX_AND_OUT;
  if (slot->auxout_count > 0)
	return TO_AUX;
  if (slot->out_count > 0)
	return TO_OUT;
  return UNKNOWN;
}

extern "C" {
  void *inTraverse(void *arg)
  {
    short rtInst;
    short playEm;
    int i,j,chunksamps;
    int heapSize,rtQSize,allQSize;
    int offset,endsamp;
    int keepGoing;
    int dummy;
	short bus_q_offset;

    Instrument *Iptr;

    unsigned long bufEndSamp;
    unsigned long chunkStart;
    unsigned long heapChunkStart;

    struct timeval tv;
    struct timezone tz;
    double sec,usec;

	Bool aux_pb_done,frame_done;
	short bus,bus_count,play_bus,busq,endbus,t_bus,t_count;
	IBusClass bus_class,qStatus,t_class;
	BusType bus_type;

    // cout << "ENTERING inTraverse() FUNCTION *****\n";

    // Wait for the ok to go ahead
    if (!audio_config) {
      cout << "inTraverse():  waiting for audio_config . . . ";
    }

    while (!audio_config) {
      // Do nothing
    }

    if (audio_config && rtInteractive) {
      cout << "audio set.\n\n";
    }

    gettimeofday(&tv, &tz);
    sec = (double)tv.tv_sec;
    usec = (double)tv.tv_usec;
    baseTime = (sec * 1e6) + usec;

    // Initialize everything

    bufStartSamp = 0;  // current end sample for buffer
    bufEndSamp = RTBUFSAMPS;
    chunkStart = 0;
    heapSize = 0;
    chunkStart = 0;
    elapsed = 0;
    rtInst = 0;
    playEm = 0;

    // printf("ENTERING inTraverse() FUNCTION\n");

    // NOTE: audioin, aux and output buffers are zero'd during allocation

    // read in an input buffer (if audio input is active)
    if (audio_on) {
      rtgetsamps();
      rtsendzeros(0);  // send a buffer of zeros to audio device
    }

    if (rtsetparams_called)         // otherwise, disk-based only
      playEm = 1;

    while(playEm) { // the big loop ==========================================

      pthread_mutex_lock(&heapLock);
      heapSize = rtHeap.getSize();
      if (heapSize > 0) {
		heapChunkStart = rtHeap.getTop();
      }
      pthread_mutex_unlock(&heapLock);

      // Pop elements off rtHeap and insert into rtQueue ----------------------
      while ((heapChunkStart < bufEndSamp) && (heapSize > 0)) {
        rtInst = 1;
        pthread_mutex_lock(&heapLock);
		Iptr = rtHeap.deleteMin();  // get next instrument off heap
		pthread_mutex_unlock(&heapLock);
		if (!Iptr)
		  break;

#ifdef TBUG
		if ((Bus_Configed == NO) && (print_is_on)) {
		  printf("WARNING:  no bus_configs defined, using default\n");
		}
#endif

		// DJT Now we push things onto different queues
		bus_class = checkClass(Iptr->bus_config);
		switch (bus_class) {
		case TO_AUX:
		  bus_count = Iptr->bus_config->auxout_count;
		  bus_q_offset = 0;
		  for(i=0;i<bus_count;i++) {
			bus = Iptr->bus_config->auxout[i];
			busq = bus+bus_q_offset;
#ifdef TBUG
			cout << "Pushing on TO_AUX[" << busq << "] rtQueue\n";
#endif
			rtQueue[busq].push(Iptr,heapChunkStart);
		  }
		  break;
		case AUX_TO_AUX:
		  bus_count = Iptr->bus_config->auxout_count;
		  bus_q_offset = MAXBUS;
		  for(i=0;i<bus_count;i++) {
			bus = Iptr->bus_config->auxout[i];
			busq = bus+bus_q_offset;
#ifdef TBUG
			cout << "Pushing on AUX_TO_AUX[" << busq << "] rtQueue\n";
#endif
			rtQueue[busq].push(Iptr,heapChunkStart);
		  }
		  break;
		case TO_OUT:
		  bus_count = Iptr->bus_config->out_count;
		  bus_q_offset = MAXBUS*2;
		  for(i=0;i<bus_count;i++) {
			bus = Iptr->bus_config->out[i];
			busq = bus+bus_q_offset;
#ifdef TBUG
			cout << "Pushing on TO_OUT[" << busq << "] rtQueue\n";
#endif
			rtQueue[busq].push(Iptr,heapChunkStart);
		  }
		  break;
		case TO_AUX_AND_OUT:
		  bus_count = Iptr->bus_config->out_count;
		  bus_q_offset = MAXBUS;
		  for(i=0;i<bus_count;i++) {
			bus = Iptr->bus_config->out[i];
			busq = bus+bus_q_offset;
#ifdef TBUG
			cout << "Pushing on TO_OUT2[" << busq << "] rtQueue\n";
#endif
			rtQueue[busq].push(Iptr,heapChunkStart);
		  }
		  bus_count = Iptr->bus_config->auxout_count;
		  bus_q_offset = 2*MAXBUS;
		  for(i=0;i<bus_count;i++) {
			bus = Iptr->bus_config->auxout[i];
			busq = bus+bus_q_offset;
#ifdef TBUG
			cout << "Pushing on TO_AUX2[" << busq << "] rtQueue\n";
#endif
			rtQueue[busq].push(Iptr,heapChunkStart);
		  }
		  break;
		default:
		  cout << "ERROR (intraverse): unknown bus_class\n";
		  break;
		}

		pthread_mutex_lock(&heapLock);
		heapSize = rtHeap.getSize();
		if (heapSize > 0)
		  heapChunkStart = rtHeap.getTop();
        pthread_mutex_unlock(&heapLock);
	  }

	  qStatus = TO_AUX;
	  play_bus = 0;
	  aux_pb_done = NO;
	  allQSize = 0;

	  // rtQueue[] playback shuffling ----------------------------------------
	  while (!aux_pb_done) {

		switch (qStatus) {
		case TO_AUX:
		  bus_q_offset = 0;
		  bus_type = BUS_AUX_OUT;
		  bus = ToAuxPlayList[play_bus++];
		  break;
		case AUX_TO_AUX:
		  bus_q_offset = MAXBUS;
		  bus = AuxToAuxPlayList[play_bus++];
		  bus_type = BUS_AUX_OUT;
		  break;
		case TO_OUT:
		  bus_q_offset = MAXBUS*2;
		  bus = ToOutPlayList[play_bus++];
		  bus_type = BUS_OUT;
		  break;
		default:
		  cout << "ERROR (intraverse): unknown bus_class\n";
		  break;
		}

		if (bus != -1)
		  busq = bus+bus_q_offset;
		else
		  busq = bus;
		if (bus == -1) {
		  switch (qStatus) {
		  case TO_AUX:
			qStatus = AUX_TO_AUX;
			play_bus = 0;
			break;
		  case AUX_TO_AUX:
			qStatus = TO_OUT;
			play_bus = 0;
			break;
		  case TO_OUT:
#ifdef TBUG
			cout << "aux_pb_done\n";
#endif
			aux_pb_done = YES;
			break;
		  default:
			cout << "ERROR (intraverse): unknown bus_class\n";
			break;
		  }
		}
#ifdef TBUG
		cout << "bus: " << bus << endl;
		cout << "busq:  " << busq << endl;
#endif
		if (busq != -1) {
		  rtQSize = rtQueue[busq].getSize();
		  if (rtQSize > 0) {
			chunkStart = rtQueue[busq].nextChunk();
		  }
		}

		// Play elements on queue (insert back in if needed) - - - - - - - -
		while ((rtQSize > 0) && (chunkStart < bufEndSamp) && (bus != -1)) {

#ifdef ALLBUG
		  cout << "Begin iteration==========\n";
		  cout << "Q-chunkStart:  " << chunkStart << endl;
		  cout << "bufEndSamp:  " << bufEndSamp << endl;
		  cout << "RTBUFSAMPS:  " << RTBUFSAMPS << endl;
#endif
		  Iptr = rtQueue[busq].pop();  // get next instrument off queue

		  endsamp = Iptr->getendsamp();

		  // difference in sample start (countdown)
		  offset = chunkStart - bufStartSamp;

		  if (offset < 0) { // BGG: added this trap for robustness
			cout << "WARNING: the scheduler is behind the queue!" << endl;
			offset = 0;
		  }

		  Iptr->set_output_offset(offset);

		  if (endsamp < bufEndSamp) {  // compute # of samples to write
			chunksamps = endsamp-chunkStart;
		  }
		  else {
			chunksamps = bufEndSamp-chunkStart;
		  }

		  Iptr->setchunk(chunksamps);  // set "chunksamps"
#ifdef TBUG
		  cout << "Iptr->exec(" << bus_type << "," << bus << ")\n";
#endif
		  Iptr->exec(bus_type, bus);    // write the samples * * * * * * * * *

#ifdef TBUG
		  cout << "endbus " << endbus << endl;
#endif
		  // ReQueue or delete - - - - - - - - - - - - - - - - - - -
		  if (endsamp > bufEndSamp) {
#ifdef ALLBUG
			cout << "inTraverse():  re queueing instrument\n";
#endif
			rtQueue[busq].push(Iptr,chunkStart+chunksamps);   // put back onto queue
		  }
		  else {
			t_class = checkClass(Iptr->bus_config);
			switch (t_class) {
			case TO_AUX:
			  t_count = Iptr->bus_config->auxout_count;
			  endbus = Iptr->bus_config->auxout[t_count-1];
			  break;
			case AUX_TO_AUX:
			  t_count = Iptr->bus_config->auxout_count;
			  endbus = Iptr->bus_config->auxout[t_count-1];
			  break;
			case TO_AUX_AND_OUT:
			  if (qStatus == TO_OUT) {
				t_count = Iptr->bus_config->out_count;
				endbus = Iptr->bus_config->out[t_count-1];
			  }
			  else
				endbus = 1000;  /* can never equal this */
			  break;
			case TO_OUT:
			  t_count = Iptr->bus_config->out_count;
			  endbus = Iptr->bus_config->out[t_count-1];
			  break;
			default:
			  cout << "ERROR (intraverse): unknown bus_class\n";
			  break;
			}
			if ((qStatus == t_class) && (bus == endbus)) {
			  delete Iptr;
			}
 		  }

		  // DJT:  not sure this check before new chunkStart is necessary
		  rtQSize = rtQueue[busq].getSize();
		  if (rtQSize) {
			chunkStart = rtQueue[busq].nextChunk();
			allQSize += rtQSize;
		  }
#ifdef TBUG
		  cout << "rtQSize: " << rtQSize << endl;
		  cout << "chunkStart:  " << chunkStart << endl;
		  cout << "chunksamps:  " << chunksamps << endl;
		  cout << "Iteration done==========\n";
#endif
		}
	  }  // end aux_pb_done ========================================

	  // Write buf to audio device -------------------------------------------
#ifdef ALLBUG
	  cout << "Writing samples----------\n";
	  cout << "Q-chunkStart:  " << chunkStart << endl;
	  cout << "bufEndSamp:  " << bufEndSamp << endl;
#endif

	  rtsendsamps();

	  // zero the buffers
	  clear_aux_buffers();
	  clear_output_buffers();

	  // read in an input buffer (if audio input is active)
	  if (audio_on) {
		// cout << "Reading data from audio port\n";
		rtgetsamps();
	  }

	  gettimeofday(&tv, &tz);
	  sec = (double)tv.tv_sec;
	  usec = (double)tv.tv_usec;
	  baseTime = (sec * 1e6) + usec;
	  elapsed += RTBUFSAMPS;
	  bufStartSamp += RTBUFSAMPS;
	  bufEndSamp += RTBUFSAMPS;

      if (!rtInteractive) {  // Ending condition
		if ((heapSize == 0) && (allQSize == 0)) {
#ifdef TBUG
		  cout << "heapSize:  " << heapSize << endl;
		  cout << "rtQSize:  " << rtQSize << endl;
		  cout << "PLAYEM = 0\n";
		  cout << "The end\n\n";
#endif
		  playEm = 0;
		}
      }
    } // end playEm =========================================================

	if (rtsetparams_called) {
	  if (play_audio) {             // Play zero'd buffers to avoid clicks
		int count = NCHANS * 4;  // DJT:  clicks on my box with 2
		for (j = 0; j < count; j++)
		  rtsendzeros(0);
      }
	  close_audio_ports();
	  rtreportstats();
	  rtcloseout();
	}

	cout << "\n";
	// cout << "EXITING inTraverse() FUNCTION *****\n";
	// exit(1);
  }

} /* extern "C" */
<|endoftext|>


<commit_before>
#include "../JSUtil.hpp"
#include "../EmersonScript.hpp"
#include "JSTimerStruct.hpp"
#include "../JSObjects/JSFields.hpp"
#include <v8.h>
#include "../JSLogging.hpp"
#include <sirikata/core/network/IOTimer.hpp>
#include <sirikata/core/network/Asio.hpp>
#include <sirikata/core/service/Context.hpp>
#include "JSSuspendable.hpp"
#include "Util.hpp"

namespace Sirikata {
namespace JS {

JSTimerStruct::JSTimerStruct(EmersonScript* eobj, Duration dur, v8::Persistent<v8::Function>& callback,
    JSContextStruct* jscont, uint32 contID,
    double timeRemaining, bool isSuspended,bool isCleared, JSCtx* jsctx)
 :JSSuspendable(),
  emerScript(eobj),
  cb(callback),
  jsContStruct(jscont),
  mCtx(jsctx),
  mDeadlineTimer(Sirikata::Network::IOTimer::create(*jsctx->getIOService())),
  timeUntil(dur),
  mTimeRemaining(timeRemaining),
  amExecuting(false),
  killAfterFire(false),
  noTimerWaiting(true)
{
    if (isCleared)
    {
        clear();
        return;
    }

    if (isSuspended)
        suspend();

    if (contID != jscont->getContextID())
    {
        eobj->registerFixupSuspendable(this,contID);
    }
    else
    {
        noTimerWaiting=false;

        if (timeRemaining == 0)
        {
            mDeadlineTimer->wait(
                timeUntil,std::tr1::bind(
                    &JSTimerStruct::evaluateCallback,this,livenessToken()));
        }
        else
        {
            mDeadlineTimer->wait(
                Duration::microseconds(timeRemaining*1000000),
                std::tr1::bind(&JSTimerStruct::evaluateCallback,this,livenessToken()));
        }

        if (jscont != NULL)
            jscont->struct_registerSuspendable(this);
    }
}

void JSTimerStruct::setPersistentObject(v8::Persistent<v8::Object>pers)
{
    mPersistentHandle = pers;
}

void JSTimerStruct::timerWeakReferenceCleanup(
    v8::Persistent<v8::Value> containsTimer, void* otherArg)
{
    JSTimerLivenessHolder* jstlh = (JSTimerLivenessHolder*) otherArg;

    if (!jstlh->lt)
    {
        delete jstlh;
        return;
    }
    Liveness::Lock locked(jstlh->lt);
    delete jstlh;
    if (!locked)
        return;

    if (!containsTimer->IsObject())
    {
        JSLOG(error, "Error when cleaning up jstimer.  Received a timer to clean up that wasn't an object.");
        return;
    }

    v8::Handle<v8::Object> timer = containsTimer->ToObject();

    //check to make sure object has adequate number of fields.
    CHECK_INTERNAL_FIELD_COUNT(timer,jstimer,TIMER_JSTIMER_TEMPLATE_FIELD_COUNT, );

    //should return if have already cleared the timer.
    String err = "Potential error when cleaning up jstimer.  Could not decode timer struct.  Likely the timer struct was already cleared, but could be more serious.";
    JSTimerStruct* jstimer = JSTimerStruct::decodeTimerStruct(timer,err);
    if (jstimer == NULL)
    {
        JSLOG(insane,err);
        return;
    }

    //asks the particular timer to free itself if it's never going to fire
    //again, or schedule itself to be freed after will never fire again.
    jstimer->mCtx->objStrand->post(
        std::tr1::bind(&JSTimerStruct::noReference, jstimer,
            jstimer->livenessToken()),
        "JSTimerStruct::noReference"
    );
}

/**
   Called by timerWeakReferenceCleanup and after firing timer when killAfterFire
   is true.  Means that no Emerson objects hold references to this timer any
   longer and that this object should either: 1) Free itself if there's no way
   that its timer will re-fire.  2) Schedule itself to be freed after its timer
   fires.

   For case 1: the timer has already fired, and (the timer isn't suspended and
   its context isn't suspended).
   For case 2: just sets killAfterFire to be true.  Will re-evaluate these
   conditions after timer actually fires.
 */
void JSTimerStruct::noReference(const Liveness::Token& alive)
{
    v8::Locker locker (mCtx->mIsolate);
    v8::Isolate::Scope iscope(mCtx->mIsolate);
    if (alive) {
        killAfterFire = true;

        if (noTimerWaiting)
        {
            //check if it's suspended and its context is suspended
            if (!(getIsSuspended() && jsContStruct->getIsSuspended()))
            {
                //can kill
                clear();
            }
        }
    }
}

void JSTimerStruct::fixSuspendableToContext(JSContextStruct* toAttachTo)
{
    jsContStruct = toAttachTo;

    noTimerWaiting=false;
    if (mTimeRemaining == 0)
    {
        mDeadlineTimer->wait(
            timeUntil,std::tr1::bind(
                &JSTimerStruct::evaluateCallback,this,livenessToken()));
    }
    else
    {
        mDeadlineTimer->wait(
            Duration::microseconds(mTimeRemaining*1000000),
            std::tr1::bind(&JSTimerStruct::evaluateCallback,this,livenessToken()));
    }

    jsContStruct->struct_registerSuspendable(this);
}

JSTimerStruct* JSTimerStruct::decodeTimerStruct(v8::Handle<v8::Value> toDecode,String& errorMessage)
{
    v8::HandleScope handle_scope;  //for garbage collection.

    if (! toDecode->IsObject())
    {
        errorMessage += "Error in decode of timer object in JSTimerStruct.cpp.  Should have received an object to decode.";
        return NULL;
    }

    v8::Handle<v8::Object> toDecodeObject = toDecode->ToObject();

    //now check internal field count
    if (toDecodeObject->InternalFieldCount() != TIMER_JSTIMER_TEMPLATE_FIELD_COUNT)
    {
        errorMessage += "Error in decode of timer object in JSTimerStruct.  Object given does not have adequate number of internal fields for decode.";
        return NULL;
    }

    //now actually try to decode each.
    //decode the jsTimerStruct field
    v8::Local<v8::External> wrapJSTimerStruct;
    wrapJSTimerStruct = v8::Local<v8::External>::Cast(toDecodeObject->GetInternalField(TIMER_JSTIMERSTRUCT_FIELD));
    void* ptr = wrapJSTimerStruct->Value();

    JSTimerStruct* returner;
    returner = static_cast<JSTimerStruct*>(ptr);
    if (returner == NULL)
        errorMessage += "Error in decode of timer object in JSTimerStruct.cpp.  Internal field of object given cannot be casted to a JSTimerStruct.";

    return returner;
}

JSTimerStruct::~JSTimerStruct()
{
    letDie();
    clear();
}

//returning all data necessary to re-generate timer
//  uint32   contextId
//  double period
//  double timeUntil timer expires
//  bool  isSuspended
//  bool  isCleared
//  func  cb
v8::Handle<v8::Value> JSTimerStruct::struct_getAllData()
{
    v8::HandleScope handle_scope;

    uint32  contId   = jsContStruct->getContextID();
    bool    issusp   = getIsSuspended();
    bool    isclear  = getIsCleared();
    double  period   = -1;
    double  tUntil   = -1;

    v8::Handle<v8::Function> cbFunc;

    if (! isclear)
    {
        cbFunc = cb;
        period = timeUntil.toSeconds();
        if (issusp)
            tUntil = timeUntil.toSeconds();
        else
        {
            Duration pt = mDeadlineTimer->expiresFromNow();
            tUntil = pt.seconds();
        }
    }

    v8::Handle<v8::Object> returner = v8::Object::New();

    if (isclear)
    {
        returner->Set(v8::String::New("isCleared"),v8::Boolean::New(isclear));
        returner->Set(v8::String::New("contextId"), v8::Integer::NewFromUnsigned(contId));
        return handle_scope.Close(returner);
    }

    returner->Set(v8::String::New("period"), v8::Number::New(period));
    returner->Set(v8::String::New("callback"),cbFunc);
    returner->Set(v8::String::New("timeRemaining"),v8::Number::New(tUntil));
    returner->Set(v8::String::New("isSuspended"),v8::Boolean::New(issusp));

    return handle_scope.Close(returner);
}

void JSTimerStruct::evaluateCallback(Liveness::Token isAlive)
{
    if (!isAlive) return;
    Liveness::Lock locked(isAlive);
    if (!locked) return;

    if (mCtx->stopped())
        return;

    mCtx->objStrand->post(
        std::tr1::bind(&JSTimerStruct::iEvaluateCallback,this,
            isAlive),
        "JSTimerStruct::iEvaluateCallback"
    );
}

void JSTimerStruct::iEvaluateCallback(Liveness::Token token)
{
    //lkjs; FIXME: Can weak reference clean up a timer
    //while it's in this function?  (If we try to use lock, we run
    //into a problem when the timer tries to clear itself.)
    if (!token)
        return;

    if (mCtx->stopped()) {
        JSLOG(warn, "Timer evaluateCallback invoked after stop request, ignoring...");
        noTimerWaiting=true; // Allow cleanup, see notes below
        return;
    }

    while(!mCtx->initialized())
    {}
    amExecuting = true;
    emerScript->invokeCallbackInContext(emerScript->livenessToken(), cb, jsContStruct);

    //if we were told to kill the timer after firing, then check kill conditions
    //again in noReference.
    if (killAfterFire)
    {
        mCtx->objStrand->post(
            std::tr1::bind(&JSTimerStruct::noReference,this,
                livenessToken()),
            "JSTimerStruct::noReference"
        );
    }

    //means that we have no pending timer operation.
    // Note that since this allows the JS GC thread to destroy this object
    // in response to all references to it being lost,
    // we need to make sure it is absolutely the *last* operation we do on
    // member variables.
    noTimerWaiting=true;
    amExecuting = false;
}

v8::Handle<v8::Value> JSTimerStruct::suspend()
{
    if (getIsCleared())
    {
        JSLOG(info, "Error in suspend of JSTimerStruct.cpp.  Called suspend even though the timer had previously been cleared.");
        return v8::ThrowException( v8::Exception::Error(v8::String::New("Error.  Called suspend on a timer that had already been cleared.")));
    }

    JSLOG(insane,"suspending timer");

    //note, it is important that call to JSSuspendable::supsend occurs before
    //actually cancelling the deadline timer so that we're performing correct
    //checks for timer cleanup.
    v8::HandleScope handle_scope;
    v8::Handle<v8::Value>returner = JSSuspendable::suspend();
    mDeadlineTimer->cancel();
    // Note that since this allows the JS GC thread to destroy this object
    // in response to all references to it being lost,
    // we need to make sure it is absolutely the *last* operation we do on
    // member variables.
    noTimerWaiting = true;
    return handle_scope.Close(returner);
}

//has more of a reset-type functionality than resume
//if the time has not been cleared, then, cancel the current timer,
//and start a new countdown to execute the callback.
v8::Handle<v8::Value> JSTimerStruct::resume()
{
    if (getIsCleared())
    {
        JSLOG(info,"Error in JSTimerStruct.  Trying to resume a timer object that has already been cleared.  Taking no action");
        return JSSuspendable::getIsSuspendedV8();
    }
    mDeadlineTimer->cancel();

    noTimerWaiting=false;
    mDeadlineTimer->wait(
        timeUntil,std::tr1::bind(
            &JSTimerStruct::evaluateCallback,this,livenessToken()));

    return JSSuspendable::resume();
}

v8::Handle<v8::Value> JSTimerStruct::clear()
{
    if (getIsCleared())
    {
        JSLOG(insane,"In JSTimerStruct, calling clear on a timer that has already been cleared.");
        return JSSuspendable::clear();
    }

    v8::HandleScope handle_scope;

    JSSuspendable::clear();

    mDeadlineTimer->cancel();

    if (! cb.IsEmpty())
        cb.Dispose();

    if (! mPersistentHandle.IsEmpty())
    {
        //check to make sure object has adequate number of fields.
        CHECK_INTERNAL_FIELD_COUNT(mPersistentHandle,jstimer,TIMER_JSTIMER_TEMPLATE_FIELD_COUNT, v8::Boolean::New(true));

        //delete typeId, and return if have incorrect params for type id
        DEL_TYPEID_AND_CHECK(mPersistentHandle,jstimer,TIMER_TYPEID_STRING,v8::Boolean::New(true));

        mPersistentHandle->SetInternalField(TIMER_JSTIMERSTRUCT_FIELD, External::New(NULL));
    }

    // Be careful after this! JSContextStruct::struct_deregisterSuspendable will
    // delete this object so you shouldn't use any member variables after
    // invoking it.
    if (jsContStruct != NULL)
    {
        //cannot clear if amExecuting.
        if (amExecuting)
        {
            mCtx->objStrand->post(
                std::tr1::bind(&JSContextStruct::struct_asyncDeregisterSuspendable,jsContStruct,this,
                    jsContStruct->livenessToken(),livenessToken()),
                "JSContextStruct::struct_asyncDeregisterSuspendable"
            );
        }
        else
            jsContStruct->struct_deregisterSuspendable(this);
    }

    // Note that since this allows the JS GC thread to destroy this object
    // in response to all references to it being lost,
    // we need to make sure it is absolutely the *last* operation we do on
    // member variables.
    // In this case, the above call will have deleted this JSTimerStruct, so we
    // don't even set it at all. It would have been unsafe to set it earlier
    // because we could have ended up with two threads trying to do the deletion.
    //noTimerWaiting = true;

    return v8::Boolean::New(true);
}

v8::Handle<v8::Value> JSTimerStruct::struct_resetTimer(double timeInSecondsToRefire)
{
    if (getIsCleared())
    {
        JSLOG(info,"Error in JSTimerStruct.  Calling reset on a timer that has already been cleared.");
        return JSSuspendable::clear();
    }

    mDeadlineTimer->cancel();
    noTimerWaiting=false;
    mDeadlineTimer->wait(
        Duration::seconds(timeInSecondsToRefire),
        std::tr1::bind(&JSTimerStruct::evaluateCallback,this, livenessToken()));

    return JSSuspendable::resume();
}

} //end namespace js
} //end namespace sirikata
<commit_msg>Fix liveness check in JSTimerStruct.<commit_after>
#include "../JSUtil.hpp"
#include "../EmersonScript.hpp"
#include "JSTimerStruct.hpp"
#include "../JSObjects/JSFields.hpp"
#include <v8.h>
#include "../JSLogging.hpp"
#include <sirikata/core/network/IOTimer.hpp>
#include <sirikata/core/network/Asio.hpp>
#include <sirikata/core/service/Context.hpp>
#include "JSSuspendable.hpp"
#include "Util.hpp"

namespace Sirikata {
namespace JS {

JSTimerStruct::JSTimerStruct(EmersonScript* eobj, Duration dur, v8::Persistent<v8::Function>& callback,
    JSContextStruct* jscont, uint32 contID,
    double timeRemaining, bool isSuspended,bool isCleared, JSCtx* jsctx)
 :JSSuspendable(),
  emerScript(eobj),
  cb(callback),
  jsContStruct(jscont),
  mCtx(jsctx),
  mDeadlineTimer(Sirikata::Network::IOTimer::create(*jsctx->getIOService())),
  timeUntil(dur),
  mTimeRemaining(timeRemaining),
  amExecuting(false),
  killAfterFire(false),
  noTimerWaiting(true)
{
    if (isCleared)
    {
        clear();
        return;
    }

    if (isSuspended)
        suspend();

    if (contID != jscont->getContextID())
    {
        eobj->registerFixupSuspendable(this,contID);
    }
    else
    {
        noTimerWaiting=false;

        if (timeRemaining == 0)
        {
            mDeadlineTimer->wait(
                timeUntil,std::tr1::bind(
                    &JSTimerStruct::evaluateCallback,this,livenessToken()));
        }
        else
        {
            mDeadlineTimer->wait(
                Duration::microseconds(timeRemaining*1000000),
                std::tr1::bind(&JSTimerStruct::evaluateCallback,this,livenessToken()));
        }

        if (jscont != NULL)
            jscont->struct_registerSuspendable(this);
    }
}

void JSTimerStruct::setPersistentObject(v8::Persistent<v8::Object>pers)
{
    mPersistentHandle = pers;
}

void JSTimerStruct::timerWeakReferenceCleanup(
    v8::Persistent<v8::Value> containsTimer, void* otherArg)
{
    JSTimerLivenessHolder* jstlh = (JSTimerLivenessHolder*) otherArg;

    if (!jstlh->lt)
    {
        delete jstlh;
        return;
    }
    Liveness::Lock locked(jstlh->lt);
    delete jstlh;
    if (!locked)
        return;

    if (!containsTimer->IsObject())
    {
        JSLOG(error, "Error when cleaning up jstimer.  Received a timer to clean up that wasn't an object.");
        return;
    }

    v8::Handle<v8::Object> timer = containsTimer->ToObject();

    //check to make sure object has adequate number of fields.
    CHECK_INTERNAL_FIELD_COUNT(timer,jstimer,TIMER_JSTIMER_TEMPLATE_FIELD_COUNT, );

    //should return if have already cleared the timer.
    String err = "Potential error when cleaning up jstimer.  Could not decode timer struct.  Likely the timer struct was already cleared, but could be more serious.";
    JSTimerStruct* jstimer = JSTimerStruct::decodeTimerStruct(timer,err);
    if (jstimer == NULL)
    {
        JSLOG(insane,err);
        return;
    }

    //asks the particular timer to free itself if it's never going to fire
    //again, or schedule itself to be freed after will never fire again.
    jstimer->mCtx->objStrand->post(
        std::tr1::bind(&JSTimerStruct::noReference, jstimer,
            jstimer->livenessToken()),
        "JSTimerStruct::noReference"
    );
}

/**
   Called by timerWeakReferenceCleanup and after firing timer when killAfterFire
   is true.  Means that no Emerson objects hold references to this timer any
   longer and that this object should either: 1) Free itself if there's no way
   that its timer will re-fire.  2) Schedule itself to be freed after its timer
   fires.

   For case 1: the timer has already fired, and (the timer isn't suspended and
   its context isn't suspended).
   For case 2: just sets killAfterFire to be true.  Will re-evaluate these
   conditions after timer actually fires.
 */
void JSTimerStruct::noReference(const Liveness::Token& alive)
{
    if (!alive) return;
    Liveness::Lock locked(alive);
    if (!locked) return;

    v8::Locker locker (mCtx->mIsolate);
    v8::Isolate::Scope iscope(mCtx->mIsolate);

    killAfterFire = true;

    if (noTimerWaiting)
    {
        //check if it's suspended and its context is suspended
        if (!(getIsSuspended() && jsContStruct->getIsSuspended()))
        {
            //can kill
            clear();
        }
    }
}

void JSTimerStruct::fixSuspendableToContext(JSContextStruct* toAttachTo)
{
    jsContStruct = toAttachTo;

    noTimerWaiting=false;
    if (mTimeRemaining == 0)
    {
        mDeadlineTimer->wait(
            timeUntil,std::tr1::bind(
                &JSTimerStruct::evaluateCallback,this,livenessToken()));
    }
    else
    {
        mDeadlineTimer->wait(
            Duration::microseconds(mTimeRemaining*1000000),
            std::tr1::bind(&JSTimerStruct::evaluateCallback,this,livenessToken()));
    }

    jsContStruct->struct_registerSuspendable(this);
}

JSTimerStruct* JSTimerStruct::decodeTimerStruct(v8::Handle<v8::Value> toDecode,String& errorMessage)
{
    v8::HandleScope handle_scope;  //for garbage collection.

    if (! toDecode->IsObject())
    {
        errorMessage += "Error in decode of timer object in JSTimerStruct.cpp.  Should have received an object to decode.";
        return NULL;
    }

    v8::Handle<v8::Object> toDecodeObject = toDecode->ToObject();

    //now check internal field count
    if (toDecodeObject->InternalFieldCount() != TIMER_JSTIMER_TEMPLATE_FIELD_COUNT)
    {
        errorMessage += "Error in decode of timer object in JSTimerStruct.  Object given does not have adequate number of internal fields for decode.";
        return NULL;
    }

    //now actually try to decode each.
    //decode the jsTimerStruct field
    v8::Local<v8::External> wrapJSTimerStruct;
    wrapJSTimerStruct = v8::Local<v8::External>::Cast(toDecodeObject->GetInternalField(TIMER_JSTIMERSTRUCT_FIELD));
    void* ptr = wrapJSTimerStruct->Value();

    JSTimerStruct* returner;
    returner = static_cast<JSTimerStruct*>(ptr);
    if (returner == NULL)
        errorMessage += "Error in decode of timer object in JSTimerStruct.cpp.  Internal field of object given cannot be casted to a JSTimerStruct.";

    return returner;
}

JSTimerStruct::~JSTimerStruct()
{
    letDie();
    clear();
}

//returning all data necessary to re-generate timer
//  uint32   contextId
//  double period
//  double timeUntil timer expires
//  bool  isSuspended
//  bool  isCleared
//  func  cb
v8::Handle<v8::Value> JSTimerStruct::struct_getAllData()
{
    v8::HandleScope handle_scope;

    uint32  contId   = jsContStruct->getContextID();
    bool    issusp   = getIsSuspended();
    bool    isclear  = getIsCleared();
    double  period   = -1;
    double  tUntil   = -1;

    v8::Handle<v8::Function> cbFunc;

    if (! isclear)
    {
        cbFunc = cb;
        period = timeUntil.toSeconds();
        if (issusp)
            tUntil = timeUntil.toSeconds();
        else
        {
            Duration pt = mDeadlineTimer->expiresFromNow();
            tUntil = pt.seconds();
        }
    }

    v8::Handle<v8::Object> returner = v8::Object::New();

    if (isclear)
    {
        returner->Set(v8::String::New("isCleared"),v8::Boolean::New(isclear));
        returner->Set(v8::String::New("contextId"), v8::Integer::NewFromUnsigned(contId));
        return handle_scope.Close(returner);
    }

    returner->Set(v8::String::New("period"), v8::Number::New(period));
    returner->Set(v8::String::New("callback"),cbFunc);
    returner->Set(v8::String::New("timeRemaining"),v8::Number::New(tUntil));
    returner->Set(v8::String::New("isSuspended"),v8::Boolean::New(issusp));

    return handle_scope.Close(returner);
}

void JSTimerStruct::evaluateCallback(Liveness::Token isAlive)
{
    if (!isAlive) return;
    Liveness::Lock locked(isAlive);
    if (!locked) return;

    if (mCtx->stopped())
        return;

    mCtx->objStrand->post(
        std::tr1::bind(&JSTimerStruct::iEvaluateCallback,this,
            isAlive),
        "JSTimerStruct::iEvaluateCallback"
    );
}

void JSTimerStruct::iEvaluateCallback(Liveness::Token token)
{
    //lkjs; FIXME: Can weak reference clean up a timer
    //while it's in this function?  (If we try to use lock, we run
    //into a problem when the timer tries to clear itself.)
    if (!token)
        return;

    if (mCtx->stopped()) {
        JSLOG(warn, "Timer evaluateCallback invoked after stop request, ignoring...");
        noTimerWaiting=true; // Allow cleanup, see notes below
        return;
    }

    while(!mCtx->initialized())
    {}
    amExecuting = true;
    emerScript->invokeCallbackInContext(emerScript->livenessToken(), cb, jsContStruct);

    //if we were told to kill the timer after firing, then check kill conditions
    //again in noReference.
    if (killAfterFire)
    {
        mCtx->objStrand->post(
            std::tr1::bind(&JSTimerStruct::noReference,this,
                livenessToken()),
            "JSTimerStruct::noReference"
        );
    }

    //means that we have no pending timer operation.
    // Note that since this allows the JS GC thread to destroy this object
    // in response to all references to it being lost,
    // we need to make sure it is absolutely the *last* operation we do on
    // member variables.
    noTimerWaiting=true;
    amExecuting = false;
}

v8::Handle<v8::Value> JSTimerStruct::suspend()
{
    if (getIsCleared())
    {
        JSLOG(info, "Error in suspend of JSTimerStruct.cpp.  Called suspend even though the timer had previously been cleared.");
        return v8::ThrowException( v8::Exception::Error(v8::String::New("Error.  Called suspend on a timer that had already been cleared.")));
    }

    JSLOG(insane,"suspending timer");

    //note, it is important that call to JSSuspendable::supsend occurs before
    //actually cancelling the deadline timer so that we're performing correct
    //checks for timer cleanup.
    v8::HandleScope handle_scope;
    v8::Handle<v8::Value>returner = JSSuspendable::suspend();
    mDeadlineTimer->cancel();
    // Note that since this allows the JS GC thread to destroy this object
    // in response to all references to it being lost,
    // we need to make sure it is absolutely the *last* operation we do on
    // member variables.
    noTimerWaiting = true;
    return handle_scope.Close(returner);
}

//has more of a reset-type functionality than resume
//if the time has not been cleared, then, cancel the current timer,
//and start a new countdown to execute the callback.
v8::Handle<v8::Value> JSTimerStruct::resume()
{
    if (getIsCleared())
    {
        JSLOG(info,"Error in JSTimerStruct.  Trying to resume a timer object that has already been cleared.  Taking no action");
        return JSSuspendable::getIsSuspendedV8();
    }
    mDeadlineTimer->cancel();

    noTimerWaiting=false;
    mDeadlineTimer->wait(
        timeUntil,std::tr1::bind(
            &JSTimerStruct::evaluateCallback,this,livenessToken()));

    return JSSuspendable::resume();
}

v8::Handle<v8::Value> JSTimerStruct::clear()
{
    if (getIsCleared())
    {
        JSLOG(insane,"In JSTimerStruct, calling clear on a timer that has already been cleared.");
        return JSSuspendable::clear();
    }

    v8::HandleScope handle_scope;

    JSSuspendable::clear();

    mDeadlineTimer->cancel();

    if (! cb.IsEmpty())
        cb.Dispose();

    if (! mPersistentHandle.IsEmpty())
    {
        //check to make sure object has adequate number of fields.
        CHECK_INTERNAL_FIELD_COUNT(mPersistentHandle,jstimer,TIMER_JSTIMER_TEMPLATE_FIELD_COUNT, v8::Boolean::New(true));

        //delete typeId, and return if have incorrect params for type id
        DEL_TYPEID_AND_CHECK(mPersistentHandle,jstimer,TIMER_TYPEID_STRING,v8::Boolean::New(true));

        mPersistentHandle->SetInternalField(TIMER_JSTIMERSTRUCT_FIELD, External::New(NULL));
    }

    // Be careful after this! JSContextStruct::struct_deregisterSuspendable will
    // delete this object so you shouldn't use any member variables after
    // invoking it.
    if (jsContStruct != NULL)
    {
        //cannot clear if amExecuting.
        if (amExecuting)
        {
            mCtx->objStrand->post(
                std::tr1::bind(&JSContextStruct::struct_asyncDeregisterSuspendable,jsContStruct,this,
                    jsContStruct->livenessToken(),livenessToken()),
                "JSContextStruct::struct_asyncDeregisterSuspendable"
            );
        }
        else
            jsContStruct->struct_deregisterSuspendable(this);
    }

    // Note that since this allows the JS GC thread to destroy this object
    // in response to all references to it being lost,
    // we need to make sure it is absolutely the *last* operation we do on
    // member variables.
    // In this case, the above call will have deleted this JSTimerStruct, so we
    // don't even set it at all. It would have been unsafe to set it earlier
    // because we could have ended up with two threads trying to do the deletion.
    //noTimerWaiting = true;

    return v8::Boolean::New(true);
}

v8::Handle<v8::Value> JSTimerStruct::struct_resetTimer(double timeInSecondsToRefire)
{
    if (getIsCleared())
    {
        JSLOG(info,"Error in JSTimerStruct.  Calling reset on a timer that has already been cleared.");
        return JSSuspendable::clear();
    }

    mDeadlineTimer->cancel();
    noTimerWaiting=false;
    mDeadlineTimer->wait(
        Duration::seconds(timeInSecondsToRefire),
        std::tr1::bind(&JSTimerStruct::evaluateCallback,this, livenessToken()));

    return JSSuspendable::resume();
}

} //end namespace js
} //end namespace sirikata
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdint.h>
#include <stdio.h>

#include <unistd.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <getopt.h>

#include <string>
#include <iostream>

#include <oriutil/debug.h>
#include <oriutil/orifile.h>
#include <ori/repostore.h>

using namespace std;

void
usage_list()
{
    cout << "ori list" << endl;
    cout << endl;
    cout << "List all local file systems." << endl;
}

/*
 * List local file systems.
 */
int
cmd_list(int argc, char * const argv[])
{
    set<string> repos = RepoStore_GetRepos();
    set<string>::iterator it;

    for (it = repos.begin(); it != repos.end(); it++)
    {
        cout << *it << endl;
    }

    return 0;
}

<commit_msg>Show FSID on list operation.<commit_after>/*
 * Copyright (c) 2013 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdint.h>
#include <stdio.h>

#include <unistd.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <getopt.h>

#include <string>
#include <iostream>
#include <iomanip>

#include <oriutil/debug.h>
#include <oriutil/orifile.h>
#include <ori/repostore.h>
#include <ori/localrepo.h>

using namespace std;

void
usage_list()
{
    cout << "ori list" << endl;
    cout << endl;
    cout << "List all local file systems." << endl;
}

/*
 * List local file systems.
 */
int
cmd_list(int argc, char * const argv[])
{
    set<string> repos = RepoStore_GetRepos();
    set<string>::iterator it;

    cout << left << setw(32) << "Name" << "File System ID" << endl;
    for (it = repos.begin(); it != repos.end(); it++)
    {
        string path, id;

        path = RepoStore_GetRepoPath(*it) + ORI_PATH_UUID;
        id = OriFile_ReadFile(path);

        cout << left << setw(32) << *it << id << endl;
    }

    return 0;
}

<|endoftext|>


<commit_before>/**
 * \file	  Encryption.cc
 * \author    Rik Honcoop
 * \copyright Copyright (c) 2017, The R2D2 Team
 * \license   See LICENSE
 */
#include "Encryption.hh"

Encryption::Encryption(){
encryptKey = 1;
}

Encryption::Encryption(int encryptionKey){
encryptKey = encryptionKey;
}

string Encryption::Decrypt(string input, int keyCode){
    string restr = input;

    for(unsigned int i =0; i <= input.length() -1; i ++){
        restr[i] = restr[i]-keyCode ;

    }
    return restr;
}

string Encryption::Decrypt(string input){
    string restr = input;

    for(unsigned int i =0; i <= input.length() -1; i ++){
        restr[i] = restr[i]-encryptKey ;

    }
    return restr;
}

string Encryption::Encrypt(string input, int keyCode){
    string restr = input;

    for(unsigned int i =0; i <= input.length() -1; i ++){
        restr[i] = restr[i]+keyCode ;

    }
    return restr;
}

string Encryption::Encrypt(string input){
    string restr = input;

    for(unsigned int i =0; i <= input.length() -1; i ++){
        restr[i] = restr[i]+encryptKey ;

    }
    return restr;
}

void Encryption::setEncryptionKey(int encryptionKey){
	encryptKey = encryptionKey;
}
<commit_msg>[RFID-01] Merge branch 'feat-rfid' of https://github.com/R2D2-2017/R2D2-2017 into feat-rfid<commit_after>/**
 * \file	  Encryption.cc
 * \author    Rik Honcoop
 * \copyright Copyright (c) 2017, The R2D2 Team
 * \license   See LICENSE
 */
#include "encryption.hh"

Encryption::Encryption(){
encryptKey = 1;
}

Encryption::Encryption(int encryptionKey){
encryptKey = encryptionKey;
}

string Encryption::Decrypt(string input, int keyCode){
    string restr = input;

    for(unsigned int i =0; i <= input.length() -1; i ++){
        restr[i] = restr[i]-keyCode ;

    }
    return restr;
}

string Encryption::Decrypt(string input){
    string restr = input;

    for(unsigned int i =0; i <= input.length() -1; i ++){
        restr[i] = restr[i]-encryptKey ;

    }
    return restr;
}

string Encryption::Encrypt(string input, int keyCode){
    string restr = input;

    for(unsigned int i =0; i <= input.length() -1; i ++){
        restr[i] = restr[i]+keyCode ;

    }
    return restr;
}

string Encryption::Encrypt(string input){
    string restr = input;

    for(unsigned int i =0; i <= input.length() -1; i ++){
        restr[i] = restr[i]+encryptKey ;

    }
    return restr;
}

void Encryption::setEncryptionKey(int encryptionKey){
	encryptKey = encryptionKey;
}
<|endoftext|>


<commit_before>#include <ctime>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include "camera.hpp"
#include <vector>

//static const int WIDTH = 640;
//static const int HEIGHT = 480;
static const int FPS = 6;
static const int DEVICE = 0;
static const std::string DIRECTORY_PATH = "/home/pi/Pictures/";//pathの先頭
static const std::string FILE_EXTENTION = ".jpg";//拡張子

static const int AOV = 62.2;//ANGLE OF VIEW
//明度について
static const int MAX_VALUE = 255;//明るさ最大
static const int NO_VALUE = 0;//明るさ最小
static const double MIN_AREA = 10;//抽出する面積の最小値

Camera::Camera()
{
	if(!capture.open(DEVICE))
	{
		std::cout<<"capture is not opened 1"<<std::endl;
	}
	if (!capture.isOpened())
	{
		std::cout<<"capture is not opened 2"<<std::endl;
	}
	//capture.set(CV_CAP_PROP_FRAME_WIDTH,WIDTH);
	//capture.set(CV_CAP_PROP_FRAME_HEIGHT,HEIGHT);
	capture.set(CV_CAP_PROP_FPS,FPS);
	//以下 対応してない
	//capture.set(CV_CAP_PROP_BUFFERSIZE, 1);
}

Camera::~Camera()
{
	capture.release();
}

int Camera::takePhoto()
{
	makeTimePath();
	cv::Mat frame;
	for (int i = 0; i < 5; i++)
	{
			capture.grab();
	}
	do
	{
		capture>>frame;
	} while(frame.empty());
	input = frame;
	imwrite(timePath+FILE_EXTENTION,input);
	return 0;
}

//時間を元にtimePathを作る
int Camera::makeTimePath(void)
{
	time_t timer;//時刻を受け取る変数
	struct tm *timeptr;//日時を集めた構造体ポインタ
	char buffer[80];
	time(&timer);//現在時刻の取得
	timeptr = localtime(&timer);//ポインタ
	strftime(buffer, sizeof(buffer), "%Y%m%d-%H%M%S", timeptr);//日時を文字列に変換してｓに代入
	std::string str(buffer);
	timePath = DIRECTORY_PATH+str;
  return 0;
}

//ノイズ除去,引数aは抽出する輪郭の面積の最小値
cv::Mat Camera::rmNoise(cv::Mat src)
{
	std::vector<std::vector<cv::Point> > contours;//輪郭座標の二次元配列
	cv::findContours(src,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);//CV_RETR_EXTERNAL:最も外側の輪郭を検出、CV_CHAIN_APPROX_NONE:近似手法
	std::vector<std::vector<cv::Point> > contours_subset;
	for (int i = 0;i<contours.size();i++)
	{
		double area = cv::contourArea(contours.at(i));//各輪郭の面積
		if (area>MIN_AREA)
		{
			contours_subset.push_back(contours.at(i));//contours_subsetに一定面積以上の輪郭を追加
		}
	}
	cv::Mat mask = cv::Mat::zeros(src.rows, src.cols, CV_8UC1);
	cv::drawContours(mask, contours_subset, -1, cv::Scalar(255), -1);//maskに一定面積以上の輪郭をdraw
	return mask;
}

int Camera::binarize()
{
	cv::Mat hsv;
	cv::Mat hsv_filtered15;//画像の初期化
	cv::Mat hsv_filtered180;//画像の初期化
	cv::cvtColor(input,hsv,CV_BGR2HSV);//入力画像(src)をhsv色空間(dst)に変換
	//inRange(入力画像,下界画像,上界画像,出力画像)
	//「HSV」は、色を色相(Hue)・彩度(Saturation)・明度(Value)
	cv::inRange(hsv,cv::Scalar(0,100,160),cv::Scalar(3,255,MAX_VALUE),hsv_filtered15);
	cv::inRange(hsv,cv::Scalar(175,100,160),cv::Scalar(180,255,MAX_VALUE),hsv_filtered180);
	cv::add(hsv_filtered15,hsv_filtered180,hsv);
	output = rmNoise(hsv);
	imwrite(timePath+"BINARY"+FILE_EXTENTION,output);
	return 0;
}

//二値化した画像から1の面積を抽出
double Camera::countArea()
{

	double Area = output.rows*output.cols;//全ピクセル数
	double redCount = 0; //赤色を認識したピクセルの数
	redCount = cv::countNonZero(output);//赤色部分の面積を計算
	double percentage = 0; //割合
	percentage = (redCount / Area)*100;//割合を計算
	std::cout<<"面積のPercentageは"<<percentage<<std::endl;
	return percentage;
}

//二値化画像のcenterを角度で返す
double Camera::getCenter()
{
	cv::Moments mu = cv::moments(output, false);//重心の計算結果をmuに代入
	double mc = mu.m10 / mu.m00;//重心のx座標
	double center = (mc - output.cols / 2) * AOV / output.cols;//正規化
	std::cout<<"重心の位置は"<<center<<std::endl;
	return center;
}
<commit_msg>debug<commit_after>#include <ctime>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include "camera.hpp"
#include <vector>

//static const int WIDTH = 640;
//static const int HEIGHT = 480;
static const int FPS = 6;
static const int DEVICE = 0;
static const std::string DIRECTORY_PATH = "/home/pi/Pictures/";//pathの先頭
static const std::string FILE_EXTENTION = ".jpg";//拡張子

static const int AOV = 62.2;//ANGLE OF VIEW
//明度について
static const int MAX_VALUE = 255;//明るさ最大
static const int NO_VALUE = 0;//明るさ最小
static const double MIN_AREA = 10;//抽出する面積の最小値

Camera::Camera()
{
	if(!capture.open(DEVICE))
	{
		std::cout<<"capture is not opened 1"<<std::endl;
	}
	if (!capture.isOpened())
	{
		std::cout<<"capture is not opened 2"<<std::endl;
	}
	//capture.set(CV_CAP_PROP_FRAME_WIDTH,WIDTH);
	//capture.set(CV_CAP_PROP_FRAME_HEIGHT,HEIGHT);
	capture.set(CV_CAP_PROP_FPS,FPS);
	//以下 対応してない
	//capture.set(CV_CAP_PROP_BUFFERSIZE, 1);
}

Camera::~Camera()
{
	capture.release();
}

int Camera::takePhoto()
{
	makeTimePath();
	cv::Mat frame;
	for (int i = 0; i < 5; i++)
	{
			capture.grab();
	}
	do
	{
		capture>>frame;
	} while(frame.empty());
	input = frame;
	imwrite(timePath+FILE_EXTENTION,input);
	return 0;
}

//時間を元にtimePathを作る
int Camera::makeTimePath(void)
{
	time_t timer;//時刻を受け取る変数
	struct tm *timeptr;//日時を集めた構造体ポインタ
	char buffer[80];
	time(&timer);//現在時刻の取得
	timeptr = localtime(&timer);//ポインタ
	strftime(buffer, sizeof(buffer), "%Y%m%d-%H%M%S", timeptr);//日時を文字列に変換してｓに代入
	std::string str(buffer);
	timePath = DIRECTORY_PATH+str;
  return 0;
}

//ノイズ除去,引数aは抽出する輪郭の面積の最小値
cv::Mat Camera::rmNoise(cv::Mat src)
{
	std::vector<std::vector<cv::Point> > contours;//輪郭座標の二次元配列
	cv::findContours(src,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);//CV_RETR_EXTERNAL:最も外側の輪郭を検出、CV_CHAIN_APPROX_NONE:近似手法
	std::vector<std::vector<cv::Point> > contours_subset;
	for (int i = 0;i<contours.size();i++)
	{
		double area = cv::contourArea(contours.at(i));//各輪郭の面積
		if (area>MIN_AREA)
		{
			contours_subset.push_back(contours.at(i));//contours_subsetに一定面積以上の輪郭を追加
		}
	}
	cv::Mat mask = cv::Mat::zeros(src.rows, src.cols, CV_8UC1);
	cv::drawContours(mask, contours_subset, -1, cv::Scalar(255), -1);//maskに一定面積以上の輪郭をdraw
	return mask;
}

int Camera::binarize()
{
	cv::Mat hsv;
	cv::Mat hsv_filtered15;//画像の初期化
	cv::Mat hsv_filtered180;//画像の初期化
	cv::cvtColor(input,hsv,CV_BGR2HSV);//入力画像(src)をhsv色空間(dst)に変換
	//inRange(入力画像,下界画像,上界画像,出力画像)
	//「HSV」は、色を色相(Hue)・彩度(Saturation)・明度(Value)
	cv::inRange(hsv,cv::Scalar(0,160,60),cv::Scalar(3,255,MAX_VALUE),hsv_filtered15);
	cv::inRange(hsv,cv::Scalar(175,160,60),cv::Scalar(180,255,MAX_VALUE),hsv_filtered180);
	cv::add(hsv_filtered15,hsv_filtered180,hsv);
	output = rmNoise(hsv);
	imwrite(timePath+"BINARY"+FILE_EXTENTION,output);
	return 0;
}

//二値化した画像から1の面積を抽出
double Camera::countArea()
{

	double Area = output.rows*output.cols;//全ピクセル数
	double redCount = 0; //赤色を認識したピクセルの数
	redCount = cv::countNonZero(output);//赤色部分の面積を計算
	double percentage = 0; //割合
	percentage = (redCount / Area)*100;//割合を計算
	std::cout<<"面積のPercentageは"<<percentage<<std::endl;
	return percentage;
}

//二値化画像のcenterを角度で返す
double Camera::getCenter()
{
	cv::Moments mu = cv::moments(output, false);//重心の計算結果をmuに代入
	double mc = mu.m10 / mu.m00;//重心のx座標
	double center = (mc - output.cols / 2) * AOV / output.cols;//正規化
	std::cout<<"重心の位置は"<<center<<std::endl;
	return center;
}
<|endoftext|>


<commit_before>#include "General_Utilities.hpp"

#include <cmath>
#include <iostream>
#include <fstream>
#include <chrono>
#include <cstdlib>
#include <libconfig.h++>

#include "Physical_Parameters.hpp"

using namespace libconfig;

//Config file
	string FormFactor="None";
	string SimID="default";
	string experiment="default";
	string version="v1.0";
	double mChi=0,sigma=0;
	double rhoDM=0.0;
	int SampleSize=0;
	int SimDate [3] = 	{0,0,0};
	int SimTime [3] = 	{0,0,0};
	double nJ2000 = 0.0;
	Eigen::Vector3d vEarth(0,0,0);
	double vcut=0.0;
	void Read_Config_File(char *inputfile)
	{
		Config cfg;
		std::string id(inputfile);
		std::string path = "../data/"+id+".cfg";
		const char *cstr = path.c_str();
		// Read the file. If there is an error, report it and exit.
			try
			{
			  cfg.readFile(cstr);
			}
			catch(const FileIOException &fioex)
			{
				std::cerr << "I/O error while reading configuration file." << std::endl;
				exit(EXIT_FAILURE);
			}
			catch(const ParseException &pex)
			{
				std::cerr << "Configurate file parse error at " << pex.getFile() << ":" << pex.getLine() << " - " << pex.getError() << std::endl;
				exit(EXIT_FAILURE);
			}
		//Simulation ID
			try
			{
				SimID = cfg.lookup("simID").c_str();
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "No 'simID' setting in configuration file." << endl;
				exit(EXIT_FAILURE);
			}
		//Experiment
			try
			{
				experiment = cfg.lookup("experiment").c_str();
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "No 'simID' setting in configuration file." << endl;
				exit(EXIT_FAILURE);
			}
		//sample size
			try
			{
				SampleSize = cfg.lookup("samplesize");
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "No 'samplesize' setting in configuration file." << endl;
				exit(EXIT_FAILURE);
			}
		//Mass
			try
			{
				mChi = cfg.lookup("mass");
				mChi*=MeV;
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "No 'mass' setting in configuration file." << endl;
				exit(EXIT_FAILURE);
			}
		//Cross section
			try
			{
				sigma = cfg.lookup("sigma");
				sigma*=pb;
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "Error: While reading 'sigma' setting in configuration file. Computation cancelled." << endl;
				exit(EXIT_FAILURE);
			}
		//DM energy density
			try
			{
				rhoDM = cfg.lookup("rho");
				rhoDM*=GeV/cm/cm/cm;
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "Error: While reading 'rho' setting in configuration file. Computation cancelled." << endl;
				exit(EXIT_FAILURE);
			}
		//Date
			try
			{
				SimDate[0] = cfg.lookup("date")[0];
				SimDate[1] = cfg.lookup("date")[1];
				SimDate[2] = cfg.lookup("date")[2];
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "Error: While reading 'date' setting in configuration file. Computation cancelled." << endl;
				exit(EXIT_FAILURE);
			}
		//Time
			try
			{
				SimTime[0] = cfg.lookup("time")[0];
				SimTime[1] = cfg.lookup("time")[1];
				SimTime[2] = cfg.lookup("time")[2];
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "Error: While reading 'time' setting in configuration file. Computation cancelled." << endl;
				exit(EXIT_FAILURE);
			}
		//Time and Detector
			nJ2000= FractionalDays(SimDate,SimTime);
		//Earth Velocity
			vEarth=EarthVelocity(nJ2000);
	}

	void LogAnalysis(double duration,int worldsize)
	{
			ofstream f;
			f.open("../results/"+SimID+".log",std::ofstream::app);
			std::chrono::time_point<std::chrono::system_clock> end;
			end = std::chrono::system_clock::now();
			std::time_t end_time = std::chrono::system_clock::to_time_t(end);
			f	<<"\n////////////////////////////////////////////////////\n\n"
			<<"//Data analysis performed:\t" <<std::ctime(&end_time)<<endl
			<<"\tMPI processes:\t\t" <<worldsize<<endl
			<<"\tExperiment:\t\t" <<experiment<<endl
			<<"\tComputation time:\t" <<duration <<"\t("<<floor(duration/3600.0)<<":"<<floor(fmod(duration/60.0,60.0))<<":"<<floor(fmod(duration,60.0))<<":"<<floor(fmod(1000*duration,1000.0)) <<")"<<endl;

	}

	std::vector<int> WorkDivision(int WorldSize)
	{
		std::vector<int> output;
		int overlap = WorldSize*ceil(180.0/WorldSize)-180;
		for(int i =0 ; i<=WorldSize; i++)
		{
			if(i==0) 			output.push_back(0);
			else if(i<=overlap)	output.push_back(i*floor(180.0/WorldSize));
			else				output.push_back(output[i-1]+ceil(180.0/WorldSize));
		}
		return output;
	}<commit_msg>Updating the working division between the MPI processes during the analysis. Now the processes handeling the high theta rings are relieved.<commit_after>#include "General_Utilities.hpp"

#include <cmath>
#include <iostream>
#include <fstream>
#include <chrono>
#include <cstdlib>
#include <libconfig.h++>

#include "Physical_Parameters.hpp"

using namespace libconfig;

//Config file
	string FormFactor="None";
	string SimID="default";
	string experiment="default";
	string version="v1.0";
	double mChi=0,sigma=0;
	double rhoDM=0.0;
	int SampleSize=0;
	int SimDate [3] = 	{0,0,0};
	int SimTime [3] = 	{0,0,0};
	double nJ2000 = 0.0;
	Eigen::Vector3d vEarth(0,0,0);
	double vcut=0.0;
	void Read_Config_File(char *inputfile)
	{
		Config cfg;
		std::string id(inputfile);
		std::string path = "../data/"+id+".cfg";
		const char *cstr = path.c_str();
		// Read the file. If there is an error, report it and exit.
			try
			{
			  cfg.readFile(cstr);
			}
			catch(const FileIOException &fioex)
			{
				std::cerr << "I/O error while reading configuration file." << std::endl;
				exit(EXIT_FAILURE);
			}
			catch(const ParseException &pex)
			{
				std::cerr << "Configurate file parse error at " << pex.getFile() << ":" << pex.getLine() << " - " << pex.getError() << std::endl;
				exit(EXIT_FAILURE);
			}
		//Simulation ID
			try
			{
				SimID = cfg.lookup("simID").c_str();
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "No 'simID' setting in configuration file." << endl;
				exit(EXIT_FAILURE);
			}
		//Experiment
			try
			{
				experiment = cfg.lookup("experiment").c_str();
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "No 'simID' setting in configuration file." << endl;
				exit(EXIT_FAILURE);
			}
		//sample size
			try
			{
				SampleSize = cfg.lookup("samplesize");
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "No 'samplesize' setting in configuration file." << endl;
				exit(EXIT_FAILURE);
			}
		//Mass
			try
			{
				mChi = cfg.lookup("mass");
				mChi*=MeV;
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "No 'mass' setting in configuration file." << endl;
				exit(EXIT_FAILURE);
			}
		//Cross section
			try
			{
				sigma = cfg.lookup("sigma");
				sigma*=pb;
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "Error: While reading 'sigma' setting in configuration file. Computation cancelled." << endl;
				exit(EXIT_FAILURE);
			}
		//DM energy density
			try
			{
				rhoDM = cfg.lookup("rho");
				rhoDM*=GeV/cm/cm/cm;
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "Error: While reading 'rho' setting in configuration file. Computation cancelled." << endl;
				exit(EXIT_FAILURE);
			}
		//Date
			try
			{
				SimDate[0] = cfg.lookup("date")[0];
				SimDate[1] = cfg.lookup("date")[1];
				SimDate[2] = cfg.lookup("date")[2];
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "Error: While reading 'date' setting in configuration file. Computation cancelled." << endl;
				exit(EXIT_FAILURE);
			}
		//Time
			try
			{
				SimTime[0] = cfg.lookup("time")[0];
				SimTime[1] = cfg.lookup("time")[1];
				SimTime[2] = cfg.lookup("time")[2];
			}
			catch(const SettingNotFoundException &nfex)
			{
				cerr << "Error: While reading 'time' setting in configuration file. Computation cancelled." << endl;
				exit(EXIT_FAILURE);
			}
		//Time and Detector
			nJ2000= FractionalDays(SimDate,SimTime);
		//Earth Velocity
			vEarth=EarthVelocity(nJ2000);
	}

	void LogAnalysis(double duration,int worldsize)
	{
			ofstream f;
			f.open("../results/"+SimID+".log",std::ofstream::app);
			std::chrono::time_point<std::chrono::system_clock> end;
			end = std::chrono::system_clock::now();
			std::time_t end_time = std::chrono::system_clock::to_time_t(end);
			f	<<"\n////////////////////////////////////////////////////\n\n"
			<<"//Data analysis performed:\t" <<std::ctime(&end_time)<<endl
			<<"\tMPI processes:\t\t" <<worldsize<<endl
			<<"\tExperiment:\t\t" <<experiment<<endl
			<<"\tComputation time:\t" <<duration <<"\t("<<floor(duration/3600.0)<<":"<<floor(fmod(duration/60.0,60.0))<<":"<<floor(fmod(duration,60.0))<<":"<<floor(fmod(1000*duration,1000.0)) <<")"<<endl;

	}

	std::vector<int> WorkDivision(int WorldSize)
	{
		std::vector<int> output;
		int overlap = WorldSize*ceil(180.0/WorldSize)-180;
		for(int i =0 ; i<=WorldSize; i++)
		{
			if(i==0) 			output.push_back(0);
			else if(i<=(WorldSize-overlap))	output.push_back(i*ceil(180.0/WorldSize));
			else				output.push_back(output[i-1]+floor(180.0/WorldSize));
		}
		return output;
	}<|endoftext|>


<commit_before><commit_msg>Take reference instead of copying whole.<commit_after><|endoftext|>


<commit_before>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include <core/session/onnxruntime_cxx_api.h>
#include <iostream>
#include <fstream>
#ifdef _WIN32
#include "getopt.h"
#else
#include <getopt.h>
#include <thread>
#endif
#include "TestResultStat.h"
#include "testenv.h"
#include "runner.h"
#include "path_lib.h"
#include "sync_api.h"
#include "providers.h"
#include "core/session/onnxruntime_cxx_api.h"

using namespace onnxruntime;

namespace {
void usage() {
  printf(
      "onnx_test_runner [options...] <data_root>\n"
      "Options:\n"
      "\t-j [models]: Specifies the number of models to run simultaneously.\n"
      "\t-A : Disable memory arena\n"
      "\t-c [runs]: Specifies the number of Session::Run() to invoke simultaneously for each model.\n"
      "\t-r [repeat]: Specifies the number of times to repeat\n"
      "\t-v: verbose\n"
      "\t-n [test_case_name]: Specifies a single test case to run.\n"
      "\t-e [EXECUTION_PROVIDER]: EXECUTION_PROVIDER could be 'cpu', 'cuda' or 'mkldnn'. Default: 'cpu'.\n"
      "\t-x: Use parallel executor, default (without -x): sequential executor.\n"
      "\t-h: help\n");
}

#ifdef _WIN32
int GetNumCpuCores() {
  SYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer[256];
  DWORD returnLength = sizeof(buffer);
  if (GetLogicalProcessorInformation(buffer, &returnLength) == FALSE) {
    // try GetSystemInfo
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    if (sysInfo.dwNumberOfProcessors <= 0) {
      ORT_THROW("Fatal error: 0 count processors from GetSystemInfo");
    }
    // This is the number of logical processors in the current group
    return sysInfo.dwNumberOfProcessors;
  }
  int processorCoreCount = 0;
  int count = (int)(returnLength / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
  for (int i = 0; i != count; ++i) {
    if (buffer[i].Relationship == RelationProcessorCore) {
      ++processorCoreCount;
    }
  }
  if (!processorCoreCount) ORT_THROW("Fatal error: 0 count processors from GetLogicalProcessorInformation");
  return processorCoreCount;
}
#else
int GetNumCpuCores() {
  return std::thread::hardware_concurrency();
}
#endif
}  // namespace

#ifdef _WIN32
int real_main(int argc, wchar_t* argv[]) {
#else
int real_main(int argc, char* argv[]) {
#endif
  //if this var is not empty, only run the tests with name in this list
  std::vector<std::basic_string<PATH_CHAR_TYPE> > whitelisted_test_cases;
  int concurrent_session_runs = GetNumCpuCores();
  bool enable_cpu_mem_arena = true;
  bool enable_sequential_execution = true;
  int repeat_count = 1;
  int p_models = GetNumCpuCores();
  bool enable_cuda = false;
  bool enable_mkl = false;
  bool enable_nuphar = false;
  OrtLoggingLevel logging_level = ORT_LOGGING_LEVEL_kWARNING;
  {
    int ch;
    while ((ch = getopt(argc, argv, ORT_TSTR("Ac:hj:m:n:r:e:xv"))) != -1) {
      switch (ch) {
        case 'A':
          enable_cpu_mem_arena = false;
          break;
        case 'v':
          logging_level = ORT_LOGGING_LEVEL_kINFO;
          break;
        case 'c':
          concurrent_session_runs = static_cast<int>(MyStrtol<PATH_CHAR_TYPE>(optarg, nullptr, 10));
          if (concurrent_session_runs <= 0) {
            usage();
            return -1;
          }
          break;
        case 'j':
          p_models = static_cast<int>(MyStrtol<PATH_CHAR_TYPE>(optarg, nullptr, 10));
          if (p_models <= 0) {
            usage();
            return -1;
          }
          break;
        case 'r':
          repeat_count = static_cast<int>(MyStrtol<PATH_CHAR_TYPE>(optarg, nullptr, 10));
          if (repeat_count <= 0) {
            usage();
            return -1;
          }
          break;
        case 'm':
          //ignore.
          break;
        case 'n':
          //run only some whitelisted tests
          //TODO: parse name str to an array
          whitelisted_test_cases.emplace_back(optarg);
          break;
        case 'e':
          if (!MyStrCmp(optarg, ORT_TSTR("cpu"))) {
            //do nothing
          } else if (!MyStrCmp(optarg, ORT_TSTR("cuda"))) {
            enable_cuda = true;
          } else if (!MyStrCmp(optarg, ORT_TSTR("mkldnn"))) {
            enable_mkl = true;
          } else if (!MyStrCmp(optarg, ORT_TSTR("nuphar"))) {
            enable_nuphar = true;
          } else {
            usage();
            return -1;
          }
          break;
        case 'x':
          enable_sequential_execution = false;
          break;
        case '?':
        case 'h':
        default:
          usage();
          return -1;
      }
    }
  }
  if (concurrent_session_runs > 1 && repeat_count > 1) {
    fprintf(stderr, "when you use '-r [repeat]', please set '-c' to 1\n");
    usage();
    return -1;
  }
  argc -= optind;
  argv += optind;
  if (argc < 1) {
    fprintf(stderr, "please specify a test data dir\n");
    usage();
    return -1;
  }
  std::unique_ptr<OrtEnv> env;
  {
    OrtEnv* t;
    ONNXStatus* ost = OrtInitialize(logging_level, "Default", &t);
    if (ost != nullptr) {
      fprintf(stderr, "Error creating environment: %s \n", OrtGetErrorMessage(ost));
      ReleaseONNXStatus(ost);
      return -1;
    }
    env.reset(t);
  }
  std::vector<std::basic_string<PATH_CHAR_TYPE> > data_dirs;
  TestResultStat stat;

  std::unique_ptr<OrtAllocator> default_allocator;
  {
    OrtAllocator* p;
    ONNXStatus* ost = OrtCreateDefaultAllocator(&p);
    if (ost != nullptr) {
      fprintf(stderr, "Error creating environment: %s \n", OrtGetErrorMessage(ost));
      ReleaseONNXStatus(ost);
      return -1;
    }
    default_allocator.reset(p);
  }
  for (int i = 0; i != argc; ++i) {
    data_dirs.emplace_back(argv[i]);
  }
  {
    std::vector<ITestCase*> tests = LoadTests(data_dirs, whitelisted_test_cases, default_allocator.get());
    SessionOptionsWrapper sf(env.get());
    if (enable_cpu_mem_arena)
      sf.EnableCpuMemArena();
    else
      sf.DisableCpuMemArena();
    if (enable_sequential_execution)
      sf.EnableSequentialExecution();
    else
      sf.DisableSequentialExecution();
    if (enable_cuda) {
#ifdef USE_CUDA
      OrtProviderFactoryInterface** f;
      ORT_THROW_ON_ERROR(OrtCreateCUDAExecutionProviderFactory(0, &f));
      sf.AppendExecutionProvider(f);
      OrtReleaseObject(f);
#else
      fprintf(stderr, "CUDA is supported in this build");
      return -1;
#endif
    }
    if (enable_nuphar) {
#ifdef USE_NUPHAR
      OrtProviderFactoryInterface** f;
      ORT_THROW_ON_ERROR(OrtCreateNupharExecutionProviderFactory(0, "", &f));
      sf.AppendExecutionProvider(f);
      OrtReleaseObject(f);
#else
      fprintf(stderr, "Nuphar is supported in this build");
      return -1;
#endif
    }
    if (enable_mkl) {
#ifdef USE_MKLDNN
      OrtProviderFactoryInterface** f;
      ORT_THROW_ON_ERROR(OrtCreateMkldnnExecutionProviderFactory(enable_cpu_mem_arena ? 1 : 0, &f));
      sf.AppendExecutionProvider(f);
      OrtReleaseObject(f);
#else
      fprintf(stderr, "MKL-DNN is supported in this build");
      return -1;
#endif
    }
    TestEnv args(tests, stat, sf);
    Status st = RunTests(args, p_models, concurrent_session_runs, static_cast<size_t>(repeat_count), GetDefaultThreadPool(Env::Default()));
    if (!st.IsOK()) {
      fprintf(stderr, "%s\n", st.ErrorMessage().c_str());
      return -1;
    }

    std::string res = stat.ToString();
    fwrite(res.c_str(), 1, res.size(), stdout);
    for (ITestCase* l : tests) {
      delete l;
    }
  }
  std::map<std::string, std::string> broken_tests{
      {"AvgPool1d", "disable reason"},
      {"AvgPool1d_stride", "disable reason"},
      {"AvgPool2d", "disable reason"},
      {"AvgPool2d_stride", "disable reason"},
      {"AvgPool3d", "disable reason"},
      {"AvgPool3d_stride", "disable reason"},
      {"AvgPool3d_stride1_pad0_gpu_input", "disable reason"},
      {"BatchNorm1d_3d_input_eval", "disable reason"},
      {"BatchNorm2d_eval", "disable reason"},
      {"BatchNorm2d_momentum_eval", "disable reason"},
      {"BatchNorm3d_eval", "disable reason"},
      {"BatchNorm3d_momentum_eval", "disable reason"},
      {"GLU", "disable reason"},
      {"GLU_dim", "disable reason"},
      {"Linear", "disable reason"},
      {"PReLU_1d", "disable reason"},
      {"PReLU_1d_multiparam", "disable reason"},
      {"PReLU_2d", "disable reason"},
      {"PReLU_2d_multiparam", "disable reason"},
      {"PReLU_3d", "disable reason"},
      {"PReLU_3d_multiparam", "disable reason"},
      {"PoissonNLLLLoss_no_reduce", "disable reason"},
      {"Softsign", "disable reason"},
      {"convtranspose_1d", "disable reason"},
      {"convtranspose_3d", "disable reason"},
      {"dynamic_slice", "disable reason"},
      {"dynamic_slice_default_axes", "disable reason"},
      {"dynamic_slice_end_out_of_bounds", "disable reason"},
      {"dynamic_slice_neg", "disable reason"},
      {"dynamic_slice_start_out_of_bounds", "disable reason"},
      {"eyelike_populate_off_main_diagonal", "disable reason"},
      {"eyelike_with_dtype", "disable reason"},
      {"eyelike_without_dtype", "disable reason"},
      {"flatten_axis0", "disable reason"},
      {"flatten_axis1", "disable reason"},
      {"flatten_axis2", "disable reason"},
      {"flatten_axis3", "disable reason"},
      {"flatten_default_axis", "disable reason"},
      {"gemm_broadcast", "disable reason"},
      {"gemm_nobroadcast", "disable reason"},
      {"greater", "disable reason"},
      {"greater_bcast", "disable reason"},
      {"less", "disable reason"},
      {"less_bcast", "disable reason"},
      {"matmul_2d", "disable reason"},
      {"matmul_3d", "disable reason"},
      {"matmul_4d", "disable reason"},
      {"mvn", "disable reason"},
      {"operator_add_broadcast", "disable reason"},
      {"operator_add_size1_broadcast", "disable reason"},
      {"operator_add_size1_right_broadcast", "disable reason"},
      {"operator_add_size1_singleton_broadcast", "disable reason"},
      {"operator_addconstant", "disable reason"},
      {"operator_addmm", "disable reason"},
      {"operator_basic", "disable reason"},
      {"operator_lstm", "disable reason"},
      {"operator_mm", "disable reason"},
      {"operator_non_float_params", "disable reason"},
      {"operator_params", "disable reason"},
      {"operator_pow", "disable reason"},
      {"operator_rnn", "disable reason"},
      {"operator_rnn_single_layer", "disable reason"},
      {"prelu_broadcast", "disable reason"},
      {"prelu_example", "disable reason"},
      {"maxunpool_export_with_output_shape", "opset 9 not supported yet"},
      {"maxunpool_export_without_output_shape", "opset 9 not supported yet"},
      {"upsample_nearest", "opset 9 not supported yet"},
      {"onehot_with_axis", "opset 9 not supported yet"},
      {"onehot_without_axis", "opset 9 not supported yet"},  // also has bug in current test re: output type. Spandan to fix.
      {"sinh", "opset 9 not supported yet"},
      {"cosh", "opset 9 not supported yet"},
      {"asinh", "opset 9 not supported yet"},
      {"acosh", "opset 9 not supported yet"},
      {"atanh", "opset 9 not supported yet"},
      {"sinh_example", "opset 9 not supported yet"},
      {"cosh_example", "opset 9 not supported yet"},
      {"asinh_example", "opset 9 not supported yet"},
      {"acosh_example", "opset 9 not supported yet"},
      {"atanh_example", "opset 9 not supported yet"},
      {"sign_model", "opset 9 not supported yet"},
      {"sign", "opset 9 not supported yet"},
      {"scatter_with_axis", "opset 9 not supported yet"},
      {"scatter_without_axis", "opset 9 not supported yet"},
      {"scan_sum", "opset 9 not supported yet"}};

#ifdef USE_CUDA
  broken_tests["maxpool_2d_default"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_pads"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_precomputed_strides"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_precomputed_pads"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_strides"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_precomputed_same_upper"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_same_upper"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_same_lower"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_3d_default"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_1d_default"] = "cudnn pooling only support input dimension >= 3";
#endif

  int result = 0;
  for (const std::string& s : stat.GetFailedTest()) {
    if (broken_tests.find(s) == broken_tests.end()) {
      fprintf(stderr, "test %s failed, please fix it\n", s.c_str());
      result = -1;
    }
  }

  return result;
}
#ifdef _WIN32
int wmain(int argc, wchar_t* argv[]) {
#else
int main(int argc, char* argv[]) {
#endif
  try {
    return real_main(argc, argv);
  } catch (std::exception& ex) {
    fprintf(stderr, "%s\n", ex.what());
    return -1;
  }
}
<commit_msg>fix typo<commit_after>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include <core/session/onnxruntime_cxx_api.h>
#include <iostream>
#include <fstream>
#ifdef _WIN32
#include "getopt.h"
#else
#include <getopt.h>
#include <thread>
#endif
#include "TestResultStat.h"
#include "testenv.h"
#include "runner.h"
#include "path_lib.h"
#include "sync_api.h"
#include "providers.h"
#include "core/session/onnxruntime_cxx_api.h"

using namespace onnxruntime;

namespace {
void usage() {
  printf(
      "onnx_test_runner [options...] <data_root>\n"
      "Options:\n"
      "\t-j [models]: Specifies the number of models to run simultaneously.\n"
      "\t-A : Disable memory arena\n"
      "\t-c [runs]: Specifies the number of Session::Run() to invoke simultaneously for each model.\n"
      "\t-r [repeat]: Specifies the number of times to repeat\n"
      "\t-v: verbose\n"
      "\t-n [test_case_name]: Specifies a single test case to run.\n"
      "\t-e [EXECUTION_PROVIDER]: EXECUTION_PROVIDER could be 'cpu', 'cuda' or 'mkldnn'. Default: 'cpu'.\n"
      "\t-x: Use parallel executor, default (without -x): sequential executor.\n"
      "\t-h: help\n");
}

#ifdef _WIN32
int GetNumCpuCores() {
  SYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer[256];
  DWORD returnLength = sizeof(buffer);
  if (GetLogicalProcessorInformation(buffer, &returnLength) == FALSE) {
    // try GetSystemInfo
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    if (sysInfo.dwNumberOfProcessors <= 0) {
      ORT_THROW("Fatal error: 0 count processors from GetSystemInfo");
    }
    // This is the number of logical processors in the current group
    return sysInfo.dwNumberOfProcessors;
  }
  int processorCoreCount = 0;
  int count = (int)(returnLength / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
  for (int i = 0; i != count; ++i) {
    if (buffer[i].Relationship == RelationProcessorCore) {
      ++processorCoreCount;
    }
  }
  if (!processorCoreCount) ORT_THROW("Fatal error: 0 count processors from GetLogicalProcessorInformation");
  return processorCoreCount;
}
#else
int GetNumCpuCores() {
  return std::thread::hardware_concurrency();
}
#endif
}  // namespace

#ifdef _WIN32
int real_main(int argc, wchar_t* argv[]) {
#else
int real_main(int argc, char* argv[]) {
#endif
  //if this var is not empty, only run the tests with name in this list
  std::vector<std::basic_string<PATH_CHAR_TYPE> > whitelisted_test_cases;
  int concurrent_session_runs = GetNumCpuCores();
  bool enable_cpu_mem_arena = true;
  bool enable_sequential_execution = true;
  int repeat_count = 1;
  int p_models = GetNumCpuCores();
  bool enable_cuda = false;
  bool enable_mkl = false;
  bool enable_nuphar = false;
  OrtLoggingLevel logging_level = ORT_LOGGING_LEVEL_kWARNING;
  {
    int ch;
    while ((ch = getopt(argc, argv, ORT_TSTR("Ac:hj:m:n:r:e:xv"))) != -1) {
      switch (ch) {
        case 'A':
          enable_cpu_mem_arena = false;
          break;
        case 'v':
          logging_level = ORT_LOGGING_LEVEL_kINFO;
          break;
        case 'c':
          concurrent_session_runs = static_cast<int>(MyStrtol<PATH_CHAR_TYPE>(optarg, nullptr, 10));
          if (concurrent_session_runs <= 0) {
            usage();
            return -1;
          }
          break;
        case 'j':
          p_models = static_cast<int>(MyStrtol<PATH_CHAR_TYPE>(optarg, nullptr, 10));
          if (p_models <= 0) {
            usage();
            return -1;
          }
          break;
        case 'r':
          repeat_count = static_cast<int>(MyStrtol<PATH_CHAR_TYPE>(optarg, nullptr, 10));
          if (repeat_count <= 0) {
            usage();
            return -1;
          }
          break;
        case 'm':
          //ignore.
          break;
        case 'n':
          //run only some whitelisted tests
          //TODO: parse name str to an array
          whitelisted_test_cases.emplace_back(optarg);
          break;
        case 'e':
          if (!MyStrCmp(optarg, ORT_TSTR("cpu"))) {
            //do nothing
          } else if (!MyStrCmp(optarg, ORT_TSTR("cuda"))) {
            enable_cuda = true;
          } else if (!MyStrCmp(optarg, ORT_TSTR("mkldnn"))) {
            enable_mkl = true;
          } else if (!MyStrCmp(optarg, ORT_TSTR("nuphar"))) {
            enable_nuphar = true;
          } else {
            usage();
            return -1;
          }
          break;
        case 'x':
          enable_sequential_execution = false;
          break;
        case '?':
        case 'h':
        default:
          usage();
          return -1;
      }
    }
  }
  if (concurrent_session_runs > 1 && repeat_count > 1) {
    fprintf(stderr, "when you use '-r [repeat]', please set '-c' to 1\n");
    usage();
    return -1;
  }
  argc -= optind;
  argv += optind;
  if (argc < 1) {
    fprintf(stderr, "please specify a test data dir\n");
    usage();
    return -1;
  }
  std::unique_ptr<OrtEnv> env;
  {
    OrtEnv* t;
    ONNXStatus* ost = OrtInitialize(logging_level, "Default", &t);
    if (ost != nullptr) {
      fprintf(stderr, "Error creating environment: %s \n", OrtGetErrorMessage(ost));
      ReleaseONNXStatus(ost);
      return -1;
    }
    env.reset(t);
  }
  std::vector<std::basic_string<PATH_CHAR_TYPE> > data_dirs;
  TestResultStat stat;

  std::unique_ptr<OrtAllocator> default_allocator;
  {
    OrtAllocator* p;
    ONNXStatus* ost = OrtCreateDefaultAllocator(&p);
    if (ost != nullptr) {
      fprintf(stderr, "Error creating environment: %s \n", OrtGetErrorMessage(ost));
      ReleaseONNXStatus(ost);
      return -1;
    }
    default_allocator.reset(p);
  }
  for (int i = 0; i != argc; ++i) {
    data_dirs.emplace_back(argv[i]);
  }
  {
    std::vector<ITestCase*> tests = LoadTests(data_dirs, whitelisted_test_cases, default_allocator.get());
    SessionOptionsWrapper sf(env.get());
    if (enable_cpu_mem_arena)
      sf.EnableCpuMemArena();
    else
      sf.DisableCpuMemArena();
    if (enable_sequential_execution)
      sf.EnableSequentialExecution();
    else
      sf.DisableSequentialExecution();
    if (enable_cuda) {
#ifdef USE_CUDA
      OrtProviderFactoryInterface** f;
      ORT_THROW_ON_ERROR(OrtCreateCUDAExecutionProviderFactory(0, &f));
      sf.AppendExecutionProvider(f);
      OrtReleaseObject(f);
#else
      fprintf(stderr, "CUDA is not supported in this build");
      return -1;
#endif
    }
    if (enable_nuphar) {
#ifdef USE_NUPHAR
      OrtProviderFactoryInterface** f;
      ORT_THROW_ON_ERROR(OrtCreateNupharExecutionProviderFactory(0, "", &f));
      sf.AppendExecutionProvider(f);
      OrtReleaseObject(f);
#else
      fprintf(stderr, "Nuphar is not supported in this build");
      return -1;
#endif
    }
    if (enable_mkl) {
#ifdef USE_MKLDNN
      OrtProviderFactoryInterface** f;
      ORT_THROW_ON_ERROR(OrtCreateMkldnnExecutionProviderFactory(enable_cpu_mem_arena ? 1 : 0, &f));
      sf.AppendExecutionProvider(f);
      OrtReleaseObject(f);
#else
      fprintf(stderr, "MKL-DNN is not supported in this build");
      return -1;
#endif
    }
    TestEnv args(tests, stat, sf);
    Status st = RunTests(args, p_models, concurrent_session_runs, static_cast<size_t>(repeat_count), GetDefaultThreadPool(Env::Default()));
    if (!st.IsOK()) {
      fprintf(stderr, "%s\n", st.ErrorMessage().c_str());
      return -1;
    }

    std::string res = stat.ToString();
    fwrite(res.c_str(), 1, res.size(), stdout);
    for (ITestCase* l : tests) {
      delete l;
    }
  }
  std::map<std::string, std::string> broken_tests{
      {"AvgPool1d", "disable reason"},
      {"AvgPool1d_stride", "disable reason"},
      {"AvgPool2d", "disable reason"},
      {"AvgPool2d_stride", "disable reason"},
      {"AvgPool3d", "disable reason"},
      {"AvgPool3d_stride", "disable reason"},
      {"AvgPool3d_stride1_pad0_gpu_input", "disable reason"},
      {"BatchNorm1d_3d_input_eval", "disable reason"},
      {"BatchNorm2d_eval", "disable reason"},
      {"BatchNorm2d_momentum_eval", "disable reason"},
      {"BatchNorm3d_eval", "disable reason"},
      {"BatchNorm3d_momentum_eval", "disable reason"},
      {"GLU", "disable reason"},
      {"GLU_dim", "disable reason"},
      {"Linear", "disable reason"},
      {"PReLU_1d", "disable reason"},
      {"PReLU_1d_multiparam", "disable reason"},
      {"PReLU_2d", "disable reason"},
      {"PReLU_2d_multiparam", "disable reason"},
      {"PReLU_3d", "disable reason"},
      {"PReLU_3d_multiparam", "disable reason"},
      {"PoissonNLLLLoss_no_reduce", "disable reason"},
      {"Softsign", "disable reason"},
      {"convtranspose_1d", "disable reason"},
      {"convtranspose_3d", "disable reason"},
      {"dynamic_slice", "disable reason"},
      {"dynamic_slice_default_axes", "disable reason"},
      {"dynamic_slice_end_out_of_bounds", "disable reason"},
      {"dynamic_slice_neg", "disable reason"},
      {"dynamic_slice_start_out_of_bounds", "disable reason"},
      {"eyelike_populate_off_main_diagonal", "disable reason"},
      {"eyelike_with_dtype", "disable reason"},
      {"eyelike_without_dtype", "disable reason"},
      {"flatten_axis0", "disable reason"},
      {"flatten_axis1", "disable reason"},
      {"flatten_axis2", "disable reason"},
      {"flatten_axis3", "disable reason"},
      {"flatten_default_axis", "disable reason"},
      {"gemm_broadcast", "disable reason"},
      {"gemm_nobroadcast", "disable reason"},
      {"greater", "disable reason"},
      {"greater_bcast", "disable reason"},
      {"less", "disable reason"},
      {"less_bcast", "disable reason"},
      {"matmul_2d", "disable reason"},
      {"matmul_3d", "disable reason"},
      {"matmul_4d", "disable reason"},
      {"mvn", "disable reason"},
      {"operator_add_broadcast", "disable reason"},
      {"operator_add_size1_broadcast", "disable reason"},
      {"operator_add_size1_right_broadcast", "disable reason"},
      {"operator_add_size1_singleton_broadcast", "disable reason"},
      {"operator_addconstant", "disable reason"},
      {"operator_addmm", "disable reason"},
      {"operator_basic", "disable reason"},
      {"operator_lstm", "disable reason"},
      {"operator_mm", "disable reason"},
      {"operator_non_float_params", "disable reason"},
      {"operator_params", "disable reason"},
      {"operator_pow", "disable reason"},
      {"operator_rnn", "disable reason"},
      {"operator_rnn_single_layer", "disable reason"},
      {"prelu_broadcast", "disable reason"},
      {"prelu_example", "disable reason"},
      {"maxunpool_export_with_output_shape", "opset 9 not supported yet"},
      {"maxunpool_export_without_output_shape", "opset 9 not supported yet"},
      {"upsample_nearest", "opset 9 not supported yet"},
      {"onehot_with_axis", "opset 9 not supported yet"},
      {"onehot_without_axis", "opset 9 not supported yet"},  // also has bug in current test re: output type. Spandan to fix.
      {"sinh", "opset 9 not supported yet"},
      {"cosh", "opset 9 not supported yet"},
      {"asinh", "opset 9 not supported yet"},
      {"acosh", "opset 9 not supported yet"},
      {"atanh", "opset 9 not supported yet"},
      {"sinh_example", "opset 9 not supported yet"},
      {"cosh_example", "opset 9 not supported yet"},
      {"asinh_example", "opset 9 not supported yet"},
      {"acosh_example", "opset 9 not supported yet"},
      {"atanh_example", "opset 9 not supported yet"},
      {"sign_model", "opset 9 not supported yet"},
      {"sign", "opset 9 not supported yet"},
      {"scatter_with_axis", "opset 9 not supported yet"},
      {"scatter_without_axis", "opset 9 not supported yet"},
      {"scan_sum", "opset 9 not supported yet"}};

#ifdef USE_CUDA
  broken_tests["maxpool_2d_default"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_pads"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_precomputed_strides"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_precomputed_pads"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_strides"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_precomputed_same_upper"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_same_upper"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_2d_same_lower"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_3d_default"] = "cudnn pooling only support input dimension >= 3";
  broken_tests["maxpool_1d_default"] = "cudnn pooling only support input dimension >= 3";
#endif

  int result = 0;
  for (const std::string& s : stat.GetFailedTest()) {
    if (broken_tests.find(s) == broken_tests.end()) {
      fprintf(stderr, "test %s failed, please fix it\n", s.c_str());
      result = -1;
    }
  }

  return result;
}
#ifdef _WIN32
int wmain(int argc, wchar_t* argv[]) {
#else
int main(int argc, char* argv[]) {
#endif
  try {
    return real_main(argc, argv);
  } catch (std::exception& ex) {
    fprintf(stderr, "%s\n", ex.what());
    return -1;
  }
}
<|endoftext|>