Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/common/event/timer_impl.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include <chrono>
4
5
#include "envoy/event/timer.h"
6
7
#include "source/common/common/scope_tracker.h"
8
#include "source/common/common/utility.h"
9
#include "source/common/event/event_impl_base.h"
10
#include "source/common/event/libevent.h"
11
12
namespace Envoy {
13
namespace Event {
14
15
/**
16
 * Utility helper functions for Timer implementation.
17
 */
18
class TimerUtils {
19
public:
20
  /**
21
   * Intended for consumption by enable(HR)Timer, this method is templated method to avoid implicit
22
   * duration conversions for its input arguments. This lets us have an opportunity to check bounds
23
   * before doing any conversions. When the passed in duration exceeds INT32_MAX max seconds, the
24
   * output will be clipped to yield INT32_MAX seconds and 0 microseconds for the
25
   * output argument. We clip to INT32_MAX to guard against overflowing the timeval structure.
26
   * ENVOY_BUGs if the duration is negative.
27
   * @tparam Duration std::chrono duration type, e.g. seconds, milliseconds, ...
28
   * @param d duration value
29
   * @param tv output parameter that will be updated
30
   */
31
68.7k
  template <typename Duration> static void durationToTimeval(const Duration& d, timeval& tv) {
32
68.7k
    if (d.count() < 0) {
33
0
      IS_ENVOY_BUG(fmt::format("Negative duration passed to durationToTimeval(): {}", d.count()));
34
0
      tv.tv_sec = 0;
35
0
      tv.tv_usec = 500000;
36
0
      return;
37
68.7k
    };
38
68.7k
    constexpr int64_t clip_to = INT32_MAX; // 136.102208 years
39
68.7k
    auto secs = std::chrono::duration_cast<std::chrono::seconds>(d);
40
68.7k
    if (secs.count() > clip_to) {
41
0
      tv.tv_sec = clip_to;
42
0
      tv.tv_usec = 0;
43
0
      return;
44
0
    }
45
46
68.7k
    auto usecs = std::chrono::duration_cast<std::chrono::microseconds>(d - secs);
47
68.7k
    tv.tv_sec = secs.count();
48
68.7k
    tv.tv_usec = usecs.count();
49
68.7k
  }
void Envoy::Event::TimerUtils::durationToTimeval<std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l> > >(std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l> > const&, timeval&)
Line
Count
Source
31
66.4k
  template <typename Duration> static void durationToTimeval(const Duration& d, timeval& tv) {
32
66.4k
    if (d.count() < 0) {
33
0
      IS_ENVOY_BUG(fmt::format("Negative duration passed to durationToTimeval(): {}", d.count()));
34
0
      tv.tv_sec = 0;
35
0
      tv.tv_usec = 500000;
36
0
      return;
37
66.4k
    };
38
66.4k
    constexpr int64_t clip_to = INT32_MAX; // 136.102208 years
39
66.4k
    auto secs = std::chrono::duration_cast<std::chrono::seconds>(d);
40
66.4k
    if (secs.count() > clip_to) {
41
0
      tv.tv_sec = clip_to;
42
0
      tv.tv_usec = 0;
43
0
      return;
44
0
    }
45
46
66.4k
    auto usecs = std::chrono::duration_cast<std::chrono::microseconds>(d - secs);
47
66.4k
    tv.tv_sec = secs.count();
48
66.4k
    tv.tv_usec = usecs.count();
49
66.4k
  }
void Envoy::Event::TimerUtils::durationToTimeval<std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000l> > >(std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000l> > const&, timeval&)
Line
Count
Source
31
2.29k
  template <typename Duration> static void durationToTimeval(const Duration& d, timeval& tv) {
32
2.29k
    if (d.count() < 0) {
33
0
      IS_ENVOY_BUG(fmt::format("Negative duration passed to durationToTimeval(): {}", d.count()));
34
0
      tv.tv_sec = 0;
35
0
      tv.tv_usec = 500000;
36
0
      return;
37
2.29k
    };
38
2.29k
    constexpr int64_t clip_to = INT32_MAX; // 136.102208 years
39
2.29k
    auto secs = std::chrono::duration_cast<std::chrono::seconds>(d);
40
2.29k
    if (secs.count() > clip_to) {
41
0
      tv.tv_sec = clip_to;
42
0
      tv.tv_usec = 0;
43
0
      return;
44
0
    }
45
46
2.29k
    auto usecs = std::chrono::duration_cast<std::chrono::microseconds>(d - secs);
47
2.29k
    tv.tv_sec = secs.count();
48
2.29k
    tv.tv_usec = usecs.count();
49
2.29k
  }
50
};
51
52
/**
53
 * libevent implementation of Timer.
54
 */
55
class TimerImpl : public Timer, ImplBase {
56
public:
57
  TimerImpl(Libevent::BasePtr& libevent, TimerCb cb, Event::Dispatcher& dispatcher);
58
59
  // Timer
60
  void disableTimer() override;
61
62
  void enableTimer(std::chrono::milliseconds d, const ScopeTrackedObject* scope) override;
63
  void enableHRTimer(std::chrono::microseconds us, const ScopeTrackedObject* object) override;
64
65
  bool enabled() override;
66
67
private:
68
  void internalEnableTimer(const timeval& tv, const ScopeTrackedObject* scope);
69
  TimerCb cb_;
70
  Dispatcher& dispatcher_;
71
  // This has to be atomic for alarms which are handled out of thread, for
72
  // example if the DispatcherImpl::post is called by two threads, they race to
73
  // both set this to null.
74
  std::atomic<const ScopeTrackedObject*> object_{};
75
};
76
77
} // namespace Event
78
} // namespace Envoy