BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_turnstile

Detailed Description

Outline

Purpose

Provide a mechanism to meter time.

Classes

Description

This component provides a mechanism, bslmt::Turnstile, to meter time. A turnstile is configured with a rate that specified how many "events" per second the turnstile should allow. After the rate is set (via the constructor or the reset method), callers may execute the waitTurn method, which blocks until the next interval arrives. If the turnstile is not called at or above the configured rate (e.g., due to processing performed at each interval), the turnstile is said to be "lagging behind." The amount of lag time is obtained from the lagTime method.

Comparison with Sleep

A straightforward implementation of metering is to call some form of sleep (e.g., bslmt::ThreadUtil::microSleep) with a computed rate after each processing step. However, simply calling "sleep" accumulates errors since this implementation does not account for the time taken during the processing step. For example, given two functions that take rate (turns per second) and duration (expected execution time in seconds), and execute rate * duration calls to bsl::sqrt, calling waitTurn on a turnstile or bslmt::ThreadUtil::microSleep with duration 1000000 / rate, respectively; the elapsed time for each call results in the following table, showing that the bslmt::Turnstile implementation maintains the correct rate while the microSleep implementation accumulates errors.

Elapsed Time
Rate Duration Turnstile Sleep
---- -------- --------- -----
10 1 0.900310 0.940390
100 1 0.980853 1.609041
500 1 1.000711 4.989093
1000 1 1.000103 9.988734

Thread Safety

Except for the reset method, this component is thread-safe and thread-aware, meaning that multiple threads may safely use their own instances or a shared instance of a bslmt::Turnstile object, provided that reset is not called on a turnstile object while another thread is accessing or modifying the same object.

Timer Resolution

The waitTurn method has a resolution of 10 milliseconds. Therefore, bslmt::Turnstile cannot guarantee that all turns can be taken in each one second interval if a rate higher than 100 turns per second is specified.

Usage

This section illustrates intended use of this component.

Example 1: Basic Usage

The following example illustrates the use of bslmt::Turnstile to control the rate of output being written to a specified output stream. The example function, heartbeat, prints a specified message at a specified rate for a specified duration. An instance of bsls::Stopwatch is used to measure time against the specified duration.

/// Write the specified `message` to the specified `stream` at the
/// specified `rate` (given in messages per second) for the specified
/// `duration`.
static void heartbeat(bsl::ostream& stream,
const bsl::string& message,
double rate,
double duration)
{
timer.start();
bslmt::Turnstile turnstile(rate);
while (true) {
turnstile.waitTurn();
if (timer.elapsedTime() >= duration) {
break;
}
stream << message;
}
}
Definition bslstl_string.h:1281
Definition bslmt_turnstile.h:180
Definition bsls_stopwatch.h:149
void start(bool collectCpuTimes=false)
Definition bsls_stopwatch.h:348
double elapsedTime() const
Definition bsls_stopwatch.h:427

The benefits of using bslmt::Turnstile in the above example, as opposed to simply calling sleep in a loop, are twofold. Firstly, bslmt::Turnstile automatically accounts for drift caused by additional processing, so the loop is allowed to execute immediately if the program fails to execute the loop at the specified rate. Secondly, computing the sleep time and executing the sleep call, are encapsulated in the turnstile component, which improves the overall readability of the program.