BDE 4.14.0 Production release
|
Provide a generic proctor for rate controlling objects.
This component provides generic proctor to automatically reserve and release units from a rate controlling object. The rate controlling object can be of any type (typically either a balb::RateLimiter
or balb::LeakyBucket
) that provides the following methods:
Use balb::ReservationGuard
to ensure that reserved units will be correctly returned to a rate controlling object in a programming scope. Note that balb::ReservationGuard
does not assume ownership of the rate controlling object.
This section illustrates the intended use of this component.
Suppose that we are limiting the rate of network traffic generation using a balb::LeakyBucket
object. We send data buffer over a network interface using the mySendData
function:
Notice that the mySendData
function may throw an exception; therefore, we should wait until mySendData
returns before indicating the amount of data sent to the leaky bucket.
Further suppose that multiple threads are sending network data and sharing the same leaky bucket. If every thread simply checks for overflowing of the leaky bucket, send data, and then submit to the leaky bucket, then the rate of data usage may exceed the limits imposed by the leaky bucket due to race conditions. We can avoid the this issue by reserving the amount of data immediately after checking whether the leaky bucket has overflown and submit the reserved amount after the data has been sent. However, this process could lead to the loss of the reserved units (effectively decreasing the leaky bucket's capacity) if mySendData
throws an exception. balb::ReservationGuard
is designed to resolve this issue.
First, we define the size of each data chunk and the total size of the data to send:
Then, we create a balb::LeakyBucket
object to limit the rate of data transmission:
Next, we send the chunks of data using a loop. For each iteration, we check whether submitting another byte would cause the leaky bucket to overflow:
Now, if the leaky bucket would not overflow, we create a balb::ReservationGuard
object to reserve the amount of data to be sent:
Then, we use the mySendData
function to send the data chunk over the network. After the data had been sent, we submit the amount of reserved data that was actually sent:
Note that we do not have manually cancel any remaining units reserved by the balb::ReservationGuard
object either because mySendData
threw an exception, or the data was only partially sent, because when the guard object goes out of scope, all remaining reserved units will be automatically cancelled.
Finally, if submitting another byte will cause the leaky bucket to overflow, then we wait until the submission will be allowed by waiting for an amount time returned by the calculateTimeToSubmit
method: