Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Examples

Duration
How you Override the Duration's Default Constructor
Saturating
xtime Conversions
Clocks
Cycle count
xtime_clock
Time Point
min Utility
A Tiny Program that Times How Long Until a Key is Struck
24 Hours Display
Simulated Thread Interface Demonstration Program
IO
French Output

Next we show how to override the duration's default constructor to do anything you want (in this case set it to zero). All we need to do is to change the representation

namespace I_dont_like_the_default_duration_behavior {

template <class R>
class zero_default
{
public:
    typedef R rep;

private:
    rep rep_;
public:
    zero_default(rep i = 0) : rep_(i) {}
    operator rep() const {return rep_;}

    zero_default& operator+=(zero_default x) {rep_ += x.rep_; return *this;}
    zero_default& operator-=(zero_default x) {rep_ -= x.rep_; return *this;}
    zero_default& operator*=(zero_default x) {rep_ *= x.rep_; return *this;}
    zero_default& operator/=(zero_default x) {rep_ /= x.rep_; return *this;}

    zero_default  operator+ () const {return *this;}
    zero_default  operator- () const {return zero_default(-rep_);}
    zero_default& operator++()       {++rep_; return *this;}
    zero_default  operator++(int)    {return zero_default(rep_++);}
    zero_default& operator--()       {--rep_; return *this;}
    zero_default  operator--(int)    {return zero_default(rep_--);}

    friend zero_default operator+(zero_default x, zero_default y) {return x += y;}
    friend zero_default operator-(zero_default x, zero_default y) {return x -= y;}
    friend zero_default operator*(zero_default x, zero_default y) {return x *= y;}
    friend zero_default operator/(zero_default x, zero_default y) {return x /= y;}

    friend bool operator==(zero_default x, zero_default y) {return x.rep_ == y.rep_;}
    friend bool operator!=(zero_default x, zero_default y) {return !(x == y);}
    friend bool operator< (zero_default x, zero_default y) {return x.rep_ < y.rep_;}
    friend bool operator<=(zero_default x, zero_default y) {return !(y < x);}
    friend bool operator> (zero_default x, zero_default y) {return y < x;}
    friend bool operator>=(zero_default x, zero_default y) {return !(x < y);}
};

typedef boost::chrono::duration<zero_default<long long>, boost::nano        > nanoseconds;
typedef boost::chrono::duration<zero_default<long long>, boost::micro       > microseconds;
typedef boost::chrono::duration<zero_default<long long>, boost::milli       > milliseconds;
typedef boost::chrono::duration<zero_default<long long>                      > seconds;
typedef boost::chrono::duration<zero_default<long long>, boost::ratio<60>   > minutes;
typedef boost::chrono::duration<zero_default<long long>, boost::ratio<3600> > hours;
}

Usage

using namespace I_dont_like_the_default_duration_behavior;

milliseconds ms;
std::cout << ms.count() << '\n';

See the source file example/i_dont_like_the_default_duration_behavior.cpp

A "saturating" signed integral type is developed. This type has +/- infinity and a NaN (like IEEE floating-point) but otherwise obeys signed integral arithmetic. This class is subsequently used as the template parameter Rep in boost::chrono::duration to demonstrate a duration class that does not silently ignore overflow.

See the source file example/saturating.cpp

Example round_up utility: converts d to To, rounding up for inexact conversions Being able to easily write this function is a major feature!

#include <boost/chrono.hpp>
#include <boost/type_traits.hpp>

#include <iostream>

template <class To, class Rep, class Period>
To
round_up(boost::chrono::duration<Rep, Period> d)
{
    To result = boost::chrono::duration_cast<To>(d);
    if (result < d)
        ++result;
    return result;
}

To demonstrate interaction with an xtime-like facility:

struct xtime
{
    long sec;
    unsigned long usec;
};

template <class Rep, class Period>
xtime
to_xtime_truncate(boost::chrono::duration<Rep, Period> d)
{
    xtime xt;
    xt.sec = static_cast<long>(boost::chrono::duration_cast<seconds>(d).count());
    xt.usec = static_cast<long>(boost::chrono::duration_cast<microseconds>(d - seconds(xt.sec)).count());
    return xt;
}

template <class Rep, class Period>
xtime
to_xtime_round_up(boost::chrono::duration<Rep, Period> d)
{
    xtime xt;
    xt.sec = static_cast<long>(boost::chrono::duration_cast<seconds>(d).count());
    xt.usec = static_cast<unsigned long>(round_up<boost::chrono::microseconds>(d - boost::chrono::seconds(xt.sec)).count());
    return xt;
}

