BTW, here is a nice clock_gettime() replacement that Jeremy wrote up:
<https://github.com/macports/macports-ports/blob/master/graphics/cogl/files/patch-clock_gettime.diff>
Thanks. That is a bit better than what I cooked up for xrootd. I might
replace it ;)
Actually, I take that back. I am not convinced the implementation in the
above link is giving results consistent with the method it is supposed
to be provide. See the attached example test code...
test1 is the output from clock_gettime(CLOCK_REALTIME, &ts);, whether
that be from the system ( 10.12+) or from the link above (older).
test2 is my own workaround.
One 10.12 I get
> ./mac1013.exe
time1 1540311943653502000
time2 1540311943653580000
time1 1540311943653606000
time2 1540311943653619000
so the two give the same times (note time of course moves on between
each call, but the two clearly agree).
on 10.9 though I get
> ./mac109.exe
time1 1156992536990
time2 1540311478974454000
time1 1156992628574
time2 1540311478974495000
see how the values of time2 agree, but time1 (now from Jeremy's
implementation) clearly has a completely different scale.
Not sure why, but for sure its not quite a drop in replacement...
Chris
#include <iostream>
#include <cstdint>
#include <sys/time.h>
#include <time.h>
#include <mach/clock.h>
#include <mach/mach.h>
static std::uint64_t kSecondsToNanos = 1000ULL * 1000ULL * 1000ULL;
#if __APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200
#include <mach/mach_time.h>
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 0
#endif
static int
clock_gettime(int clk_id, struct timespec *t)
{
mach_timebase_info_data_t timebase;
mach_timebase_info(&timebase);
const std::uint64_t time = mach_absolute_time();
const double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
const double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
t->tv_sec = seconds;
t->tv_nsec = nseconds;
return 0;
}
#else
#include <time.h>
#endif
std::uint64_t time1()
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return (static_cast<std::uint64_t>(ts.tv_sec) * kSecondsToNanos +
static_cast<std::uint64_t>(ts.tv_nsec));
}
std::uint64_t time2()
{
struct timespec ts;
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = ( mts.tv_nsec / 1000 ) * 1000;
return (static_cast<std::uint64_t>(ts.tv_sec) * kSecondsToNanos +
static_cast<std::uint64_t>(ts.tv_nsec));
}
int main()
{
int c(0);
while ( ++c < 10 )
{
std::cout << "time1 " << time1() << std::endl;
std::cout << "time2 " << time2() << std::endl;
//#ifdef CLOCK_REALTIME
//std::cout << "time1 " << time1() << std::endl;
//#else
//std::cout << "time2 " << time2() << std::endl;
//#endif
}
return 0;
}