/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 |