Another Timer class [Windows Only]

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Zeuss
Posts: 114
Joined: Mon Nov 08, 2004 9:02 pm
Location: Canberra - Australia
Contact:

Another Timer class [Windows Only]

Post by Zeuss »

I got a bit bored, and wanted to make something different that never really gets much attention, so I made myself a new timer class for fun.

I know there is some pretty horrid stuff happening in there, but it seems to do a reasonable job.

Comments, suggestions, criticisms welcome.

Code: Select all

// Filename:	Timer.h
// Author:		Caswal 'Zeussy' Parker
// Date:		11th June 2008
// License:		Use as you want for what you want, just leave this documentation at the top of the file.
//				I am not liable for any harm this may file may cause. Use at your own risk.
//
// Description: The ultimate time elapsed class for games and other time critical applications
//				Has specific time elapsed calls as well as a general one
//				Uses Singleton Design Patter so accessibly globally
//				It can also callback functions and member functions of a class
//				
// Usage:		Above int main(int argc, char* argv[]) add INIT_TIMER
//				float DT = Timer.getTimeElapsed();
//				float DT = Timer.getTimeElasped("Player");
//				float DT = Timer["Player"];
//
//				Timer.addCallback( &func, 3 );
//				Timer.addMemberCallback<bar>( &object, &bar::func, 5 );
//
//				Timer.update(); //Must be called every so often, probably once an update/main loop
#ifndef __TIMER_H__
#define __TIMER_H__

#include <list>
#include <map>
#include <string>
#include <windows.h>

#define Timer (*CTimer::Instance())
#define PTimer (CTimer::Instance())
#define INIT_TIMER CTimer* CTimer::instance = 0;

class CTimer
{
	//Keep these private, else we ain't no singleton
	CTimer(void)
	{
		//Better restrict to 1 processor, for good ol Performance Counter
		SetProcessAffinityMask( GetCurrentProcess(), 1L );

		QueryPerformanceFrequency( &freq );
		QueryPerformanceCounter( &prevTime );
	}
	virtual ~CTimer(void) {};
public:

	//The instance function, if anyones cares to invoke it by hand
	static CTimer* Instance()
	{
		if ( instance == 0 )
			return instance = new CTimer();

		return instance;
	}

	//Destroy function for the singleton
	static void Destroy()
	{
		delete instance;
		instance = 0;
	}

	//The lazy way of getting time elapsed for a specific timer
	float operator[](const char* name)
	{
		return getTimeElapsed(name);
	}


	//The way of getting the generic time elapsed, or a specific
	float getTimeElapsed(const char* name = 0)
	{
		LARGE_INTEGER CurrentTime;

		if ( name )
		{
			if ( times[name].QuadPart == 0 )
			{
				QueryPerformanceCounter( &times[name] );
				return 0.f;
			} else
			{
				QueryPerformanceCounter( &CurrentTime );

				LARGE_INTEGER Difference;
				Difference.QuadPart = CurrentTime.QuadPart - times[name].QuadPart;

				QueryPerformanceCounter( &times[name] );


				return (float)Difference.QuadPart / (float)freq.QuadPart;
			}
		}
		else
		{
			QueryPerformanceCounter( &CurrentTime );

			LARGE_INTEGER Difference;
			Difference.QuadPart = CurrentTime.QuadPart - prevTime.QuadPart;

			QueryPerformanceCounter( &prevTime );


			return (float)Difference.QuadPart / (float)freq.QuadPart;
		}
	}


	//Function Pointer Typedef
	typedef void (*fptr)(void);

	//Add a simple void func(void) function to be called back later
	void addCallback( fptr ptr, float timeToCallInSecs )
	{
		SCallback temp;
		temp.func = ptr;
		temp.timeToCall = timeToCallInSecs;

		QueryPerformanceCounter( &(temp.startTime) );		

		callbacks.push_back(temp);
	}

	//Add a member void func(void) function of a class to be called back later
	template <class T> void addMemberCallback(T *Object, void (T::*fmptr)(), float TimeToCall )
	{
		SMemberCallback tempCall;

		tempCall.Object = Object;
		tempCall.timeToCall = TimeToCall;
		QueryPerformanceCounter( &(tempCall.startTime) );		

		typedef void (SMemberCallback::*cast)();

		tempCall.fmptr = (cast)fmptr;

		memberCallbacks.push_back(tempCall);
	}

	//For timed callbacks
	//After enough time has elapsed, execure the callbacks
	void update()
	{
		//Get the current time
		LARGE_INTEGER CurrentTime;
		QueryPerformanceCounter( &CurrentTime );

		//Some more Local Scope
		{
			std::list<SCallback>::iterator iter = callbacks.begin();

			//Loop through the callbacks, call and erase any callbacks thate are ready
			while(iter != callbacks.end())
			{
				float diff = (float)(CurrentTime.QuadPart - prevTime.QuadPart) / (float)freq.QuadPart;

				if ( diff > iter->timeToCall )
				{
					(*iter->func)();
					
					iter = callbacks.erase(iter++);
				}
				else 
					iter++;
			}
		}

		std::list<SMemberCallback>::iterator iter = memberCallbacks.begin();

		//Loop through the member callbacks
		while(iter != memberCallbacks.end())
		{
			float diff = (float)(CurrentTime.QuadPart - prevTime.QuadPart) / (float)freq.QuadPart;

			if ( diff > iter->timeToCall )
			{
				//Omg it burns us!
				//I am unsure if this is virtual safe?
				//I would assume so as the function pointer originally passed
				//Has to be from the type to be allowed to be passed as a parameter of addCallback
				//The SMemberCallback* typecast is just to get around the problem that you cannot
				//Invoke a function on a void datatype
				//A few tests seem to indicate that this is fine
				((SMemberCallback*)iter->Object->*iter->fmptr)();
				
				iter = memberCallbacks.erase(iter++);
			}
			else 
				iter++;
		}
	}

private:
	//Current Instance
	static CTimer *instance;

	//Map for all the specific time elapsed
	std::map<std::string, LARGE_INTEGER> times;

	//Generic timer stuff
	LARGE_INTEGER prevTime;
	LARGE_INTEGER freq;

	//Callback vars and types
	//Standard function callback
	struct SCallback
	{
		fptr func;
		float timeToCall;
		LARGE_INTEGER startTime;
	};

	//Member function callback
	struct SMemberCallback
	{
		void (SMemberCallback::*fmptr)(void);
		void *Object;
		float timeToCall;
		LARGE_INTEGER startTime;
	};

	//The list of callback
	std::list<SCallback> callbacks;
	std::list<SMemberCallback> memberCallbacks;
};


#endif
Help make Irrlicht even Better! Create and submit your own Irrlicht Extension
Want a Games Education? Try The Academy of Interactive Entertainment
Post Reply