Coverage Report

Created: 2023-11-12 09:30

/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
   * Throws an EnvoyException on negative duration input.
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
228k
  template <typename Duration> static void durationToTimeval(const Duration& d, timeval& tv) {
32
228k
    if (d.count() < 0) {
33
0
      ExceptionUtil::throwEnvoyException(
34
0
          fmt::format("Negative duration passed to durationToTimeval(): {}", d.count()));
35
0
    };
36
228k
    constexpr int64_t clip_to = INT32_MAX; // 136.102208 years
37
228k
    auto secs = std::chrono::duration_cast<std::chrono::seconds>(d);
38
228k
    if (secs.count() > clip_to) {
39
0
      tv.tv_sec = clip_to;
40
0
      tv.tv_usec = 0;
41
0
      return;
42
0
    }
43
44
228k
    auto usecs = std::chrono::duration_cast<std::chrono::microseconds>(d - secs);
45
228k
    tv.tv_sec = secs.count();
46
228k
    tv.tv_usec = usecs.count();
47
228k
  }
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
77.1k
  template <typename Duration> static void durationToTimeval(const Duration& d, timeval& tv) {
32
77.1k
    if (d.count() < 0) {
33
0
      ExceptionUtil::throwEnvoyException(
34
0
          fmt::format("Negative duration passed to durationToTimeval(): {}", d.count()));
35
0
    };
36
77.1k
    constexpr int64_t clip_to = INT32_MAX; // 136.102208 years
37
77.1k
    auto secs = std::chrono::duration_cast<std::chrono::seconds>(d);
38
77.1k
    if (secs.count() > clip_to) {
39
0
      tv.tv_sec = clip_to;
40
0
      tv.tv_usec = 0;
41
0
      return;
42
0
    }
43
44
77.1k
    auto usecs = std::chrono::duration_cast<std::chrono::microseconds>(d - secs);
45
77.1k
    tv.tv_sec = secs.count();
46
77.1k
    tv.tv_usec = usecs.count();
47
77.1k
  }
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
151k
  template <typename Duration> static void durationToTimeval(const Duration& d, timeval& tv) {
32
151k
    if (d.count() < 0) {
33
0
      ExceptionUtil::throwEnvoyException(
34
0
          fmt::format("Negative duration passed to durationToTimeval(): {}", d.count()));
35
0
    };
36
151k
    constexpr int64_t clip_to = INT32_MAX; // 136.102208 years
37
151k
    auto secs = std::chrono::duration_cast<std::chrono::seconds>(d);
38
151k
    if (secs.count() > clip_to) {
39
0
      tv.tv_sec = clip_to;
40
0
      tv.tv_usec = 0;
41
0
      return;
42
0
    }
43
44
151k
    auto usecs = std::chrono::duration_cast<std::chrono::microseconds>(d - secs);
45
151k
    tv.tv_sec = secs.count();
46
151k
    tv.tv_usec = usecs.count();
47
151k
  }
48
};
49
50
/**
51
 * libevent implementation of Timer.
52
 */
53
class TimerImpl : public Timer, ImplBase {
54
public:
55
  TimerImpl(Libevent::BasePtr& libevent, TimerCb cb, Event::Dispatcher& dispatcher);
56
57
  // Timer
58
  void disableTimer() override;
59
60
  void enableTimer(std::chrono::milliseconds d, const ScopeTrackedObject* scope) override;
61
  void enableHRTimer(std::chrono::microseconds us, const ScopeTrackedObject* object) override;
62
63
  bool enabled() override;
64
65
private:
66
  void internalEnableTimer(const timeval& tv, const ScopeTrackedObject* scope);
67
  TimerCb cb_;
68
  Dispatcher& dispatcher_;
69
  // This has to be atomic for alarms which are handled out of thread, for
70
  // example if the DispatcherImpl::post is called by two threads, they race to
71
  // both set this to null.
72
  std::atomic<const ScopeTrackedObject*> object_{};
73
};
74
75
} // namespace Event
76
} // namespace Envoy