-
Notifications
You must be signed in to change notification settings - Fork 5.3k
event: create timer from ScaledRangeTimerManager #13524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f95bd82
effc203
324198d
b8e5e1e
dc82f73
b3f1c99
794e9e1
5808eed
e29329b
4b00ebe
97e06c3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| #pragma once | ||
|
|
||
| #include "envoy/common/pure.h" | ||
| #include "envoy/event/timer.h" | ||
|
|
||
| #include "absl/types/variant.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Event { | ||
|
|
||
| /** | ||
| * Describes a minimum timer value that is equal to a scale factor applied to the maximum. | ||
| */ | ||
| struct ScaledMinimum { | ||
| explicit ScaledMinimum(double scale_factor) : scale_factor_(scale_factor) {} | ||
| const double scale_factor_; | ||
| }; | ||
|
|
||
| /** | ||
| * Describes a minimum timer value that is an absolute duration. | ||
| */ | ||
| struct AbsoluteMinimum { | ||
| explicit AbsoluteMinimum(std::chrono::milliseconds value) : value_(value) {} | ||
| const std::chrono::milliseconds value_; | ||
| }; | ||
|
|
||
| /** | ||
| * Class that describes how to compute a minimum timeout given a maximum timeout value. It wraps | ||
| * ScaledMinimum and AbsoluteMinimum and provides a single computeMinimum() method. | ||
| */ | ||
| class ScaledTimerMinimum : private absl::variant<ScaledMinimum, AbsoluteMinimum> { | ||
| public: | ||
| // Use base class constructor. | ||
| using absl::variant<ScaledMinimum, AbsoluteMinimum>::variant; | ||
akonradi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Computes the minimum value for a given maximum timeout. If this object was constructed with a | ||
| // - ScaledMinimum value: | ||
| // the return value is the scale factor applied to the provided maximum. | ||
| // - AbsoluteMinimum: | ||
| // the return value is that minimum, and the provided maximum is ignored. | ||
| std::chrono::milliseconds computeMinimum(std::chrono::milliseconds maximum) const { | ||
akonradi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| struct Visitor { | ||
| explicit Visitor(std::chrono::milliseconds value) : value_(value) {} | ||
| std::chrono::milliseconds operator()(ScaledMinimum scale_factor) { | ||
| return std::chrono::duration_cast<std::chrono::milliseconds>(scale_factor.scale_factor_ * | ||
| value_); | ||
| } | ||
| std::chrono::milliseconds operator()(AbsoluteMinimum absolute_value) { | ||
| return absolute_value.value_; | ||
| } | ||
| const std::chrono::milliseconds value_; | ||
| }; | ||
| return absl::visit<Visitor, const absl::variant<ScaledMinimum, AbsoluteMinimum>&>( | ||
| Visitor(maximum), *this); | ||
| } | ||
| }; | ||
|
|
||
| /** | ||
| * Class for creating Timer objects that can be adjusted towards either the minimum or maximum | ||
| * of their range by the owner of the manager object. Users of this class can call createTimer() to | ||
| * receive a new Timer object that they can then enable or disable at will (but only on the same | ||
| * dispatcher), and setScaleFactor() to change the scaling factor. The current scale factor is | ||
| * applied to all timers, including those that are created later. | ||
| */ | ||
| class ScaledRangeTimerManager { | ||
| public: | ||
| virtual ~ScaledRangeTimerManager() = default; | ||
|
|
||
| /** | ||
| * Creates a new timer backed by the manager. Calling enableTimer on the returned object sets the | ||
| * maximum duration, while the first argument here controls the minimum. Passing a value of | ||
| * ScaleFactor(x) sets the min to (x * max) when the timer is enabled, while AbsoluteValue(y) sets | ||
| * the min to the duration y. | ||
| */ | ||
| virtual TimerPtr createTimer(ScaledTimerMinimum minimum, TimerCb callback) PURE; | ||
akonradi marked this conversation as resolved.
Show resolved
Hide resolved
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can RangeTimer just derive from Timer? It seems like we could avoid by allowing a RangeTimer to also be stored as a normal timer if needed?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the RangeTimer interface is destined for the bit bucket; we don't need it for any consumer code now that we have a createTimer method and it's not used anywhere. I think we should just remove it. Thoughts on doing that in this PR or another one?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just do it!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, PTAL. |
||
|
|
||
| /** | ||
| * Sets the scale factor for all timers created through this manager. The value should be between | ||
| * 0 and 1, inclusive. The scale factor affects the amount of time timers spend in their target | ||
| * range. The timers returned by createTimer will fire after (min + (max - min) * scale_factor). | ||
| * This means that a scale factor of 0 causes timers to fire immediately at the min duration, a | ||
| * factor of 0.5 causes firing halfway between min and max, and a factor of 1 causes firing at | ||
| * max. | ||
| */ | ||
| virtual void setScaleFactor(double scale_factor) PURE; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this take a ScaledMinimum (or similar) which can better ASSERT that it's between 0.0 and 1.0 and then clamp if needed?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Between here and the OverloadAction class, I think it would be a good idea to have a single simple wrapper class that enforces 0.0 and 1.0 bounds. I'm going to do that in a future PR. |
||
| }; | ||
|
|
||
| using ScaledRangeTimerManagerPtr = std::unique_ptr<ScaledRangeTimerManager>; | ||
|
|
||
| } // namespace Event | ||
| } // namespace Envoy | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the wrapper I was suggesting in the previous PR? Do we assume that this is between 0.0 and 1.0? Can we document that and ASSERT that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned below, I'm going to leave this for a refactoring PR.