From bf70ca6bb2e3cd92e373205ed55f827e86a2f0cf Mon Sep 17 00:00:00 2001
From: kaetemi <none@none>
Date: Fri, 27 Jul 2012 22:26:49 +0200
Subject: [PATCH] Added: Function to prefer high resolution local time

---
 code/nel/include/nel/misc/time_nl.h |  8 +++++-
 code/nel/src/misc/time_nl.cpp       | 44 +++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/code/nel/include/nel/misc/time_nl.h b/code/nel/include/nel/misc/time_nl.h
index 9e44b4b36..62161e304 100644
--- a/code/nel/include/nel/misc/time_nl.h
+++ b/code/nel/include/nel/misc/time_nl.h
@@ -86,7 +86,13 @@ public:
 	 * time that is the same on all computers.
 	 * \warning On Win32, the value is on 32 bits only. It wraps around to 0 every about 49.71 days.
 	 */
-	static TTime	getLocalTime ();
+	static TTime	getLocalTime();
+
+	/** Same as getLocalTime, but prefers high resolution timers.
+	 * Must call probe once in the beginning of the application before using, 
+	 * to ensure the correct settings are applied.
+	 */
+	static TTime	getLocalTimeHR();
 
 	/** Return the time in processor ticks. Use it for profile purpose.
 	 * If the performance time is not supported on this hardware, it returns 0.
diff --git a/code/nel/src/misc/time_nl.cpp b/code/nel/src/misc/time_nl.cpp
index 4a3586baa..11a920a79 100644
--- a/code/nel/src/misc/time_nl.cpp
+++ b/code/nel/src/misc/time_nl.cpp
@@ -37,6 +37,12 @@
 namespace NLMISC
 {
 
+namespace {
+#ifdef NL_OS_WINDOWS
+bool a_HaveQueryPerformance = false;
+#endif
+}
+
 void CTime::probeTimerInfo(CTime::CTimerInfo &result)
 {
 	breakable
@@ -65,6 +71,7 @@ void CTime::probeTimerInfo(CTime::CTimerInfo &result)
 			result.IsHighPrecisionAvailable = false;
 			result.HighPrecisionResolution = 1000;
 		}
+		a_HaveQueryPerformance = result.IsHighPrecisionAvailable;
 		if (!result.IsHighPrecisionAvailable)
 		{
 			lowResTime = timeGetTime();
@@ -292,6 +299,43 @@ TTime CTime::getLocalTime ()
 #endif
 }
 
+#ifdef NL_OS_WINDOWS
+namespace {
+struct CQPFProvider
+{
+	CQPFProvider()
+	{
+		QueryPerformanceFrequency(&Frequency);
+	}
+	LARGE_INTEGER Frequency;
+};
+CQPFProvider s_QPFProvider;
+}
+#endif
+
+/// Same as above but prefer high resolution timer
+TTime CTime::getLocalTimeHR()
+{
+#ifdef NL_OS_WINDOWS
+	if (a_HaveQueryPerformance)
+	{
+		// On a (fast) 15MHz timer this rolls over after 7000 days.
+		// If my calculations are right.
+		LARGE_INTEGER counter;
+		QueryPerformanceCounter(&counter);
+		counter.QuadPart *= 1000;
+		counter.QuadPart /= s_QPFProvider.Frequency.QuadPart;
+	}
+	else
+	{
+		// Use default reliable low resolution timer.
+		return getLocalTime();
+	}
+#else
+	// Other OS always use the best available high resolution timer.
+	return getLocalTime();
+#endif
+}
 
 /* Return the time in processor ticks. Use it for profile purpose.
  * If the performance time is not supported on this hardware, it returns 0.