Skip to content
Snippets Groups Projects
sclock.c 3.87 KiB
Newer Older
/*
 * Clocks, real-time and otherwise.
 * Stuart Levy, slevy@ncsa.uiuc.edu
 * National Center for Supercomputing Applications,
 * University of Illinois 2001.
 */

slevy's avatar
slevy committed
#if WIN32
# include <sys/timeb.h>
slevy's avatar
 
slevy committed
# include <memory.h>
# include "winjunk.h"
slevy's avatar
slevy committed
#else
# include <time.h>
# include <sys/types.h>
# include <sys/time.h>
#endif

#include <stdlib.h>
#include <math.h>

slevy's avatar
 
slevy committed
#if CAVE
# include <cave_ogl.h>
#endif

slevy's avatar
slevy committed
#include "sclock.h"

double wallclock_time(void)
{
#if CAVE
  return *CAVETime;
#else
#if WIN32
  static struct _timeb tm0;
  struct _timeb tm;
  _ftime( &tm );
  if(tm0.time == 0)
	  tm0 = tm;
  return tm.time - tm0.time + .001*(tm.millitm - tm0.millitm);
#else /*unix*/
  struct timeval now;
  static struct timeval tv0;
  gettimeofday(&now, NULL);
  if(tv0.tv_sec == 0)
    tv0 = now;
  return (now.tv_sec - tv0.tv_sec) + 1e-6*(now.tv_usec - tv0.tv_usec);
#endif
#endif
}

void clock_init( SClock *clk ) {
    memset(clk, 0, sizeof(*clk));
    clk->fwd = 1;
}

void clock_tick( SClock *clk ) {
    if(clk == NULL) return;
    if(!clk->running) return;

    if(clk->parent) {
	clk->curtime = clock_time(clk->parent)*clk->speed*clk->fwd + clk->basetime;
	/* ... or maybe some other function of parent's clock ... */
	clk->seqno = clk->parent->seqno;
    } else {
	clk->seqno++;
	if(clk->walltimed) {
	    double wallnow = (clk->wallfunc!=NULL)
				? (*clk->wallfunc)(clk) : wallclock_time();
	    if(clk->waswalltimed)
	    	clk->curtime += clk->fwd * clk->speed * (wallnow - clk->walllasttick);
	    clk->walllasttick = wallnow;
	} else {
slevy's avatar
 
slevy committed
	    clock_step(clk, clk->fwd);
slevy's avatar
slevy committed
	}
	clk->waswalltimed = clk->walltimed;
    }
}

double clock_time( SClock *clk ) {
slevy's avatar
 
slevy committed
    double curtime;

slevy's avatar
slevy committed
    if(clk == NULL) return 0;
slevy's avatar
 
slevy committed

    curtime = clk->curtime;
    if(curtime < clk->tmin) {
	double delta = fmod( clk->tmin - curtime,
slevy's avatar
slevy committed
				clk->tmax - clk->tmin + 2*clk->wrapband )
			- clk->wrapband;
slevy's avatar
 
slevy committed
	if(delta > 0) clock_set_time( clk, curtime = clk->tmax - delta );
	else curtime = clk->tmin;
slevy's avatar
slevy committed

    } else if(clk->curtime > clk->tmax) {
	double delta = fmod( clk->curtime - clk->tmax,
slevy's avatar
 
slevy committed
				clk->tmax - clk->tmin + 2*clk->wrapband )
slevy's avatar
slevy committed
			- clk->wrapband;
slevy's avatar
 
slevy committed
	if(delta > 0) clock_set_time( clk, curtime = clk->tmin + delta );
	else curtime = clk->tmax;
slevy's avatar
slevy committed
    }
slevy's avatar
 
slevy committed
    return clk->continuous ? curtime : rint(curtime);
slevy's avatar
slevy committed
}

void clock_set_fwd( SClock *clk, int fwd ) {
    fwd = (fwd>0) ? 1 : -1;
    if(clk && clk->fwd != fwd) {
	clk->basetime += 2*(clk->curtime - clk->basetime);
	clk->fwd = fwd;
    }
}

int clock_fwd( SClock *clk ) {
    return clk ? (clk->fwd>0 ? 1 : -1) : 0;
}

void clock_set_time( SClock *clk, double newtime ) {
    if(clk) {
	clk->basetime += newtime - clk->curtime;
	clk->curtime = newtime;
    }
}

void clock_set_speed( SClock *clk, double speed ) {
    /* Set speed while adjusting base to preserve value */
    if(clk && clk->speed != speed) {
	if(clk->speed != 0)
	    clk->basetime += (1 - speed/clk->speed) * clk->fwd
				* (clk->curtime - clk->basetime);
	clk->speed = speed;
    }
}

double clock_speed( SClock *clk ) {
    return clk ? clk->speed : 0;
}

void clock_set_timebase( SClock *clk, double timebase ) {
    if(clk)
	clk->basetime = timebase;
}

double clock_timebase( SClock *clk ) {
    return clk ? clk->basetime : 0;
}

slevy's avatar
slevy committed
void clock_set_step( SClock *clk, double step ) {
    if(clk) clk->deltatime = step;
}

void clock_step( SClock *clk, double sign ) {
slevy's avatar
 
slevy committed
    clock_add( clk, sign * clk->deltatime );
slevy's avatar
slevy committed
}

void clock_add( SClock *clk, double incr ) {
    if(clk) {
	clk->curtime += incr;
	clk->basetime += incr;
	clk->seqno++;
    }
}

void clock_set_running( SClock *clk, int running ) {
    if(clk) {
	clk->running = running;
	clk->waswalltimed = 0;
    }
}

int clock_running( SClock *clk ) {
    return clk ? clk->running : 0;
}

void clock_set_range( SClock *clk, double tmin, double tmax, double wrapband ) {
slevy's avatar
 
slevy committed
    /* if(tmin == tmax) tmax = tmin + 1; */
slevy's avatar
slevy committed
    clk->tmin = tmin;
    clk->tmax = tmax;
    clk->wrapband = wrapband>0 ? wrapband : 0;
}