From 3a895e313b91bd8b23bab81d45efce63ca47cde7 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 27 Oct 2019 22:51:43 +0100 Subject: [PATCH] Fix compilation error on MSVC. Based on code that I wrote for gnulib. --- src/base/random/cl_random_from.cc | 18 +++++++++---- src/timing/cl_t_current.cc | 43 +++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/base/random/cl_random_from.cc b/src/base/random/cl_random_from.cc index 3614cc3..d187f47 100644 --- a/src/base/random/cl_random_from.cc +++ b/src/base/random/cl_random_from.cc @@ -62,15 +62,23 @@ inline uint32 get_seed (void) #endif #elif defined(_WIN32) && !defined(__CYGWIN__) -#include -#include + +/* included above. */ namespace cln { inline uint32 get_seed (void) { - struct timeb timebuf; - ftime(&timebuf); - return highlow32(timebuf.time, (long)(timebuf.millitm)*1000); + FILETIME current_time; + + GetSystemTimeAsFileTime (¤t_time); + + /* Convert from FILETIME to 'struct timeval'. */ + /* FILETIME: */ + ULONGLONG since_1601 = + ((ULONGLONG) current_time.dwHighDateTime << 32) + | (ULONGLONG) current_time.dwLowDateTime; + /* Divide by 20 ms, and take the low-order 32 bits. */ + return (ULONG) (since_1601 / 2000000); } } // namespace cln diff --git a/src/timing/cl_t_current.cc b/src/timing/cl_t_current.cc index aa5d3b1..6800e39 100644 --- a/src/timing/cl_t_current.cc +++ b/src/timing/cl_t_current.cc @@ -1,5 +1,9 @@ // cl_current_time(). +#if defined(_WIN32) && !defined(__CYGWIN__) +#include // For GetSystemTimeAsFileTime(), must be included first, sorry. +#endif + // General includes. #include "base/cl_sysdep.h" @@ -19,6 +23,8 @@ #else extern "C" int gettimeofday (struct timeval * tp, GETTIMEOFDAY_TZP_T tzp); #endif +#elif defined(_WIN32) && !defined(__CYGWIN__) + /* included above. */ #else #include #endif @@ -42,6 +48,43 @@ const cl_timespec cl_current_time () return cl_timespec(tv.tv_sec, tv.tv_usec * (1000000000/1000000) ); +#elif defined(_WIN32) && !defined(__CYGWIN__) + + /* GetSystemTimePreciseAsFileTime was introduced only in Windows 8. */ + typedef void (WINAPI * GetSystemTimePreciseAsFileTimeFuncType) (FILETIME *lpTime); + static GetSystemTimePreciseAsFileTimeFuncType GetSystemTimePreciseAsFileTimeFunc = NULL; + static BOOL initialized = FALSE; + + if (!initialized) { + HMODULE kernel32 = LoadLibrary ("kernel32.dll"); + if (kernel32 != NULL) { + GetSystemTimePreciseAsFileTimeFunc = + (GetSystemTimePreciseAsFileTimeFuncType) (void *) GetProcAddress (kernel32, "GetSystemTimePreciseAsFileTime"); + } + initialized = TRUE; + } + + FILETIME current_time; + + if (GetSystemTimePreciseAsFileTimeFunc != NULL) + GetSystemTimePreciseAsFileTimeFunc (¤t_time); + else + GetSystemTimeAsFileTime (¤t_time); + + /* Convert from FILETIME to 'struct timeval'. */ + /* FILETIME: */ + ULONGLONG since_1601 = + ((ULONGLONG) current_time.dwHighDateTime << 32) + | (ULONGLONG) current_time.dwLowDateTime; + /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89 leap + years, in total 134774 days. */ + ULONGLONG since_1970 = + since_1601 - (ULONGLONG) 134774 * (ULONGLONG) 86400 * (ULONGLONG) 10000000; + ULONGLONG microseconds_since_1970 = since_1970 / (ULONGLONG) 10; + return cl_timespec(microseconds_since_1970 / (ULONGLONG) 1000000, + (microseconds_since_1970 % (ULONGLONG) 1000000) * (1000000000/1000000) + ); + #else return cl_timespec(time(NULL),0); #endif -- 2.49.0