//-----------------------------------------------------------------------------
// COPYRIGHT  (c)  1997 
// THE REGENTS OF THE UNIVERSITY OF MICHIGAN
// ALL RIGHTS RESERVED
// 
// PERMISSION IS GRANTED TO USE, COPY, CREATE DERIVATIVE WORKS 
// AND REDISTRIBUTE THIS SOFTWARE AND SUCH DERIVATIVE WORKS FOR 
// ANY PURPOSE, SO LONG AS NO FEE IS CHARGED, AND SO LONG AS 
// THE COPYRIGHT NOTICE ABOVE, THIS GRANT OF PERMISSION, AND 
// THE DISCLAIMER BELOW APPEAR IN ALL COPIES MADE; AND SO LONG 
// AS THE NAME OF THE UNIVERSITY OF MICHIGAN IS NOT USED IN ANY 
// ADVERTISING OR PUBLICITY PERTAINING TO THE USE OR 
// DISTRIBUTION OF THIS SOFTWARE WITHOUT SPECIFIC, WRITTEN 
// PRIOR AUTHORIZATION.
// 
// THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 
// FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS 
// FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE 
// UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR 
// IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
// REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 
// FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 
// CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT 
// HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH 
// DAMAGES.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// File: time.hh
//
// Purpose: Routines for measuring the time spent in a given process.
//
// Remarks: --
//
// History: 04/21/92 - JPMS - first version.
//
// Copyright (c) 1996 Joao P. Marques Silva.
//
// RCS Version:
//     $Id: time.hh,v 1.1.1.1 2002/05/01 14:23:27 mguthaus Exp $
//-----------------------------------------------------------------------------

#ifndef _TIMER_DEF_
#define _TIMER_DEF_

#include <stream.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>


extern "C" {
#ifdef _I386_RESOURCE_H
    /* LINUX defines rusage_who with an enum, who else? */
    int getrusage(enum __rusage_who, struct rusage*);
#else
    int getrusage(int, struct rusage*);
#endif
}


//-----------------------------------------------------------------------------
// Class: Timer
//
// Purpose: Time measurement class and member functions.
//-----------------------------------------------------------------------------

class Timer {
  public:

    //-------------------------------------------------------------------------
    // Constructor.
    //-------------------------------------------------------------------------

    Timer() { updateTime(); start = last = current; }
    ~Timer() {}

    //-------------------------------------------------------------------------
    // Presets time to current time.
    //-------------------------------------------------------------------------

    inline void presetTime() {
	updateTime();
	start = last = current;
    }

    //-------------------------------------------------------------------------
    // Returns elapsed CPU time since last call for this object.
    //-------------------------------------------------------------------------

    inline double elapsedTime() {
	updateTime();
	msec = (current - last) / 1000.0;
	last = current;
	return( msec );
    }

    //-------------------------------------------------------------------------
    // Returns total CPU time since construction of object.
    //-------------------------------------------------------------------------

    inline double totalTime() {
	updateTime();
	msec = (current - start) / 1000.0;
	last = current;
	return( msec );
    }

    //-------------------------------------------------------------------------
    // Reads total time, but does not change the information used to measure
    // the elapsed time (last).
    //-------------------------------------------------------------------------

    inline double readTime() {
	updateTime();
	msec = (current - start) / 1000.0;
	return( msec );
    }
  protected:

    //-------------------------------------------------------------------------
    // Auxiliar variables.
    //-------------------------------------------------------------------------

    double msec;

    //-------------------------------------------------------------------------
    // Auxiliary internal variables.
    //-------------------------------------------------------------------------

    long          start;    // Start time, when the constructor is invoked.
    long          last;     // Last time the print time method was made.
    long          current;  // Present time.
    struct rusage rusage;   // Resource variable.
    double        _time;    // Time in seconds.

    //-------------------------------------------------------------------------
    // Updates current time of object.
    //-------------------------------------------------------------------------

    inline void updateTime() {
        // Note: this seems to cause a UMR warning when running
        // purify.  I think it is because the rusage struct has
        // some zero-padded fields.  Probably correct behavior.
        // - MAR
	(void) getrusage(RUSAGE_SELF, &rusage);

	// User time.

	current = (long) (rusage.ru_utime.tv_sec*1000 +
	                 rusage.ru_utime.tv_usec/1000);

	// System time => total time.
	// NOTE: Most packages and tools do not measure the system time.

	current += (long) (rusage.ru_stime.tv_sec*1000+
	                  rusage.ru_stime.tv_usec/1000);
    }
};

#endif

/*****************************************************************************/