microseconds
from_xtime(xtime xt)
{
    return boost::chrono::seconds(xt.sec) + boost::chrono::microseconds(xt.usec);
}

void print(xtime xt)
{
    std::cout << '{' << xt.sec << ',' << xt.usec << "}\n";
}

Usage

xtime xt = to_xtime_truncate(seconds(3) + boost::chrono::milliseconds(251));
print(xt);
boost::chrono::milliseconds ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(from_xtime(xt));
std::cout << ms.count() << " milliseconds\n";
xt = to_xtime_round_up(ms);
print(xt);
xt = to_xtime_truncate(boost::chrono::seconds(3) + nanoseconds(999));
print(xt);
xt = to_xtime_round_up(boost::chrono::seconds(3) + nanoseconds(999));
print(xt);

See the source file xtime.cpp

Users can easily create their own clocks, with both points in time and time durations which have a representation and precision of their own choosing. For example if there is a hardware counter which simply increments a count with each cycle of the cpu, one can very easily build clocks, time points and durations on top of that, using only a few tens of lines of code. Such systems can be used to call the time-sensitive threading API's such as sleep, wait on a condition variable, or wait for a mutex lock. The API proposed herein is not sensitive as to whether this is a 300MHz clock (with a 3 1/3 nanosecond tick period) or a 3GHz clock (with a tick period of 1/3 of a nanosecond). And the resulting code will be just as efficient as if the user wrote a special purpose clock cycle counter.

#include <boost/chrono.hpp>
#include <boost/type_traits.hpp>
#include <iostream>

template <long long speed>
struct cycle_count
{
    typedef typename boost::__ratio_multiply__<boost::ratio<speed>, boost::mega>::type
        frequency;  // Mhz
    typedef typename boost::__ratio_divide__<boost::ratio<1>, frequency>::type period;
    typedef long long rep;
    typedef boost::chrono::duration<rep, period> duration;
    typedef boost::chrono::time_point<cycle_count> time_point;

    static time_point now()
    {
        static long long tick = 0;
        // return exact cycle count
        return time_point(duration(++tick));  // fake access to clock cycle count
    }
};

template <long long speed>
struct approx_cycle_count
{
    static const long long frequency = speed * 1000000;  // MHz
    typedef nanoseconds duration;
    typedef duration::rep rep;
    typedef duration::period period;
    static const long long nanosec_per_sec = period::den;
    typedef boost::chrono::time_point<approx_cycle_count> time_point;

    static time_point now()
    {
        static long long tick = 0;
        // return cycle count as an approximate number of nanoseconds
        // compute as if nanoseconds is only duration in the std::lib
        return time_point(duration(++tick * nanosec_per_sec / frequency));
    }
};

See the source file cycle_count.cpp

This example demonstrates the use of a timeval-like struct to be used as the representation type for both duration and time_point.

class xtime {
private:
    long tv_sec;
    long tv_usec;

    void fixup() {
        if (tv_usec < 0) {
            tv_usec += 1000000;
            --tv_sec;
        }
    }

public:
    explicit xtime(long sec, long usec) {
        tv_sec = sec;
        tv_usec = usec;
        if (tv_usec < 0 || tv_usec >= 1000000) {
            tv_sec += tv_usec / 1000000;
            tv_usec %= 1000000;
            fixup();
        }
    }

    explicit xtime(long long usec) {
        tv_usec = static_cast<long>(usec % 1000000);
        tv_sec  = static_cast<long>(usec / 1000000);
        fixup();
    }

    // explicit
    operator long long() const {return static_cast<long long>(tv_sec) * 1000000 + tv_usec;}

    xtime& operator += (xtime rhs) {
        tv_sec += rhs.tv_sec;
        tv_usec += rhs.tv_usec;
        if (tv_usec >= 1000000) {
            tv_usec -= 1000000;
            ++tv_sec;
        }
        return *this;
    }

    xtime& operator -= (xtime rhs) {
        tv_sec -= rhs.tv_sec;
        tv_usec -= rhs.tv_usec;
        fixup();
        return *this;
    }

    xtime& operator %= (xtime rhs) {
        long long t = tv_sec * 1000000 + tv_usec;
        long long r = rhs.tv_sec * 1000000 + rhs.tv_usec;
        t %= r;
        tv_sec = static_cast<long>(t / 1000000);
        tv_usec = static_cast<long>(t % 1000000);
        fixup();
        return *this;
    }

