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