This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 6 years ago.
I tried creating a Stopwatch struct whose purpose is to measure time using the Windows QueryPerformanceCounter() function, and if it does not exist or is not supported, it falls back to using clock() in time.h.
Unfortunately a Linker error is taking place as follows:
Error LNK2001: unresolved external symbol "private: static struct Stopwatch::StopwatchInitializer Stopwatch::platformInfo" (?platformInfo#Stopwatch##0UStopwatchInitializer#1#A) in Main.obj
When I change platformInfo to non-static, the application works, but if marked static, it doesn't.
My intention is to leave it static so that it is initialized only once, but the Linker is not cooperating.
Why is that? Here is my code:
StdAfx.h:
#pragma once
#include "time.h"
#ifdef _WIN32
#include "windows.h"
#endif
//A stopwatch function provider that offers clock tick accuracy
struct Stopwatch {
//holds the platform data required to initialize the stopwatch
private:
struct StopwatchInitializer {
public:
double nanosecondsPerTick;
bool isHighResolution;
StopwatchInitializer() {
#ifdef _WIN32
LARGE_INTEGER value;
isHighResolution = !!QueryPerformanceFrequency(&value);
nanosecondsPerTick = isHighResolution ? 1000000000.0 / value.QuadPart : 1000000000.0 / CLOCKS_PER_SEC;
#elif
isHighResolution = false;
nanosecondsPerTick = 1000000000.0 / CLOCKS_PER_SEC;
#endif
}
};
//static single instance of the StopwatchInitializer instance
//here is the error though
static const StopwatchInitializer platformInfo;
double startTimeStamp, elapsed;
bool isRunning;
public:
//Initializes the stopwatch.
Stopwatch() {
elapsed = 0.0;
startTimeStamp = 0.0;
isRunning = false;
}
//Initializes the stopwatch with the specified pre-elapsed ticks.
Stopwatch(double preElapsedTicks) {
elapsed = preElapsedTicks;
startTimeStamp = 0.0;
isRunning = false;
}
//Gets the current time in platform-specific ticks.
double getTimeStamp() {
#ifdef _WIN32
if (platformInfo.isHighResolution) {
LARGE_INTEGER num;
QueryPerformanceCounter(&num);
return (double) num.QuadPart;
} else
return (double) clock();
#elif
return (double) clock();
#endif
}
//Starts or resumes the stopwatch.
void start() {
if (isRunning)
return;
isRunning = true;
startTimeStamp = getTimeStamp();
}
//Stops the stopwatch.
void stop() {
if (isRunning) {
isRunning = false;
elapsed += getTimeStamp() - startTimeStamp;
}
}
//Gets whether the stopwatch is running
int getIsRunning() {
return isRunning;
}
//Sets whether the stopwatch is running (boolean value).
void setIsRunning(bool value) {
if (value)
start();
else
stop();
}
//Gets the current elapsed ticks.
double getElapsedTicks() {
return isRunning ? (elapsed - startTimeStamp) + getTimeStamp() : elapsed;
}
//Gets the elapsed time in fortnights.
double getElapsedFortnights() {
return (platformInfo.nanosecondsPerTick * 0.00000000000000082671957671957672) * getElapsedTicks();
}
//Gets the elapsed time in weeks.
double getElapsedWeeks() {
return (platformInfo.nanosecondsPerTick * 0.00000000000000165343915343915344) * getElapsedTicks();
}
//Gets the elapsed time in days.
double getElapsedDays() {
return (platformInfo.nanosecondsPerTick * 0.00000000000001157407407407407407) * getElapsedTicks();
}
//Gets the elapsed time in hours.
double getElapsedHours() {
return (platformInfo.nanosecondsPerTick * 0.00000000000027777777777777777777) * getElapsedTicks();
}
//Gets the elapsed time in minutes.
double getElapsedMinutes() {
return (platformInfo.nanosecondsPerTick * 0.00000000001666666666666666666666) * getElapsedTicks();
}
//Gets the elapsed time in seconds.
double getElapsedSeconds() {
return (platformInfo.nanosecondsPerTick * 0.000000001) * getElapsedTicks();
}
//Gets the elapsed time in milliseconds.
double getElapsedMilliseconds() {
return (platformInfo.nanosecondsPerTick * 0.000001) * getElapsedTicks();
}
//Gets the elapsed time in microseconds.
double getElapsedMicroseconds() {
return (platformInfo.nanosecondsPerTick * 0.001) * getElapsedTicks();
}
//Gets the elapsed time in nanoseconds.
double getElapsedNanoseconds() {
return platformInfo.nanosecondsPerTick * getElapsedTicks();
}
//Resets the elapsed time.
void reset() {
elapsed = 0.0;
isRunning = false;
startTimeStamp = 0.0;
}
//Resets the elapsed time to the specified platform-specific ticks.
void reset(double ticks) {
elapsed = ticks;
isRunning = false;
startTimeStamp = 0.0;
}
//Resets the stopwatch and restarts it.
void restart() {
elapsed = 0.0;
isRunning = true;
startTimeStamp = getTimeStamp();
}
//Resets the stopwatch to specified platform-specific ticks and restarts it.
void restart(double ticks) {
elapsed = ticks;
isRunning = true;
startTimeStamp = getTimeStamp();
}
//Converts nanoseconds to platform-specific ticks.
double convertToTicks(double nanoseconds) {
return nanoseconds / platformInfo.nanosecondsPerTick;
}
//Converts platform-specific ticks to nanoseconds.
double convertToNanoseconds(double ticks) {
return ticks * platformInfo.nanosecondsPerTick;
}
};
Main.h:
#include "stdafx.h"
#include "stdio.h"
//entry point
int main() {
Stopwatch stopwatch;
int x;
double value = 100002030.0;
stopwatch.start();
for (x = 0; x < 100000000; x++)
value /= 2.2;
printf("Division: %fms, value: %f", stopwatch.getElapsedMilliseconds(), value);
value = 100002030.0;
stopwatch.restart();
for (x = 0; x < 100000000; x++)
value *= 0.45454545454;
printf("\nMultiplication: %fms, value: %f", stopwatch.getElapsedMilliseconds(), value);
scanf_s("");
}
You declared static member platformInfo, but didn't define it, so the linker complains about it. To define this static member outside of the class, add this line at top-level of your source:
const Stopwatch::StopwatchInitializer Stopwatch::platformInfo;
Related
currently i am programming for an embedded application which reads values from sensors periodically. I want them to be read, every 20 ms.
Im using this tutorial
struct periodic_info {
int sig;
sigset_t alarm_sig;
};
static int make_periodic(int unsigned period, struct periodic_info *info)
{
static int next_sig;
int ret;
unsigned int ns;
unsigned int sec;
struct sigevent sigev;
timer_t timer_id;
struct itimerspec itval;
/* Initialise next_sig first time through. We can't use static
initialisation because SIGRTMIN is a function call, not a constant */
if (next_sig == 0)
next_sig = SIGRTMIN;
/* Check that we have not run out of signals */
if (next_sig > SIGRTMAX)
return -1;
info->sig = next_sig;
next_sig++;
/* Create the signal mask that will be used in wait_period */
sigemptyset(&(info->alarm_sig));
sigaddset(&(info->alarm_sig), info->sig);
/* Create a timer that will generate the signal we have chosen */
sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = info->sig;
sigev.sigev_value.sival_ptr = (void *)&timer_id;
ret = timer_create(CLOCK_MONOTONIC, &sigev, &timer_id);
if (ret == -1)
return ret;
/* Make the timer periodic */
sec = period / 1000000;
ns = (period - (sec * 1000000)) * 1000;
itval.it_interval.tv_sec = sec;
itval.it_interval.tv_nsec = ns;
itval.it_value.tv_sec = sec;
itval.it_value.tv_nsec = ns;
ret = timer_settime(timer_id, 0, &itval, NULL);
return ret;
}
static void wait_period(struct periodic_info *info)
{
int sig;
sigwait(&(info->alarm_sig), &sig);
}
static int thread_1_count;
The Main:
int main(){
pthread_t t_1;
pthread_t t_2;
sigset_t alarm_sig;
int i;
printf("Periodic threads using POSIX timers\n");
/* Block all real time signals so they can be used for the timers.
Note: this has to be done in main() before any threads are created
so they all inherit the same mask. Doing it later is subject to
race conditions */
sigemptyset(&alarm_sig);
for (i = SIGRTMIN; i <= SIGRTMAX; i++)
sigaddset(&alarm_sig, i);
sigprocmask(SIG_BLOCK, &alarm_sig, NULL);
pthread_create(&t_1, NULL, thread_1, NULL);
sleep(10);
printf("Thread 1 %d iterations\n", thread_1_count);
return 0;
My Problem now, i measured the time with high resolution clock with a period of 20ms.
static void *thread_1(void *arg)
{
struct periodic_info info;
printf("Thread 1 period 10ms\n");
make_periodic(20000, &info);
while (1) {
auto start = std::chrono::high_resolution_clock::now();
printf("Hello\n");
thread_1_count++;
wait_period(&info);
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> ms_double = finish - start;
std::cout << ms_double.count() << "ms\n";
}
return NULL;
}
The output i get ist:
...
19.8556ms
19.8587ms
19.8556ms
19.8543ms
19.8562ms
19.8809ms
19.7592ms
19.8381ms
19.8302ms
19.8437ms
...
So my Question, why is the Time shorter than my Period time, what am i doing wrong ?
To be more accurate, don't take time twice on each iteration, keep the last value, like this:
static void *thread_1(void *arg)
{
struct periodic_info info;
printf("Thread 1 period 10ms\n");
make_periodic(20000, &info);
auto start = std::chrono::high_resolution_clock::now();
while (1) {
wait_period(&info);
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> ms_double = finish - start;
std::cout << ms_double.count() << "ms\n";
start = finish;
}
return NULL;
}
This way, it will make the time measuring more accurate.
When I call QueryPerformanceCounter many times in a shot time, it gives me a wrong output. The code is working an amount of loop iteration, and at a point the QueryPerformanceCounter returns 2 consecutive different values.
Code:
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <math.h>
//timer (us)
double PCFreq = 0.0;
__int64 CounterStart = 0;
//prototypage
double micros(void);
void StartCounter(void);
int main()
{
StartCounter();
//initialisation time
printf("go\n");
for (long i = 0; i < 100000000; i += 1) {
double time_stamp1 = micros();
double time_stamp2 = micros();
if (fabs(time_stamp1 - time_stamp2) > 1000) {
printf("time_stamp1 : %lf\n", time_stamp1);
printf("time_stamp2 : %lf\n", time_stamp2);
printf("i : %ld\n", i);
break;
}
}
printf("finish\n");
}
void StartCounter() {
LARGE_INTEGER li;
if (!QueryPerformanceFrequency(&li)) {
printf("not initialized");
}
PCFreq = double(li.QuadPart) / 1000000.0;
QueryPerformanceCounter(&li);
CounterStart = li.QuadPart;
}
double micros() {
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return double(li.QuadPart - CounterStart) / PCFreq;
}
Unexpected output:
go
time_stamp1 : 709840.300000
time_stamp2 : 712229.000000
i : 5524494
finish
I've tried to use SDL_GetTimer() to make action after passing 1000ms using this piece of code:
while(1)
{
int tajmer;
int czas = SDL_GetTicks();
tajmer = SDL_GetTicks() - czas;
if(tajmer > 1000)
{
MoveUp();
czas = SDL_GetTicks();
}
}
But it causes my program to crash. Any ideas why, or how to implement simple timer correctly?
Every time the loop runs, czas is updated to the current time.
Solution: Move it out of the loop.
int czas = SDL_GetTicks();
while(1)
{
int tajmer;
tajmer = SDL_GetTicks() - czas;
if(tajmer > 1000)
{
MoveUp();
czas = SDL_GetTicks();
}
}
However what you are trying to accomplish could possibly be done in a better way using built in timers:
http://wiki.libsdl.org/SDL_AddTimer
Edit:
Example using SDL_AddTimer.
Uint32 my_callbackfunc(Uint32 interval, void *param);
int main() {
... // don't forget to SDL_Init
...
SDL_AddTimer(1000, my_callbackfunc, NULL);
...
}
Uint32 my_callbackfunc(Uint32 interval, void *param)
{
MoveUp();
return(1000); // or however long to wait before my_callbackfunc should run.
}
If you are currently using classes and want to call a class's method called MoveUp() then perhaps:
class example {
...
void start_moving() {
SDL_AddTimer(1000, my_callbackfunc, (void*)this);
}
...
public void MoveUp() {
...
}
}
Uint32 my_callbackfunc(Uint32 interval, void *param) {
((example*)param)->MoveUp();
return (1000);
}
Continuing on Yujin Wus answer you can also do something like this.
int timer = 0;
int ticks = SDL_GetTicks();
while(true)
{
timer += SDL_GetTicks() - ticks;
ticks = SDL_GetTicks();
if(timer >= 1000)
{
timer -= 1000;
MoveUp();
}
}
Or something like this
const int DELAY = 1000;
int timer = SDL_GetTicks() + DELAY;
while(true)
{
if(timer - SDL_GetTicks() <= 0)
{
timer += DELAY;
MoveUp();
}
}
I am new to C++ , I have a program in C++ written for Linux. I'm trying to convert it to Windows. The code I have is:
struct Timer
{
struct tms t[2];
void STARTTIME (void)
{
times(t);
}
void STOPTIME(void)
{
times(t+1);
}
double USERTIME(void)
{
return ((double)((t+1)->tms_utime - t->tms_utime))/((double)sysconf(_SC_CLK_TCK));
}
};
For tms_utime I find term QueryPerformanceCounter in Visual C++, but I cannot apply this.
For sysconf(_SC_CLK_TCK) I use CLOCKS_PER_SEC but I do not know how correct this is? What is the equivalent code for Windows?
Here is a drop-in replacement that returns the user time, rather than the elapsed time:
#include <windows.h>
struct Timer
{
ULONGLONG t[2];
void STARTTIME (void)
{
t[0] = getCurrentUserTime();
}
void STOPTIME(void)
{
t[1] = getCurrentUserTime();
}
double USERTIME(void)
{
return (t[1] - t[0]) / 1e7;
}
private:
// Return current user time in units of 100ns.
// See http://msdn.microsoft.com/en-us/library/ms683223
// for documentation on GetProcessTimes()
ULONGLONG getCurrentUserTime()
{
FILETIME ct, et, kt, ut;
GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut);
ULARGE_INTEGER t;
t.HighPart = ut.dwHighDateTime;
t.LowPart = ut.dwLowDateTime;
return t.QuadPart;
}
};
Here's a class I wrote that I always use
#ifndef HIGHPERFTIMER_H
#define HIGHPERFTIMER_H
#include <windows.h>
#include <stdio.h>
class StopWatch
{
LARGE_INTEGER freq, startTime, endTime, thisTime, lastTime ;
double fFreq ;
public:
double total_time ;
StopWatch()
{
QueryPerformanceFrequency( &freq ) ;
fFreq = (double)freq.QuadPart ;
total_time = 0 ;
printf( " --- The ffreq is %lf\n", fFreq ) ;
}
void start()
{
QueryPerformanceCounter( &startTime ) ;
thisTime = lastTime = startTime ;
total_time = 0.0 ; // start counter at 0 seconds
}
double stop()
{
QueryPerformanceCounter( &endTime ) ;
total_time = ( endTime.QuadPart - startTime.QuadPart ) / fFreq ;
return total_time ;
}
void update()
{
lastTime = thisTime ;
QueryPerformanceCounter( &thisTime ) ;
total_time += ( thisTime.QuadPart - lastTime.QuadPart ) / fFreq ;
}
} ;
#endif //HIGHPERFTIMER_H
Example usage:
int main()
{
StopWatch stopWatch ;
stopWatch.start() ;
///.. code..
stopWatch.stop() ;
printf( "Time elapsed: %f sec", stopWatch.total_time ) ;
}
This is (an untested, but logically correct) drop in replacement. The usertime function returns in second resolution (as a double) so you need to divide by the required resolution.
struct Timer
{
__int64 t[2];
void Start()
{
QueryPerformanceCounter((LARGE_INTEGER*)&t[0]);
}
void Stop()
{
QueryPerformanceCounter((LARGE_INTEGER*)&t[1]);
}
double usertime()
{
__int64 freq;
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
return (double(t[1] - t[0])) / freq;
}
};
I have the following code running on qnx momemntics.
#define BILLION 1000000000L;
struct timespec start_time;
struct timespec stop_time;
void start MyTestFunc() {
//Initialize the Test Start time
clock_gettime(CLOCK_REALTIME,&start_time)
// ... additonal code.
cout << "The exectuion time of func "<< calculateExecutionTime();
}
double calculateExecutionTime ()
{
clock_gettime(CLOCK_REALTIME,&stop_time);
double dSeconds = (stop_time.tv_sec - start_time.tv_sec);
double dNanoSeconds = (double)( stop_time.tv_nsec - start_time.tv_nsec ) / BILLION;
return dSeconds + dNanoSeconds;
}
Now i want to port above code to windows. can any one provide sample code.
Thanks!
You can implement a clock_gettime() replacement for windows as follows:
LARGE_INTEGER
getFILETIMEoffset()
{
SYSTEMTIME s;
FILETIME f;
LARGE_INTEGER t;
s.wYear = 1970;
s.wMonth = 1;
s.wDay = 1;
s.wHour = 0;
s.wMinute = 0;
s.wSecond = 0;
s.wMilliseconds = 0;
SystemTimeToFileTime(&s, &f);
t.QuadPart = f.dwHighDateTime;
t.QuadPart <<= 32;
t.QuadPart |= f.dwLowDateTime;
return (t);
}
int
clock_gettime(int X, struct timeval *tv)
{
LARGE_INTEGER t;
FILETIME f;
double microseconds;
static LARGE_INTEGER offset;
static double frequencyToMicroseconds;
static int initialized = 0;
static BOOL usePerformanceCounter = 0;
if (!initialized) {
LARGE_INTEGER performanceFrequency;
initialized = 1;
usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
if (usePerformanceCounter) {
QueryPerformanceCounter(&offset);
frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.;
} else {
offset = getFILETIMEoffset();
frequencyToMicroseconds = 10.;
}
}
if (usePerformanceCounter) QueryPerformanceCounter(&t);
else {
GetSystemTimeAsFileTime(&f);
t.QuadPart = f.dwHighDateTime;
t.QuadPart <<= 32;
t.QuadPart |= f.dwLowDateTime;
}
t.QuadPart -= offset.QuadPart;
microseconds = (double)t.QuadPart / frequencyToMicroseconds;
t.QuadPart = microseconds;
tv->tv_sec = t.QuadPart / 1000000;
tv->tv_usec = t.QuadPart % 1000000;
return (0);
}
Avoiding PerformanceCounter mess, simple code:
struct timespec { long tv_sec; long tv_nsec; }; //header part
int clock_gettime(int, struct timespec *spec) //C-file part
{ __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime);
wintime -=116444736000000000i64; //1jan1601 to 1jan1970
spec->tv_sec =wintime / 10000000i64; //seconds
spec->tv_nsec =wintime % 10000000i64 *100; //nano-seconds
return 0;
}
...is fast, reliable and correct porting solution with impressive 100ns precision (1ms/10000).
And QPC-based solution which precision will be possibly (on some hw) even better is:
struct timespec { long tv_sec; long tv_nsec; }; //header part
#define exp7 10000000i64 //1E+7 //C-file part
#define exp9 1000000000i64 //1E+9
#define w2ux 116444736000000000i64 //1.jan1601 to 1.jan1970
void unix_time(struct timespec *spec)
{ __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime);
wintime -=w2ux; spec->tv_sec =wintime / exp7;
spec->tv_nsec =wintime % exp7 *100;
}
int clock_gettime(int, timespec *spec)
{ static struct timespec startspec; static double ticks2nano;
static __int64 startticks, tps =0; __int64 tmp, curticks;
QueryPerformanceFrequency((LARGE_INTEGER*)&tmp); //some strange system can
if (tps !=tmp) { tps =tmp; //init ~~ONCE //possibly change freq ?
QueryPerformanceCounter((LARGE_INTEGER*)&startticks);
unix_time(&startspec); ticks2nano =(double)exp9 / tps; }
QueryPerformanceCounter((LARGE_INTEGER*)&curticks); curticks -=startticks;
spec->tv_sec =startspec.tv_sec + (curticks / tps);
spec->tv_nsec =startspec.tv_nsec + (double)(curticks % tps) * ticks2nano;
if (!(spec->tv_nsec < exp9)) { spec->tv_sec++; spec->tv_nsec -=exp9; }
return 0;
}
My improved version of clock_gettime() using QueryPerformanceCounter().
#define BILLION (1E9)
static BOOL g_first_time = 1;
static LARGE_INTEGER g_counts_per_sec;
int clock_gettime(int dummy, struct timespec *ct)
{
LARGE_INTEGER count;
if (g_first_time)
{
g_first_time = 0;
if (0 == QueryPerformanceFrequency(&g_counts_per_sec))
{
g_counts_per_sec.QuadPart = 0;
}
}
if ((NULL == ct) || (g_counts_per_sec.QuadPart <= 0) ||
(0 == QueryPerformanceCounter(&count)))
{
return -1;
}
ct->tv_sec = count.QuadPart / g_counts_per_sec.QuadPart;
ct->tv_nsec = ((count.QuadPart % g_counts_per_sec.QuadPart) * BILLION) / g_counts_per_sec.QuadPart;
return 0;
}
I think my version is an improvement over the currently accepted answer using QueryPerformanceCounter(), because -
More robust - checks return values of functions, also value returned in pass-by-reference variable.
More robust - checks validity of input parameter.
More streamlined - Uses as few as necessary number of variables (3 vs 7).
More streamlined - Avoids the code-path involving GetSystemTimeAsFileTime() since QueryPerformanceFrequency() and QueryPerformanceCounter() are guaranteed to work on systems that run Windows XP or later.
A full-featured and fully-tested implementation of clock_gettime() has been in mingw-w64 for many years now. You'll have to use a toolchain with mingw64/msys2 to use this, with header #include <time.h> (on windows). If you're writing a codebase that's portable between linux and windows, and you can't find clock_gettime() in <time.h> for your linux builds 3, I'd suggest you try #include <pthread_time.h>, compiling with -pthread, or linking with -lrt.
See also question 60020968 for Windows builds; and 33846055, 538609 for your Linux builds.
I needed monotonic and realtime.
For monotonic, I just take the perf counter since a wall clock baseline is meaningless.
#define MS_PER_SEC 1000ULL // MS = milliseconds
#define US_PER_MS 1000ULL // US = microseconds
#define HNS_PER_US 10ULL // HNS = hundred-nanoseconds (e.g., 1 hns = 100 ns)
#define NS_PER_US 1000ULL
#define HNS_PER_SEC (MS_PER_SEC * US_PER_MS * HNS_PER_US)
#define NS_PER_HNS (100ULL) // NS = nanoseconds
#define NS_PER_SEC (MS_PER_SEC * US_PER_MS * NS_PER_US)
int clock_gettime_monotonic(struct timespec *tv)
{
static LARGE_INTEGER ticksPerSec;
LARGE_INTEGER ticks;
if (!ticksPerSec.QuadPart) {
QueryPerformanceFrequency(&ticksPerSec);
if (!ticksPerSec.QuadPart) {
errno = ENOTSUP;
return -1;
}
}
QueryPerformanceCounter(&ticks);
tv->tv_sec = (long)(ticks.QuadPart / ticksPerSec.QuadPart);
tv->tv_nsec = (long)(((ticks.QuadPart % ticksPerSec.QuadPart) * NS_PER_SEC) / ticksPerSec.QuadPart);
return 0;
}
and wall clock, based on GMT unlike the tempting and similar _ftime() function.
int clock_gettime_realtime(struct timespec *tv)
{
FILETIME ft;
ULARGE_INTEGER hnsTime;
GetSystemTimePreciseAsFileTime(&ft);
hnsTime.LowPart = ft.dwLowDateTime;
hnsTime.HighPart = ft.dwHighDateTime;
// To get POSIX Epoch as baseline, subtract the number of hns intervals from Jan 1, 1601 to Jan 1, 1970.
hnsTime.QuadPart -= (11644473600ULL * HNS_PER_SEC);
// modulus by hns intervals per second first, then convert to ns, as not to lose resolution
tv->tv_nsec = (long) ((hnsTime.QuadPart % HNS_PER_SEC) * NS_PER_HNS);
tv->tv_sec = (long) (hnsTime.QuadPart / HNS_PER_SEC);
return 0;
}
And then the POSIX compatible function... see POSIX header for typedef and macros.
int clock_gettime(clockid_t type, struct timespec *tp)
{
if (type == CLOCK_MONOTONIC)
{
return clock_gettime_monotonic(tp);
}
else if (type == CLOCK_REALTIME)
{
return clock_gettime_realtime(tp);
}
errno = ENOTSUP;
return -1;
}
You can use timespec_get to implement simple clock_gettime.
(timespec_get function is available since C11)
int clock_gettime(int, struct timespec *tv)
{
return timespec_get(tv, TIME_UTC);
}
... but result timespec has about 10 milisec resolution on my windows7 64bit machine. :(
Here is my version of clock_gettime.
int clock_gettime(int, struct timespec *tv)
{
static int initialized = 0;
static LARGE_INTEGER freq, startCount;
static struct timespec tv_start;
LARGE_INTEGER curCount;
time_t sec_part;
long nsec_part;
if (!initialized) {
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&startCount);
timespec_get(&tv_start, TIME_UTC);
initialized = 1;
}
QueryPerformanceCounter(&curCount);
curCount.QuadPart -= startCount.QuadPart;
sec_part = curCount.QuadPart / freq.QuadPart;
nsec_part = (long)((curCount.QuadPart - (sec_part * freq.QuadPart))
* 1000000000UL / freq.QuadPart);
tv->tv_sec = tv_start.tv_sec + sec_part;
tv->tv_nsec = tv_start.tv_nsec + nsec_part;
if(tv->tv_nsec >= 1000000000UL) {
tv->tv_sec += 1;
tv->tv_nsec -= 1000000000UL;
}
return 0;
}