Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bslmt_chronoutil
[Package bslmt]

Provide utilities related to threading with C++11-style clocks. More...

Namespaces

namespace  bslmt

Detailed Description

Outline
Purpose:
Provide utilities related to threading with C++11-style clocks.
Classes:
bslmt::ChronoUtil namespace for bsl::chrono-related operations
See also:
Description:
This component defines a utility struct, bslmt::ChronoUtil, that serves as a namespace for a suite of classes and functions for interfacing C++11-style clocks with the clocks that BDE provides.
bslmt::ChronoUtil defines a durationToTimeInterval function for converting an arbitrary bsl::chrono::duration to a bsls::TimeInterval.
bslmt::ChronoUtil also defines a timedWait function for waiting on a synchronization primitive that uses a bsls system clock type internally (see bsls_systemclocktype), while allowing the user to specify the timeout using a bsl::chrono::time_point.
ChronoUtil::timedWait requires several things from the underlying primitive:
(1) an enumeration containing e_TIMED_OUT.
(2) a member function, timedWait, that takes a const bsls::TimeInterval& denoting the timeout value, and possibly an additional pointer argument. This function should return 0 upon success, e_TIMED_OUT on a timeout, and some other value on failure. ChronoUtil::timedWait will convert the bsl::chrono::time_point that is passed to it into a bsls::TimeInterval that can be used by the synchronization primitive (ARG_TYPE is just a placeholder name; the primitive will have its own type):
  int timedWait(const bsls::TimeInterval&);
  int timedWait(ARG_TYPE *argument, const bsls::TimeInterval&);
(3) a const member function, clockType, that takes no parameters and returns the underlying clock that the primitive uses -- either bsls::SystemClockType::e_REALTIME or bsls::SystemClockType::e_MONOTONIC:
  bsls::SystemClockType::Enum clockType() const;
Note that if the clock associated with the time point does not correspond to the clock used by the underlying synchronization primitive, then the timedWait function of the primitive may be called more than once, so the method is potentially more efficient if the clocks match.
Finally, bslmt::ChronoUtil defines an isMatchingClock function that checks to see if a C++11-style clock matches a bsls system clock. See bsls_systemclocktype.
Usage:
This example illustrates intended use of this component.
We first define a synchronization primitive that is compliant with the requirements of bslmt::ChronoUtil::timedWait and then demonstrate use of that primitive with timedWait.
Prologue: Create a Synchronization Primitive:
The TimedWaitSuccess class, defined below, is a synchronization primitive that complies with the requirements of bslmt::ChronoUtil::timedWait (see the component-level documentation for information).
First, we define the interface of TimedWaitSuccess:
  class TimedWaitSuccess {
      // 'TimedWaitSuccess' is a synchronization primitive that always
      // succeeds.

    private:
      // DATA
      bsls::SystemClockType::Enum d_clockType;

    public:
      // TYPES
      enum { e_TIMED_OUT = 1 };

      // CREATORS
      explicit
      TimedWaitSuccess(bsls::SystemClockType::Enum clockType
                                        = bsls::SystemClockType::e_REALTIME);
          // Create a 'TimedWaitSuccess' object.  Optionally specify a
          // 'clockType' indicating the type of the system clock against
          // which the 'bsls::TimeInterval' 'absTime' timeouts passed to the
          // 'timedWait' method are to be interpreted.  If 'clockType' is not
          // specified then the realtime system clock is used.

      // MANIPULATORS
      int timedWait(const bsls::TimeInterval&);
          // Return 0 immediately.  Note that this is for demonstration and
          // testing purposes only.

      // ACCESSORS
      bsls::SystemClockType::Enum clockType() const;
          // Return the clock type used for timeouts.
  };
Then, we implement the creator. All it has to do is remember the clockType that was passed to it:
  inline
  TimedWaitSuccess::TimedWaitSuccess(bsls::SystemClockType::Enum clockType)
  : d_clockType(clockType)
  {
  }
Next, we implement the timedWait function. In this simplistic primitive, this function always succeeds:
  // MANIPULATORS
  inline
  int TimedWaitSuccess::timedWait(const bsls::TimeInterval&)
  {
      return 0;
  }
Next, we implement the clockType function, which returns the underlying bsls::SystemClockType::Enum that this primitive uses:
  // ACCESSORS
  inline
  bsls::SystemClockType::Enum TimedWaitSuccess::clockType() const
  {
      return d_clockType;
  }
Example 1: Using bslmt::ChronoUtil::timedWait:
This example demonstrates use of bslmt::ChronoUtil::timedWait to block on a synchronization primitive until either a condition is satisfied or a specified amount of time has elapsed. We use a bsl::chrono::time_point to specify the amount of time to wait. To do this, we call bslmt::ChronoUtil::timedWait, passing in the timeout as an absolute time point. In this example, we're using TimedWaitSuccess as the synchronization primitive, and specifying the timeout using bsl::chrono::steady_clock.
First, we construct the TimedWaitSuccess primitive; by default it uses the bsls realtime system clock to measure time:
  TimedWaitSuccess aPrimitive;
Then, we call bslmt::ChronoUtil::timedWait to block on aPrimitive, while passing a timeout of "10 seconds from now", measured on the bsl::chrono::steady_clock:
  int rc = bslmt::ChronoUtil::timedWait(
           &aPrimitive,
           bsl::chrono::steady_clock::now() + bsl::chrono::seconds(10));
When this call returns, one of three things will be true: (a) rc == 0, which means that the call succeeded before the timeout expired, (b) rc == TimedWaitSuccess::e_TIMED_OUT, which means that the call did not succeed before the timeout expired, or (c) rc equals some other value, which means that an error occurred.
If the call to bslmt::ChronoUtil::timedWait returned e_TIMED_OUT then we are guaranteed that the current time *on the clock that the time point was defined on* is greater than the timeout value that was passed in.