OperationThrottler::get_throttle() returns a ThrottleReleaser guard whose
destructor calls release_throttle(), the mClock RequestCompletion that
decrements in_progress. The guard has to be held for the whole operation: a
caller that discards it at acquisition releases the slot in the same step, so
the operation never counts against max_in_progress and the throttle does
nothing.
Mark the type [[nodiscard]] so the compiler flags a discarded co_await of
get_throttle().
Signed-off-by: Kefu Chai <k.chai@proxmox.com>
return !max_in_progress || in_progress < max_in_progress;
}
- class ThrottleReleaser {
+ // The returned guard's destructor is the mClock RequestCompletion
+ // (release_throttle), so it must be held for the throttled operation's whole
+ // lifetime. Dropping it at acquisition frees the slot immediately and the
+ // operation never counts against max_in_progress.
+ class [[nodiscard("discarding the guard releases the throttle slot immediately")]] ThrottleReleaser {
OperationThrottler *parent = nullptr;
public:
ThrottleReleaser(OperationThrottler *parent) : parent(parent) {}