    friend xtime operator+(xtime x, xtime y) {return x += y;}
    friend xtime operator-(xtime x, xtime y) {return x -= y;}
    friend xtime operator%(xtime x, xtime y) {return x %= y;}

    friend bool operator==(xtime x, xtime y)
        { return (x.tv_sec == y.tv_sec && x.tv_usec == y.tv_usec); }

    friend bool operator<(xtime x, xtime y) {
        if (x.tv_sec == y.tv_sec)
            return (x.tv_usec < y.tv_usec);
        return (x.tv_sec < y.tv_sec);
    }

    friend bool operator!=(xtime x, xtime y) { return !(x == y); }
    friend bool operator> (xtime x, xtime y) { return y < x; }
    friend bool operator<=(xtime x, xtime y) { return !(y < x); }
    friend bool operator>=(xtime x, xtime y) { return !(x < y); }

    friend std::ostream& operator<<(std::ostream& os, xtime x)
        {return os << '{' << x.tv_sec << ',' << x.tv_usec << '}';}
};

Clock based on timeval-like struct.

class xtime_clock
{
public:
    typedef xtime                                  rep;
    typedef boost::micro                           period;
    typedef boost::chrono::duration<rep, period>   duration;
    typedef boost::chrono::time_point<xtime_clock> time_point;

    static time_point now()
    {
    #if defined(BOOST_CHRONO_WINDOWS_API)
        time_point t(duration(xtime(0)));
        gettimeofday((timeval*)&t, 0);
        return t;

    #elif defined(BOOST_CHRONO_MAC_API)

        time_point t(duration(xtime(0)));
        gettimeofday((timeval*)&t, 0);
        return t;

    #elif defined(BOOST_CHRONO_POSIX_API)
        //time_point t(0,0);

        timespec ts;
        ::clock_gettime( CLOCK_REALTIME, &ts );

        xtime xt( ts.tv_sec, ts.tv_nsec/1000);
        return time_point(duration(xt));

    #endif  // POSIX
    }
};

Usage of xtime_clock

std::cout << "sizeof xtime_clock::time_point = " << sizeof(xtime_clock::time_point) << '\n';
std::cout << "sizeof xtime_clock::duration = " << sizeof(xtime_clock::duration) << '\n';
std::cout << "sizeof xtime_clock::rep = " << sizeof(xtime_clock::rep) << '\n';
xtime_clock::duration delay(boost::chrono::milliseconds(5));
xtime_clock::time_point start = xtime_clock::now();
while (xtime_clock::now() - start <= delay) {}
xtime_clock::time_point stop = xtime_clock::now();
xtime_clock::duration elapsed = stop - start;
std::cout << "paused " << boost::chrono::::nanoseconds(elapsed).count() << " nanoseconds\n";

See the source file example/timeval_demo.cpp

The user can define a function returning the earliest time_point as follows:

template <class Clock, class Duration1, class Duration2>
typename boost::common_type<time_point<Clock, Duration1>,
                     time_point<Clock, Duration2> >::type
min(time_point<Clock, Duration1> t1, time_point<Clock, Duration2> t2)
{
    return t2 < t1 ? t2 : t1;
}

Being able to easily write this function is a major feature!

BOOST_AUTO(t1, system_clock::now() + seconds(3));
BOOST_AUTO(t2, system_clock::now() + nanoseconds(3));
BOOST_AUTO(t3, min(t1, t2));

See the source file example/min_time_point.cpp

#include <boost/chrono.hpp>
#include <iostream>
#include <iomanip>

using namespace boost::chrono;

template< class Clock >
class timer
{
  typename Clock::time_point start;
public:
  timer() : start( Clock::now() ) {}
  typename Clock::duration elapsed() const
  {
    return Clock::now() - start;
  }
  double seconds() const
  {
    return elapsed().count() * ((double)Clock::period::num/Clock::period::den);
  }
};

int main()
{
  timer<system_clock> t1;
  timer<steady_clock> t2;
  timer<high_resolution_clock> t3;

  std::cout << "Type the Enter key: ";
  std::cin.get();

  std::cout << std::fixed << std::setprecision(9);
  std::cout << "system_clock-----------: "
            << t1.seconds() << " seconds\n";
  std::cout << "steady_clock--------: "
            << t2.seconds() << " seconds\n";
  std::cout << "high_resolution_clock--: "
            << t3.seconds() << " seconds\n";

  system_clock::time_point d4 = system_clock::now();
  system_clock::time_point d5 = system_clock::now();

  std::cout << "\nsystem_clock latency-----------: " << (d5 - d4).count() << std::endl;

  steady_clock::time_point d6 = steady_clock::now();
  steady_clock::time_point d7 = steady_clock::now();

  std::cout << "steady_clock latency--------: " << (d7 - d6).count() << std::endl;

  high_resolution_clock::time_point d8 = high_resolution_clock::now();
  high_resolution_clock::time_point d9 = high_resolution_clock::now();

  std::cout << "high_resolution_clock latency--: " << (d9 - d8).count() << std::endl;

  std::time_t now = system_clock::to_time_t(system_clock::now());

  std::cout << "\nsystem_clock::now() reports UTC is "
    << std::asctime(std::gmtime(&now)) << "\n";

  return 0;
}

