Suggestion : microseconds timer


#1

Hi Jules,

I’ve seen that the timer classes in Juce can only go down to millisecond accuracy.
In case you’re interested, I’ve written a cross-platform class which measures time using microseconds

Please feel free to reuse this code (it probably not good enough to be used “as is” in Juce though)

[code]#include “timer.h”

#ifdef _WINDOWS
#include <windows.h>

LARGE_INTEGER countsPerSec;
boost::uint_fast64_t countsPerMicrosec;
LARGE_INTEGER startTime;


 Timer::Timer()
{
	QueryPerformanceFrequency(&countsPerSec);
	countsPerMicrosec=1000000*countsPerSec.QuadPart;
	QueryPerformanceCounter(&startTime);
}




boost::uint_fast64_t  Timer::getRunningTimeMicrosec(void)
{
	LARGE_INTEGER currentTime; 		
	QueryPerformanceCounter(&currentTime);
	return (boost::uint_fast64_t)((currentTime.QuadPart-startTime.QuadPart)/countsPerMicrosec) ;
}




void  Timer::waitFor(boost::uint_fast64_t durationInMicrosec)
{
	LARGE_INTEGER callTime; 		
	QueryPerformanceCounter(&callTime);
	boost::uint_fast64_t callTimeInMicrosecs=(boost::uint_fast64_t)callTime.QuadPart/countsPerMicrosec;

	if(durationInMicrosec>1000) // if theres more than 1ms to wait, then we wait by steps of 1ms 
	{
		Sleep((DWORD)durationInMicrosec/1000); //integer division -> integer result
	}
	while(getRunningTimeMicrosec()<durationInMicrosec+callTimeInMicrosecs);
	
}



void  Timer::waitUntil(boost::uint_fast64_t timeInMicrosec)
{
	LARGE_INTEGER callTime; 
	QueryPerformanceCounter(&callTime);
	boost::uint_fast64_t callTimeInMicrosecs=(boost::uint_fast64_t)callTime.QuadPart/countsPerMicrosec;
	boost::int_fast64_t deltaMicrosec=timeInMicrosec-callTimeInMicrosecs;
	if (deltaMicrosec<0)
	{
		return; //shit, we're already late !
	}
	else
	{
		if(deltaMicrosec>1000) // if theres more than 1ms to wait, then we wait by steps of 1ms 
		{
			Sleep((DWORD)deltaMicrosec/1000); //integer division -> integer result
		}
	while(getRunningTimeMicrosec()<timeInMicrosec);
	}
}

#else // !_WINDOWS -> We can safely use boost :slight_smile:
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread.hpp>

 Timer::Timer()
{
	startTime=boost::posix_time::microsec_clock::local_time();
}




boost::uint_fast64_t  Timer::getRunningTimeMicrosec(void)
{
	return (boost::uint_fast64_t)(boost::posix_time::microsec_clock::local_time()-startTime).total_microseconds();
}




void  Timer::waitFor(boost::uint_fast64_t durationInMicrosec)
{
	boost::this_thread::sleep(boost::posix_time::microseconds(durationInMicrosec));	
}



void  Timer::waitUntil(boost::uint_fast64_t timeInMicrosec)
{
	boost::uint_fast64_t callTime=getRunningTimeMicrosec();

	boost::int_fast64_t deltaMicrosec=timeInMicrosec-callTime;
	if (deltaMicrosec<0)
	{
		return; //shit, we're already late !
	}
	else
	{
		boost::this_thread::sleep(boost::posix_time::microseconds(deltaMicrosec));	
	}
}

#endif[/code]

It uses boost though …


#2

What’s wrong with Time::getMillisecondCounterHiRes() or Time::getHighResolutionTicks() ?


#3

Errr …Time::getMillisecondCounterHiRes() returns milliseconds, not microseconds, or did I miss something ? :slight_smile:

However, my implementation is absolutely not necessary at all, as you have everything needed (and better implemented :slight_smile: ) in juce_win32_SystemStats.cpp
I guess the correct, cross platform way to get the time in microseconds is simply to make something like :


#4

It returns a double


#5

It returns a double…[/quote]

This totally proves I should drink more cofee. sorry for making you loose your time :roll: