timekeeper.h 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. #pragma once
  2. #include <util/datetime/base.h>
  3. #include <util/generic/singleton.h>
  4. #include <util/string/cast.h>
  5. #include <util/system/thread.h>
  6. #include <util/system/event.h>
  7. #include <util/system/env.h>
  8. #include <cstdlib>
  9. /* Keeps current time accurate up to 1/10 second */
  10. class TTimeKeeper {
  11. public:
  12. static TInstant GetNow(void) {
  13. return TInstant::MicroSeconds(GetTime());
  14. }
  15. static time_t GetTime(void) {
  16. return Singleton<TTimeKeeper>()->CurrentTime.tv_sec;
  17. }
  18. static const struct timeval& GetTimeval(void) {
  19. return Singleton<TTimeKeeper>()->CurrentTime;
  20. }
  21. TTimeKeeper()
  22. : Thread(&TTimeKeeper::Worker, this)
  23. {
  24. ConstTime = !!GetEnv("TEST_TIME");
  25. if (ConstTime) {
  26. try {
  27. CurrentTime.tv_sec = FromString<ui32>(GetEnv("TEST_TIME"));
  28. } catch (TFromStringException exc) {
  29. ConstTime = false;
  30. }
  31. }
  32. if (!ConstTime) {
  33. gettimeofday(&CurrentTime, nullptr);
  34. Thread.Start();
  35. }
  36. }
  37. ~TTimeKeeper() {
  38. if (!ConstTime) {
  39. Exit.Signal();
  40. Thread.Join();
  41. }
  42. }
  43. private:
  44. static const ui32 UpdateInterval = 100000;
  45. struct timeval CurrentTime;
  46. bool ConstTime;
  47. TSystemEvent Exit;
  48. TThread Thread;
  49. static void* Worker(void* arg) {
  50. TTimeKeeper* owner = static_cast<TTimeKeeper*>(arg);
  51. do {
  52. /* Race condition may occur here but locking looks too expensive */
  53. gettimeofday(&owner->CurrentTime, nullptr);
  54. } while (!owner->Exit.WaitT(TDuration::MicroSeconds(UpdateInterval)));
  55. return nullptr;
  56. }
  57. };