The output of this program run looks like this:

See the source file example/await_keystroke.cpp

In the example above we take advantage of the fact that time_points convert as long as they have the same clock, and as long as their internal durations convert. We also take advantage of the fact that a duration with a floating-point representation will convert from anything. Finally the I/O system discovers the more readable "hours" unit for our duration<double, ratio<3600>>.

There are many other ways to format durations and time_points. For example see ISO 8601. Instead of coding every possibility into operator<<, which would lead to significant code bloat for even the most trivial uses, this document seeks to inform the reader how to write custom I/O when desired.

As an example, the function below streams arbitrary durations to arbitrary basic_ostreams using the format:

[-]d/hh:mm:ss.cc

Where:

  • d is the number of days
  • h is the number of hours
  • m is the number of minutes
  • ss.cc is the number of seconds rounded to the nearest hundredth of a second
    1. include <boost/chrono/chrono_io.hpp>
    2. include <ostream>
    3. include <iostream>
// format duration as [-]d/hh::mm::ss.cc
template <class CharT, class Traits, class Rep, class Period>
std::basic_ostream<CharT, Traits>&
display(std::basic_ostream<CharT, Traits>& os,
        boost::chrono::duration<Rep, Period> d)
{
    using namespace std;
    using namespace boost;

    typedef boost::chrono::duration<long long, boost::ratio<86400> > days;
    typedef boost::chrono::duration<long long, boost:centi> centiseconds;

    // if negative, print negative sign and negate
    if (d < boost::chrono::duration<Rep, Period>(0))
    {
        d = -d;
        os << '-';
    }
    // round d to nearest centiseconds, to even on tie
    centiseconds cs = boost::chrono::duration_cast<centiseconds>(d);
    if (d - cs > boost::chrono::milliseconds(5)
        || (d - cs == boost::chrono::milliseconds(5) && cs.count() & 1))
        ++cs;
    // separate seconds from centiseconds
    boost::chrono::seconds s = boost::chrono::duration_cast<boost::chrono::seconds>(cs);
    cs -= s;
    // separate minutes from seconds
    boost::chrono::minutes m = boost::chrono::duration_cast<boost::chrono::minutes>(s);
    s -= m;
    // separate hours from minutes
    boost::chrono::hours h = boost::chrono::duration_cast<boost::chrono::hours>(m);
    m -= h;
    // separate days from hours
    days dy = boost::chrono::duration_cast<days>(h);
    h -= dy;
    // print d/hh:mm:ss.cc
    os << dy.count() << '/';
    if (h < boost::chrono::hours(10))
        os << '0';
    os << h.count() << ':';
    if (m < boost::chrono::minutes(10))
        os << '0';
    os << m.count() << ':';
    if (s < boost::chrono::seconds(10))
        os << '0';
    os << s.count() << '.';
    if (cs < boost::chrono::centiseconds(10))
        os << '0';
    os << cs.count();
    return os;
}

int main()
{
    using namespace std;
    using namespace boost;

    display(cout, boost::chrono::steady_clock::now().time_since_epoch()
                  + boost::chrono::duration<long, boost::mega>(1)) << '\n';
    display(cout, -boost::chrono::milliseconds(6)) << '\n';
    display(cout, boost::chrono::duration<long, boost::mega>(1)) << '\n';
    display(cout, -boost::chrono::duration<long, boost::mega>(1)) << '\n';
}

The output could be:

12/06:03:22.95
-0/00:00:00.01
11/13:46:40.00
-11/13:46:40.00

The C++11 standard library's multi-threading library requires the ability to deal with the representation of time in a manner consistent with modern C++ practices. Next is a simulation of this interface.

The non-member sleep functions can be emulated as follows:

