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