/*

 BabbleMud - A MUD server

 Author:  Nick Gammon 
          http://www.gammon.com.au/ 

(C) Copyright Nick Gammon 2004. Permission to copy, use, modify, sell and
distribute this software is granted provided this copyright notice appears
in all copies. This software is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.
 
*/


// updated timer.cpp to make it Windows compatible
//   -dhaley aug-15-04

#ifdef WIN32
#include <windows.h>	// for QueryPerformanceCounter
#else
#include <sys/time.h>	// for gettimeofday
#endif

#include "timer.h"
#include <iomanip>

/*

Useful timer class. Times whatever happens during its lifetime.

Can output to an output stream (which could be converted to a string, see
example, or a double.

Example of simple usage to output to cout:

  {
  timer t ("test");
  // do something
  }   // destructor outputs times to cout
  
Example of outputting to a string:

  ostringstream os;
  {
  timer t ("doing lots of things", &os);
  // do something
  } // destructor outputs time to os
  string s = os.str ();

Example of outputting to a double:

  double d = 0.0;
  {
  timer t ("test", NULL, &d);
  // do something
  }   // destructor outputs to d
  
  cout << "d = " << d << endl;

*/


// constructor remembers time it was constructed
timer::timer (const string & reason, ostream * os, double * total) 
  : reason_ (reason), os_ (os), total_ (total)
{
#ifdef WIN32
	LARGE_INTEGER large_int_frequency;	
	QueryPerformanceFrequency (&large_int_frequency);
	counterFrequency_ = large_int_frequency.QuadPart;
	QueryPerformanceCounter	((LARGE_INTEGER	*) &start_);
#else
	struct timeval t;
	gettimeofday( &t, NULL );
	start_ = (t.tv_sec * 1000000L) + t.tv_usec;
#endif
	if (os)
		*os_ <<	"Start	   : " << std::setw (25) << std::left << reason_ << std::endl;
};  // end constructor

// destructor gets current time, displays difference
timer::~timer () throw ()
{
#ifdef WIN32
	__int64	finish;
	__int64	iTimeTaken;	   
	QueryPerformanceCounter	((LARGE_INTEGER	*) &finish);  
	iTimeTaken = finish	- start_; 
	double total = ((double) iTimeTaken) /		
		((double) counterFrequency_);
#else
	struct timeval t;
	gettimeofday( &t, NULL );
	long long finish = (t.tv_sec * 1000000L) + t.tv_usec; 
	double total = (finish - start_) / 1000000.0;
#endif
	if ( total_ ) // add to the total, if we have one
		*total_ += total;
	if ( os_ ) // print if we wanted to
	{
		*os_ <<	"Time taken: " << std::setw (25) << std::left << reason_ << " = "
			<< std::fixed << total << " seconds." << std::endl;
	}
};     // end destructor
