mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 01:25:21 +00:00
68 lines
2.0 KiB
C++
68 lines
2.0 KiB
C++
#include <base/sleep.h>
|
|
|
|
#include <ctime>
|
|
#include <cerrno>
|
|
#include <system_error>
|
|
|
|
#if defined(OS_DARWIN)
|
|
#include <mach/mach.h>
|
|
#include <mach/mach_time.h>
|
|
#endif
|
|
|
|
/**
|
|
* Sleep with nanoseconds precision. Tolerant to signal interruptions
|
|
*
|
|
* In case query profiler is turned on, all threads spawned for
|
|
* query execution are repeatedly interrupted by signals from timer.
|
|
* Functions for relative sleep (sleep(3), nanosleep(2), etc.) have
|
|
* problems in this setup and man page for nanosleep(2) suggests
|
|
* using absolute deadlines, for instance clock_nanosleep(2).
|
|
*/
|
|
void sleepForNanoseconds(uint64_t nanoseconds)
|
|
{
|
|
#if defined(OS_DARWIN)
|
|
//https://developer.apple.com/library/archive/technotes/tn2169/_index.html
|
|
//https://dshil.github.io/blog/missed-os-x-clock-guide/
|
|
static mach_timebase_info_data_t timebase_info{};
|
|
if (timebase_info.denom == 0)
|
|
mach_timebase_info(&timebase_info);
|
|
|
|
uint64_t time_to_wait = nanoseconds * timebase_info.denom / timebase_info.numer;
|
|
uint64_t now = mach_absolute_time();
|
|
|
|
while (mach_wait_until(now + time_to_wait) != KERN_SUCCESS);
|
|
#else
|
|
constexpr auto clock_type = CLOCK_MONOTONIC;
|
|
|
|
struct timespec current_time;
|
|
if (0 != clock_gettime(clock_type, ¤t_time))
|
|
throw std::system_error(std::error_code(errno, std::system_category()));
|
|
|
|
constexpr uint64_t resolution = 1'000'000'000;
|
|
struct timespec finish_time = current_time;
|
|
|
|
finish_time.tv_nsec += nanoseconds % resolution;
|
|
const uint64_t extra_second = finish_time.tv_nsec / resolution;
|
|
finish_time.tv_nsec %= resolution;
|
|
|
|
finish_time.tv_sec += (nanoseconds / resolution) + extra_second;
|
|
|
|
while (clock_nanosleep(clock_type, TIMER_ABSTIME, &finish_time, nullptr) == EINTR);
|
|
#endif
|
|
}
|
|
|
|
void sleepForMicroseconds(uint64_t microseconds)
|
|
{
|
|
sleepForNanoseconds(microseconds * 1000);
|
|
}
|
|
|
|
void sleepForMilliseconds(uint64_t milliseconds)
|
|
{
|
|
sleepForMicroseconds(milliseconds * 1000);
|
|
}
|
|
|
|
void sleepForSeconds(uint64_t seconds)
|
|
{
|
|
sleepForMilliseconds(seconds * 1000);
|
|
}
|