199 lines
4.2 KiB
Plaintext
199 lines
4.2 KiB
Plaintext
|
|
#ifndef CTL_NANO_TIMER_H
|
||
|
|
#define CTL_NANO_TIMER_H
|
||
|
|
|
||
|
|
#define CTL_NOEXCEPT throw()
|
||
|
|
#if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
|
||
|
|
#if _MSC_VER >= 1900
|
||
|
|
#undef CTL_NOEXCEPT
|
||
|
|
#define CTL_NOEXCEPT noexcept
|
||
|
|
#endif
|
||
|
|
#elif defined(__cplusplus) && __cplusplus >= 201103L
|
||
|
|
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__clang__) // If compiler is GCC/G++
|
||
|
|
#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4
|
||
|
|
#undef CTL_NOEXCEPT
|
||
|
|
#define CTL_NOEXCEPT noexcept
|
||
|
|
#endif
|
||
|
|
#elif defined(__clang__)
|
||
|
|
#if __has_feature(cxx_noexcept)
|
||
|
|
#undef CTL_NOEXCEPT
|
||
|
|
#define CTL_NOEXCEPT noexcept
|
||
|
|
#endif
|
||
|
|
#else // Assume type traits and initializer support for other compilers and standard libraries
|
||
|
|
#undef CTL_NOEXCEPT
|
||
|
|
#define CTL_NOEXCEPT noexcept
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
#if defined(__MACH__)
|
||
|
|
#include <mach/clock.h>
|
||
|
|
#include <mach/mach.h>
|
||
|
|
|
||
|
|
namespace CTL
|
||
|
|
{
|
||
|
|
|
||
|
|
class nanotimer
|
||
|
|
{
|
||
|
|
private:
|
||
|
|
clock_serv_t system_clock;
|
||
|
|
mach_timespec_t time1, time2;
|
||
|
|
public:
|
||
|
|
nanotimer() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &system_clock);
|
||
|
|
}
|
||
|
|
|
||
|
|
~nanotimer() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
mach_port_deallocate(mach_task_self(), system_clock);
|
||
|
|
}
|
||
|
|
|
||
|
|
void start() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
clock_get_time(system_clock, &time1);
|
||
|
|
}
|
||
|
|
|
||
|
|
double get_elapsed_ms() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
return static_cast<double>(get_elapsed_ns()) / 1000000.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
double get_elapsed_us() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
return static_cast<double>(get_elapsed_ns()) / 1000.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
double get_elapsed_ns() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
clock_get_time(system_clock, &time2);
|
||
|
|
return ((1000000000.0 * static_cast<double>(time2.tv_sec - time1.tv_sec)) + static_cast<double>(time2.tv_nsec - time1.tv_nsec));
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
// Linux/BSD implementation:
|
||
|
|
#elif (defined(linux) || defined(__linux__) || defined(__linux)) || (defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) || defined(__OHOS__)
|
||
|
|
#include <time.h>
|
||
|
|
#include <sys/time.h>
|
||
|
|
|
||
|
|
namespace CTL
|
||
|
|
{
|
||
|
|
|
||
|
|
class nanotimer
|
||
|
|
{
|
||
|
|
private:
|
||
|
|
struct timespec time1, time2;
|
||
|
|
public:
|
||
|
|
nanotimer() CTL_NOEXCEPT {}
|
||
|
|
|
||
|
|
void start() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
clock_gettime(CLOCK_MONOTONIC, &time1);
|
||
|
|
}
|
||
|
|
|
||
|
|
double get_elapsed_ms() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
return get_elapsed_ns() / 1000000.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
double get_elapsed_us() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
return get_elapsed_ns() / 1000.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
double get_elapsed_ns() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
clock_gettime(CLOCK_MONOTONIC, &time2);
|
||
|
|
return ((1000000000.0 * static_cast<double>(time2.tv_sec - time1.tv_sec)) + static_cast<double>(time2.tv_nsec - time1.tv_nsec));
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
// Windows implementation:
|
||
|
|
#elif defined(_WIN32)
|
||
|
|
#if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__) && !defined(NOMINMAX)
|
||
|
|
#define NOMINMAX // Otherwise MS compilers act like idiots when using std::numeric_limits<>::max() and including windows.h
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
||
|
|
#define WIN32_LEAN_AND_MEAN
|
||
|
|
#include <windows.h>
|
||
|
|
#undef WIN32_LEAN_AND_MEAN
|
||
|
|
#else
|
||
|
|
#include <windows.h>
|
||
|
|
#endif
|
||
|
|
|
||
|
|
namespace CTL
|
||
|
|
{
|
||
|
|
|
||
|
|
class nanotimer
|
||
|
|
{
|
||
|
|
private:
|
||
|
|
LARGE_INTEGER ticks1, ticks2;
|
||
|
|
double frequency;
|
||
|
|
public:
|
||
|
|
nanotimer() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
LARGE_INTEGER freq;
|
||
|
|
QueryPerformanceFrequency(&freq);
|
||
|
|
frequency = static_cast<double>(freq.QuadPart);
|
||
|
|
}
|
||
|
|
|
||
|
|
void start() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
QueryPerformanceCounter(&ticks1);
|
||
|
|
}
|
||
|
|
|
||
|
|
double get_elapsed_ms() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
QueryPerformanceCounter(&ticks2);
|
||
|
|
return (static_cast<double>(ticks2.QuadPart - ticks1.QuadPart) * 1000.0) / frequency;
|
||
|
|
}
|
||
|
|
|
||
|
|
double get_elapsed_us() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
return get_elapsed_ms() * 1000.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
double get_elapsed_ns() CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
return get_elapsed_ms() * 1000000.0;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
#if defined(__MACH__) || (defined(linux) || defined(__linux__) || defined(__linux)) || (defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) || defined(_WIN32) || defined(__OHOS__)
|
||
|
|
inline void nanosecond_delay(const double delay_ns) CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
nanotimer timer;
|
||
|
|
timer.start();
|
||
|
|
|
||
|
|
while(timer.get_elapsed_ns() < delay_ns)
|
||
|
|
{};
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
inline void microsecond_delay(const double delay_us) CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
nanosecond_delay(delay_us * 1000.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
inline void millisecond_delay(const double delay_ms) CTL_NOEXCEPT
|
||
|
|
{
|
||
|
|
nanosecond_delay(delay_ms * 1000000.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#undef CTL_NOEXCEPT
|
||
|
|
|
||
|
|
#endif
|