namespace boost { namespace this_thread {

template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d) {
    chrono::microseconds t = chrono::duration_cast<chrono::microseconds>(d);
    if (t < d)
        ++t;
    if (t > chrono::microseconds(0))
        std::cout << "sleep_for " << t.count() << " microseconds\n";
}

template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& t) {
    using namespace chrono;
    typedef time_point<Clock, Duration> Time;
    typedef system_clock::time_point SysTime;
    if (t > Clock::now()) {
        typedef typename common_type<typename Time::duration,
                                     typename SysTime::duration>::type D;
        /* auto */ D d = t - Clock::now();
        microseconds us = duration_cast<microseconds>(d);
        if (us < d)
            ++us;
        SysTime st = system_clock::now() + us;
        std::cout << "sleep_until    ";
        detail::print_time(st);
        std::cout << " which is " << (st - system_clock::now()).count() << " microseconds away\n";
    }
}

}}

Next is the boost::thread::timed_mutex modified functions

namespace boost {
struct timed_mutex {
    // ...

    template <class Rep, class Period>
    bool try_lock_for(const chrono::duration<Rep, Period>& d) {
        chrono::microseconds t = chrono::duration_cast<chrono::microseconds>(d);
        if (t <= chrono::microseconds(0))
            return try_lock();
        std::cout << "try_lock_for " << t.count() << " microseconds\n";
        return true;
    }

    template <class Clock, class Duration>
    bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
    {
        using namespace chrono;
        typedef time_point<Clock, Duration> Time;
        typedef system_clock::time_point SysTime;
        if (t <= Clock::now())
            return try_lock();
        typedef typename common_type<typename Time::duration,
          typename Clock::duration>::type D;
        /* auto */ D d = t - Clock::now();
        microseconds us = duration_cast<microseconds>(d);
        SysTime st = system_clock::now() + us;
        std::cout << "try_lock_until ";
        detail::print_time(st);
        std::cout << " which is " << (st - system_clock::now()).count()
          << " microseconds away\n";
        return true;
    }
};
}

boost::thread::condition_variable time related function are modified as follows:

namespace boost {
struct condition_variable
{
    // ...

    template <class Rep, class Period>
    bool wait_for(mutex&, const chrono::duration<Rep, Period>& d) {
        chrono::microseconds t = chrono::duration_cast<chrono::microseconds>(d);
        std::cout << "wait_for " << t.count() << " microseconds\n";
        return true;
    }

    template <class Clock, class Duration>
    bool wait_until(mutex&, const chrono::time_point<Clock, Duration>& t) {
        using namespace boost::chrono;
        typedef time_point<Clock, Duration> Time;
        typedef system_clock::time_point SysTime;
        if (t <= Clock::now())
            return false;
        typedef typename common_type<typename Time::duration,
          typename Clock::duration>::type D;
        /* auto */ D d = t - Clock::now();
        microseconds us = duration_cast<microseconds>(d);
        SysTime st = system_clock::now() + us;
         std::cout << "wait_until     ";
        detail::print_time(st);
        std::cout << " which is " << (st - system_clock::now()).count()
          << " microseconds away\n";
        return true;
    }
};
}

Next follows how simple is the usage of this functions:

boost::mutex m;
boost::timed_mutex mut;
boost::condition_variable cv;

using namespace boost;

this_thread::sleep_for(chrono::seconds(3));
this_thread::sleep_for(chrono::nanoseconds(300));
chrono::system_clock::time_point time_limit = chrono::system_clock::now() + chrono::__seconds_(4) + chrono::milliseconds(500);
this_thread::sleep_until(time_limit);

mut.try_lock_for(chrono::milliseconds(30));
mut.try_lock_until(time_limit);

cv.wait_for(m, chrono::minutes(1));    // real code would put this in a loop
cv.wait_until(m, time_limit);  // real code would put this in a loop

// For those who prefer floating-point
this_thread::sleep_for(chrono::duration<double>(0.25));
this_thread::sleep_until(chrono::system_clock::now() + chrono::duration<double>(1.5));

See the source file example/simulated_thread_interface_demo.cpp

IO

Example use of output in French

#include <boost/chrono/chrono_io.hpp>
#include <iostream>
#include <locale>

int main()
{
    using namespace std;
    using namespace boost;
    using namespace boost::chrono;

    cout.imbue(locale(locale(), new duration_punct<char>
        (
            duration_punct<char>::use_long,
            "secondes", "minutes", "heures",
            "s", "m", "h"
        )));
    hours h(5);
    minutes m(45);
    seconds s(15);
    milliseconds ms(763);
    cout << h << ", " << m << ", " << s << " et " << ms << '\n';
}

Output is:

5 heures, 45 minutes, 15 secondes et 763 millisecondes

See the source file example/french.cpp


PrevUpHomeNext