// #include #include #include #include #include #include "Exception.hpp" #include "Time.hpp" #include "Assert.hpp" std::ostream& operator<<(std::ostream& out, Duration d) { if (d.ns < 1'000) { out << d.ns << "ns"; } else if (d.ns < 1'000'000) { out << d.ns/1'000 << "." << d.ns%1'000 << "us"; } else if (d.ns < 1'000'000'000) { out << d.ns/1'000'000 << "." << d.ns%1'000'000 << "ms"; } else if (d.ns < 1'000'000'000ull*60) { out << d.ns/1'000'000'000 << "." << d.ns%1'000'000'000 << "s"; } else if (d.ns < 1'000'000'000ull*60*60) { out << d.ns/(1'000'000'000ull*60) << "." << d.ns%(1'000'000'000ull*60) << "m"; } else { out << d.ns/(1'000'000'000ull*60*60) << "." << d.ns%(1'000'000'000ull*60*60) << "h"; } return out; } __attribute__((constructor)) static void checkClockRes() { struct timespec ts; if (clock_getres(CLOCK_REALTIME, &ts) != 0) { throw SYSCALL_EXCEPTION("clock_getres"); } if (ts.tv_sec != 0 || ts.tv_nsec != 1) { throw EGGS_EXCEPTION("expected nanosecond precisions, got %s,%s", ts.tv_sec, ts.tv_nsec); } } EggsTime eggsNow() { struct timespec now; if (clock_gettime(CLOCK_REALTIME, &now) != 0) { throw SYSCALL_EXCEPTION("clock_gettime"); } return EggsTime(((uint64_t)now.tv_nsec + ((uint64_t)now.tv_sec * 1'000'000'000ull))); } std::ostream& operator<<(std::ostream& out, EggsTime eggst) { time_t secs = eggst.ns / 1'000'000'000ull; uint64_t nsecs = eggst.ns % 1'000'000'000ull; struct tm tm; if (gmtime_r(&secs, &tm) == nullptr) { throw SYSCALL_EXCEPTION("gmtime_r"); } // "2006-01-02T15:04:05.999999999" char buf[31]; ALWAYS_ASSERT(strftime(buf, 29, "%Y-%m-%dT%H:%M:%S.", &tm) == 20); ALWAYS_ASSERT(snprintf(buf+20, 10, "%09lu", nsecs) == 9); buf[30] = '\0'; out << buf; return out; } void sleepFor(Duration dt) { std::this_thread::sleep_for(std::chrono::nanoseconds(dt.ns)); }