142 lines
3.4 KiB
C
142 lines
3.4 KiB
C
#ifndef TREE_SITTER_CLOCK_H_
|
|
#define TREE_SITTER_CLOCK_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
typedef uint64_t TSDuration;
|
|
|
|
#ifdef _WIN32
|
|
|
|
// Windows:
|
|
// * Represent a time as a performance counter value.
|
|
// * Represent a duration as a number of performance counter ticks.
|
|
|
|
#include <windows.h>
|
|
typedef uint64_t TSClock;
|
|
|
|
static inline TSDuration duration_from_micros(uint64_t micros) {
|
|
LARGE_INTEGER frequency;
|
|
QueryPerformanceFrequency(&frequency);
|
|
return micros * (uint64_t)frequency.QuadPart / 1000000;
|
|
}
|
|
|
|
static inline uint64_t duration_to_micros(TSDuration self) {
|
|
LARGE_INTEGER frequency;
|
|
QueryPerformanceFrequency(&frequency);
|
|
return self * 1000000 / (uint64_t)frequency.QuadPart;
|
|
}
|
|
|
|
static inline TSClock clock_null(void) {
|
|
return 0;
|
|
}
|
|
|
|
static inline TSClock clock_now(void) {
|
|
LARGE_INTEGER result;
|
|
QueryPerformanceCounter(&result);
|
|
return (uint64_t)result.QuadPart;
|
|
}
|
|
|
|
static inline TSClock clock_after(TSClock base, TSDuration duration) {
|
|
return base + duration;
|
|
}
|
|
|
|
static inline bool clock_is_null(TSClock self) {
|
|
return !self;
|
|
}
|
|
|
|
static inline bool clock_is_gt(TSClock self, TSClock other) {
|
|
return self > other;
|
|
}
|
|
|
|
#elif defined(CLOCK_MONOTONIC) && !defined(__APPLE__)
|
|
|
|
// POSIX with monotonic clock support (Linux)
|
|
// * Represent a time as a monotonic (seconds, nanoseconds) pair.
|
|
// * Represent a duration as a number of microseconds.
|
|
//
|
|
// On these platforms, parse timeouts will correspond accurately to
|
|
// real time, regardless of what other processes are running.
|
|
|
|
#include <time.h>
|
|
typedef struct timespec TSClock;
|
|
|
|
static inline TSDuration duration_from_micros(uint64_t micros) {
|
|
return micros;
|
|
}
|
|
|
|
static inline uint64_t duration_to_micros(TSDuration self) {
|
|
return self;
|
|
}
|
|
|
|
static inline TSClock clock_now(void) {
|
|
TSClock result;
|
|
clock_gettime(CLOCK_MONOTONIC, &result);
|
|
return result;
|
|
}
|
|
|
|
static inline TSClock clock_null(void) {
|
|
return (TSClock) {0, 0};
|
|
}
|
|
|
|
static inline TSClock clock_after(TSClock base, TSDuration duration) {
|
|
TSClock result = base;
|
|
result.tv_sec += duration / 1000000;
|
|
result.tv_nsec += (duration % 1000000) * 1000;
|
|
return result;
|
|
}
|
|
|
|
static inline bool clock_is_null(TSClock self) {
|
|
return !self.tv_sec;
|
|
}
|
|
|
|
static inline bool clock_is_gt(TSClock self, TSClock other) {
|
|
if (self.tv_sec > other.tv_sec) return true;
|
|
if (self.tv_sec < other.tv_sec) return false;
|
|
return self.tv_nsec > other.tv_nsec;
|
|
}
|
|
|
|
#else
|
|
|
|
// macOS or POSIX without monotonic clock support
|
|
// * Represent a time as a process clock value.
|
|
// * Represent a duration as a number of process clock ticks.
|
|
//
|
|
// On these platforms, parse timeouts may be affected by other processes,
|
|
// which is not ideal, but is better than using a non-monotonic time API
|
|
// like `gettimeofday`.
|
|
|
|
#include <time.h>
|
|
typedef uint64_t TSClock;
|
|
|
|
static inline TSDuration duration_from_micros(uint64_t micros) {
|
|
return micros * (uint64_t)CLOCKS_PER_SEC / 1000000;
|
|
}
|
|
|
|
static inline uint64_t duration_to_micros(TSDuration self) {
|
|
return self * 1000000 / (uint64_t)CLOCKS_PER_SEC;
|
|
}
|
|
|
|
static inline TSClock clock_null(void) {
|
|
return 0;
|
|
}
|
|
|
|
static inline TSClock clock_now(void) {
|
|
return (uint64_t)clock();
|
|
}
|
|
|
|
static inline TSClock clock_after(TSClock base, TSDuration duration) {
|
|
return base + duration;
|
|
}
|
|
|
|
static inline bool clock_is_null(TSClock self) {
|
|
return !self;
|
|
}
|
|
|
|
static inline bool clock_is_gt(TSClock self, TSClock other) {
|
|
return self > other;
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif // TREE_SITTER_CLOCK_H_
|