[#BloombergLP-balb-LeakyBucket] = xref:BloombergLP.adoc[BloombergLP]::xref:BloombergLP/balb.adoc[balb]::LeakyBucket :relfileprefix: ../../ :mrdocs: This mechanism implements a leaky bucket that allows clients to monitor whether a resource is being consumed at a particular rate. The behavior of a leak bucket is determined by two properties: the drain rate (in units/s) and capacity (in units), both of which can be specified at construction or using the `setRateAndCapacity` method. == Synopsis Declared in `<balb_leakybucket.h>` [source,cpp,subs="verbatim,replacements,macros,-callouts"] ---- class LeakyBucket; ---- == Description Units can be added to a leaky bucket by either submitting them using the `submit` method or reserving them using the `reserve` method. Submitted units are removed from a leaky bucket at the drain rate, while reserved units stays unaffected in a leaky bucket until they are either cancelled (removed from the leaky bucket) using the `cancelReserved` method or submitted using the `submitReserved` method. Adding units to a leaky bucket will cause it to overflow if after the units are added, the total number of units in the leaky bucket (including both submitted and reserved units) exceeds its capacity. A leaky bucket can be queried whether adding a specified number of units would cause it to overflow via the `wouldOverflow` method. If submitting units to a leaky bucket will cause it to overflow, the estimated amount of time to wait before 1 more units can be submitted without causing the leaky bucket to overflow can be determined using the `calculateTimeToSubmit` method. The state of a leaky bucket must be updated manually using the `updateState` method supplying the current time interval. The time intervals supplied should all refer to the same time origin. A leaky bucket keeps some statistics, including the number of submitted units, that can be accessed using the `getStatistics` method and reset using the `resetStatistics` method. The class invariants are: * `capacity() > 0` * `drainRate() > 0` This class: * is _exception_ _neutral_ (agnostic) * is _const_ _thread‐safe_ For terminology see `bsldoc_glossary`. == Member Functions [cols="1,4"] |=== | Name| Description | xref:BloombergLP/balb/LeakyBucket/2constructor.adoc[`LeakyBucket`] [.small]#[constructor]# | Create an empty leaky bucket having the specified `drainRate`, the specified `capacity`, and the specified `currentTime` as the initial `lastUpdateTime`. The behavior is undefined unless `0 < newRate`, `0 < newCapacity`, and `LLONG_MIN != currentTime.seconds()`. | xref:BloombergLP/balb/LeakyBucket/2destructor.adoc[`~LeakyBucket`] [.small]#[destructor]# | Destroy this object. | xref:BloombergLP/balb/LeakyBucket/calculateTimeToSubmit.adoc[`calculateTimeToSubmit`] | If 1 more unit can be submitted to this leaky bucket without causing it to overflow, then return a time interval of 0 immediately. Otherwise, first update the state of this leaky bucket to the specified `currentTime`. Then, return the estimated time interval that should pass from `currentTime` until 1 more unit can be submitted to this leaky bucket without causing it to overflow. The number of nanoseconds in the returned time interval is rounded up. Note that a time interval of 0 can still be return after the state of this leaky bucket has been updated to `currentTime`. Also note that after waiting for the returned time interval, clients should typically check again using this method, because additional units may have been submitted in the interim. The behavior is undefined unless `LLONG_MIN != currentTime.seconds()` and the total number of seconds in the time interval resulting from `currentTime ‐ lastUpdateTime()` can be represented with a 64‐bit signed integer. | xref:BloombergLP/balb/LeakyBucket/cancelReserved.adoc[`cancelReserved`] | Cancel the specified `numUnits` that were previously reserved. This method reduces the number of reserved units by `numUnits`. The behavior is undefined unless `numUnits <= unitsReserved()`. | xref:BloombergLP/balb/LeakyBucket/capacity.adoc[`capacity`] | Return the capacity of this leaky bucket. | xref:BloombergLP/balb/LeakyBucket/drainRate.adoc[`drainRate`] | Return the drain rate of this leaky bucket. | xref:BloombergLP/balb/LeakyBucket/getStatistics.adoc[`getStatistics`] | Load, into the specified `submittedUnits` and the specified `unusedUnits` respectively, the numbers of submitted units and the number of unused units for this leaky bucket from the `statisticsCollectionStartTime` to the `lastUpdateTime`. The number of unused units is the difference between the number of units that could have been consumed and the number of units actually submitted for the time period. | xref:BloombergLP/balb/LeakyBucket/lastUpdateTime.adoc[`lastUpdateTime`] | Return the time interval when this leaky bucket was last updated. | xref:BloombergLP/balb/LeakyBucket/reserve.adoc[`reserve`] | Reserve the specified `numUnits` for future use by this leaky bucket. The behavior is undefined unless 'unitsReserved() + unitsInBucket() + numUnits' can be represented by a 64‐bit unsigned integral type. Note that after this operation, this bucket may overflow. Also note that the time interval between the invocations of `reserve` and `submitReserved` or `cancelReserved` should be kept as short as possible; otherwise, the precision of the time interval calculated by `calculateTimeToSubmit` may be negatively affected. | xref:BloombergLP/balb/LeakyBucket/reset.adoc[`reset`] | Reset the following statistic counters for this leaky bucket to 0: `unitsInBucket`, `unitsReserved`, `submittedUnits`, and `unusedUnits`. Set the `lastUpdateTime` and the `statisticCollectionStartTime` to the specified `currentTime` of this leaky bucket. The behavior is undefined unless 'LLONG_MIN != currentTime.seconds()'. | xref:BloombergLP/balb/LeakyBucket/resetStatistics.adoc[`resetStatistics`] | Reset the statics collected for this leaky bucket by setting the number of units used and the number of units submitted to 0, and set the `statisticsCollectionStartTime` to the `lastUpdateTime` of this leaky bucket. | xref:BloombergLP/balb/LeakyBucket/setRateAndCapacity.adoc[`setRateAndCapacity`] | Set the drain rate of this leaky bucket to the specified `newRate` and the capacity of this leaky bucket to the specified `newCapacity`. The behavior is undefined unless `0 < newRate` and `0 < newCapacity`. | xref:BloombergLP/balb/LeakyBucket/statisticsCollectionStartTime.adoc[`statisticsCollectionStartTime`] | Return the time interval when the collection of the statistics (as returned by `getStatistics`) started. | xref:BloombergLP/balb/LeakyBucket/submit.adoc[`submit`] | Submit the specified `numUnits` to this leaky bucket. The behavior is undefined unless `unitsReserved() + unitsInBucket() + numUnits` can be represented by a 64‐bit unsigned integral type. Note that after this operation, this leaky bucket may overflow. | xref:BloombergLP/balb/LeakyBucket/submitReserved.adoc[`submitReserved`] | Submit the specified `numUnits` that were previously reserved. This method reduces the number of reserved units by `numUnits` and submits `numUnits` to this leaky bucket. The behavior is undefined unless `numUnits <= unitsReserved()`. | xref:BloombergLP/balb/LeakyBucket/unitsInBucket.adoc[`unitsInBucket`] | Return the number of submitted units in this leaky bucket. | xref:BloombergLP/balb/LeakyBucket/unitsReserved.adoc[`unitsReserved`] | Return the number of reserved units in this leaky bucket. | xref:BloombergLP/balb/LeakyBucket/updateState.adoc[`updateState`] | Set the `lastUpdateTime` of this leaky bucket to the specified `currentTime`. If `currentTime` is after `lastUpdateTime`, then update the `unitsInBucket` of this leaky bucket by subtracting from it the number of units drained from `lastUpdateTime` to `currentTime`. If `currentTime` is before the `statisticsCollectionStartTime` of this leaky bucket, set `statisticsCollectionStartTime` to `currentTime`. The behavior is undefined unless `LLONG_MIN != currentTime.seconds()` and the total number of seconds in the time interval resulting from `currentTime ‐ lastUpdateTime()` can be represented with a 64‐bit signed integer. | xref:BloombergLP/balb/LeakyBucket/wouldOverflow.adoc[`wouldOverflow`] | Update the state of this this leaky bucket to the specified `currentTime`, and return `true` if adding 1 more unit to this leaky bucket would cause the total number of units held by this leaky bucket to exceed its capacity, and `false` otherwise. Note that this method counts both submitted units and reserved units toward the total number of units held by this leaky bucket. The behavior is undefined unless `LLONG_MIN != currentTime.seconds()` and the total number of seconds in the time interval resulting from `currentTime ‐ lastUpdateTime()` can be represented with a 64‐bit signed integer. |=== == Static Member Functions [cols="1,4"] |=== | Name| Description | xref:BloombergLP/balb/LeakyBucket/calculateCapacity.adoc[`calculateCapacity`] | Return the capacity of a leaky bucket as the rounded‐down product of the specified `drainRate` by the specified `timeWindow`. If the result evaluates to 0, return 1. The behavior is undefined unless the product of `drainRate` and `timeWindow` can be represented by a 64‐bit unsigned integral type. | xref:BloombergLP/balb/LeakyBucket/calculateDrainTime.adoc[`calculateDrainTime`] | Return the time interval required to drain the specified `numUnits` at the specified `drainRate`, round up the number of nanoseconds in the time interval if the specified `ceilFlag` is set to `true`, otherwise, round down the number of nanoseconds. The behavior is undefined unless the number of seconds in the calculated interval may be represented by a 64‐bit signed integral type. | xref:BloombergLP/balb/LeakyBucket/calculateTimeWindow.adoc[`calculateTimeWindow`] | Return the time interval over which a leaky bucket _approximates_ a moving‐total of submitted units, as the rounded‐down ratio between the specified `capacity` and the specified `drainRate`. If the rounded ratio is 0, return a time interval of 1 nanosecond. The behavior is undefined unless `drainRate > 0` and `capacity / drainRate` can be represented with 64‐bit signed integral type. |=== [.small]#Created with https://www.mrdocs.com[MrDocs]#