#define _CRT_SECURE_NO_WARNINGS
#include <boost/chrono/chrono.hpp>
#include <boost/type_traits.hpp>
#include <cassert>
#include <climits>
#include <iostream>
#include <ostream>
#include <stdexcept>
#include <windows.h>
namespace
{
int gettimeofday(struct timeval * tp, void *)
{
FILETIME ft;
::GetSystemTimeAsFileTime( &ft ); long long t = (static_cast<long long>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
# if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300
t -= 116444736000000000LL;
# else
t -= 116444736000000000;
# endif
t /= 10; tp->tv_sec = static_cast<long>( t / 1000000UL);
tp->tv_usec = static_cast<long>( t % 1000000UL);
return 0;
}
}
namespace std {
void __print_time(boost::chrono::system_clock::time_point t)
{
using namespace boost::chrono;
time_t c_time = system_clock::to_time_t(t);
std::tm* tmptr = std::localtime(&c_time);
system_clock::duration d = t.time_since_epoch();
std::cout << tmptr->tm_hour << ':' << tmptr->tm_min << ':' << tmptr->tm_sec
<< '.' << (d - duration_cast<seconds>(d)).count();
}
namespace this_thread {
template <class Rep, class Period>
void sleep_for(const boost::chrono::duration<Rep, Period>& d)
{
boost::chrono::microseconds t = boost::chrono::duration_cast<boost::chrono::microseconds>(d);
if (t < d)
++t;
if (t > boost::chrono::microseconds(0))
std::cout << "sleep_for " << t.count() << " microseconds\n";
}
template <class Clock, class Duration>
void sleep_until(const boost::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())
{
typedef typename boost::common_type<typename Time::duration,
typename SysTime::duration>::type D;
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 ";
__print_time(st);
std::cout << " which is " << (st - system_clock::now()).count() << " microseconds away\n";
}
}
}
struct mutex {};
struct timed_mutex
{
bool try_lock() {std::cout << "timed_mutex::try_lock()\n"; return true;}
template <class Rep, class Period>
bool try_lock_for(const boost::chrono::duration<Rep, Period>& d)
{
boost::chrono::microseconds t = boost::chrono::duration_cast<boost::chrono::microseconds>(d);
if (t <= boost::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 boost::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 try_lock();
typedef typename boost::common_type<typename Time::duration,
typename Clock::duration>::type D;
D d = t - Clock::now();
microseconds us = duration_cast<microseconds>(d);
SysTime st = system_clock::now() + us;
std::cout << "try_lock_until ";
__print_time(st);
std::cout << " which is " << (st - system_clock::now()).count()
<< " microseconds away\n";
return true;
}
};
struct condition_variable
{
template <class Rep, class Period>
bool wait_for(mutex&, const boost::chrono::duration<Rep, Period>& d)
{
boost::chrono::microseconds t = boost::chrono::duration_cast<boost::chrono::microseconds>(d);
std::cout << "wait_for " << t.count() << " microseconds\n";
return true;
}
template <class Clock, class Duration>
bool wait_until(mutex&, const boost::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 boost::common_type<typename Time::duration,
typename Clock::duration>::type D;
D d = t - Clock::now();
microseconds us = duration_cast<microseconds>(d);
SysTime st = system_clock::now() + us;
std::cout << "wait_until ";
__print_time(st);
std::cout << " which is " << (st - system_clock::now()).count()
<< " microseconds away\n";
return true;
}
};
}
std::mutex m;
std::timed_mutex mut;
std::condition_variable cv;
void basic_examples()
{
std::cout << "Running basic examples\n";
using namespace std;
using namespace boost::chrono;
system_clock::time_point time_limit = system_clock::now() + seconds(4) + milliseconds(500);
this_thread::sleep_for(seconds(3));
this_thread::sleep_for(nanoseconds(300));
this_thread::sleep_until(time_limit);
mut.try_lock_for(milliseconds(30));
mut.try_lock_until(time_limit);
cv.wait_for(m, minutes(1)); cv.wait_until(m, time_limit); this_thread::sleep_for(duration<double>(0.25));
this_thread::sleep_until(system_clock::now() + duration<double>(1.5));
}
namespace User1
{
template <class Ratio>
class length
{
public:
typedef Ratio ratio;
private:
double len_;
public:
length() : len_(1) {}
length(const double& len) : len_(len) {}
template <class R>
length(const length<R>& d)
: len_(d.count() * boost::ratio_divide<Ratio, R>::type::den /
boost::ratio_divide<Ratio, R>::type::num) {}
double count() const {return len_;}
length& operator+=(const length& d) {len_ += d.count(); return *this;}
length& operator-=(const length& d) {len_ -= d.count(); return *this;}
length operator+() const {return *this;}
length operator-() const {return length(-len_);}
length& operator*=(double rhs) {len_ *= rhs; return *this;}
length& operator/=(double rhs) {len_ /= rhs; return *this;}
};
typedef length<boost::ratio<1> > meter; typedef length<boost::centi> centimeter; typedef length<boost::kilo> kilometer; typedef length<boost::ratio<254, 10000> > inch; typedef length<boost::ratio_multiply<boost::ratio<12>, inch::ratio>::type> foot; typedef length<boost::ratio_multiply<boost::ratio<5280>, foot::ratio>::type> mile;
typedef boost::chrono::duration<double> seconds; typedef boost::chrono::duration<double, boost::pico> picosecond; typedef boost::chrono::duration<double, boost::femto> femtosecond; typedef boost::chrono::duration<double, boost::atto> attosecond;
template <class R1, class R2>
class quantity
{
double q_;
public:
quantity() : q_(1) {}
double get() const {return q_;}
void set(double q) {q_ = q;}
};
template <>
class quantity<boost::ratio<1>, boost::ratio<0> >
{
double q_;
public:
quantity() : q_(1) {}
quantity(seconds d) : q_(d.count()) {}
double get() const {return q_;}
void set(double q) {q_ = q;}
};
template <>
class quantity<boost::ratio<0>, boost::ratio<1> >
{
double q_;
public:
quantity() : q_(1) {}
quantity(meter d) : q_(d.count()) {}
double get() const {return q_;}
void set(double q) {q_ = q;}
};
template <>
class quantity<boost::ratio<0>, boost::ratio<0> >
{
double q_;
public:
quantity() : q_(1) {}
quantity(double d) : q_(d) {}
double get() const {return q_;}
void set(double q) {q_ = q;}
};
typedef quantity<boost::ratio<0>, boost::ratio<0> > Scalar;
typedef quantity<boost::ratio<1>, boost::ratio<0> > Time; typedef quantity<boost::ratio<0>, boost::ratio<1> > Distance; typedef quantity<boost::ratio<-1>, boost::ratio<1> > Speed; typedef quantity<boost::ratio<-2>, boost::ratio<1> > Acceleration;
template <class R1, class R2, class R3, class R4>
quantity<typename boost::ratio_subtract<R1, R3>::type, typename boost::ratio_subtract<R2, R4>::type>
operator/(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
{
typedef quantity<typename boost::ratio_subtract<R1, R3>::type, typename boost::ratio_subtract<R2, R4>::type> R;
R r;
r.set(x.get() / y.get());
return r;
}
template <class R1, class R2, class R3, class R4>
quantity<typename boost::ratio_add<R1, R3>::type, typename boost::ratio_add<R2, R4>::type>
operator*(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
{
typedef quantity<typename boost::ratio_add<R1, R3>::type, typename boost::ratio_add<R2, R4>::type> R;
R r;
r.set(x.get() * y.get());
return r;
}
template <class R1, class R2>
quantity<R1, R2>
operator+(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
{
typedef quantity<R1, R2> R;
R r;
r.set(x.get() + y.get());
return r;
}
template <class R1, class R2>
quantity<R1, R2>
operator-(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
{
typedef quantity<R1, R2> R;
R r;
r.set(x.get() - y.get());
return r;
}
Distance
compute_distance(Speed v0, Time t, Acceleration a)
{
return v0 * t + Scalar(.5) * a * t * t; }
}
void testUser1()
{
std::cout << "*************\n";
std::cout << "* testUser1 *\n";
std::cout << "*************\n";
User1::Distance d( User1::mile(110) );
User1::Time t( boost::chrono::hours(2) );
User1::Speed s = d / t;
std::cout << "Speed = " << s.get() << " meters/sec\n";
User1::Acceleration a = User1::Distance( User1::foot(32.2) ) / User1::Time() / User1::Time();
std::cout << "Acceleration = " << a.get() << " meters/sec^2\n";
User1::Distance df = compute_distance(s, User1::Time( User1::seconds(0.5) ), a);
std::cout << "Distance = " << df.get() << " meters\n";
std::cout << "There are " << User1::mile::ratio::den << '/' << User1::mile::ratio::num << " miles/meter";
User1::meter mt = 1;
User1::mile mi = mt;
std::cout << " which is approximately " << mi.count() << '\n';
std::cout << "There are " << User1::mile::ratio::num << '/' << User1::mile::ratio::den << " meters/mile";
mi = 1;
mt = mi;
std::cout << " which is approximately " << mt.count() << '\n';
User1::attosecond as(1);
User1::seconds sec = as;
std::cout << "1 attosecond is " << sec.count() << " seconds\n";
std::cout << "sec = as; // compiles\n";
sec = User1::seconds(1);
as = sec;
std::cout << "1 second is " << as.count() << " attoseconds\n";
std::cout << "as = sec; // compiles\n";
std::cout << "\n";
}
namespace User2
{
template <class I>
class saturate
{
public:
typedef I int_type;
static const int_type nan = int_type(int_type(1) << (sizeof(int_type) * CHAR_BIT - 1));
static const int_type neg_inf = nan + 1;
static const int_type pos_inf = -neg_inf;
private:
int_type i_;
public:
saturate() : i_(nan) {}
explicit saturate(int_type i) : i_(i) {}
operator int_type() const;
saturate& operator+=(saturate x);
saturate& operator-=(saturate x) {return *this += -x;}
saturate& operator*=(saturate x);
saturate& operator/=(saturate x);
saturate& operator%=(saturate x);
saturate operator- () const {return saturate(-i_);}
saturate& operator++() {*this += saturate(int_type(1)); return *this;}
saturate operator++(int) {saturate tmp(*this); ++(*this); return tmp;}
saturate& operator--() {*this -= saturate(int_type(1)); return *this;}
saturate operator--(int) {saturate tmp(*this); --(*this); return tmp;}
friend saturate operator+(saturate x, saturate y) {return x += y;}
friend saturate operator-(saturate x, saturate y) {return x -= y;}
friend saturate operator*(saturate x, saturate y) {return x *= y;}
friend saturate operator/(saturate x, saturate y) {return x /= y;}
friend saturate operator%(saturate x, saturate y) {return x %= y;}
friend bool operator==(saturate x, saturate y)
{
if (x.i_ == nan || y.i_ == nan)
return false;
return x.i_ == y.i_;
}
friend bool operator!=(saturate x, saturate y) {return !(x == y);}
friend bool operator<(saturate x, saturate y)
{
if (x.i_ == nan || y.i_ == nan)
return false;
return x.i_ < y.i_;
}
friend bool operator<=(saturate x, saturate y)
{
if (x.i_ == nan || y.i_ == nan)
return false;
return x.i_ <= y.i_;
}
friend bool operator>(saturate x, saturate y)
{
if (x.i_ == nan || y.i_ == nan)
return false;
return x.i_ > y.i_;
}
friend bool operator>=(saturate x, saturate y)
{
if (x.i_ == nan || y.i_ == nan)
return false;
return x.i_ >= y.i_;
}
friend std::ostream& operator<<(std::ostream& os, saturate s)
{
switch (s.i_)
{
case pos_inf:
return os << "inf";
case nan:
return os << "nan";
case neg_inf:
return os << "-inf";
};
return os << s.i_;
}
};
template <class I>
saturate<I>::operator int_type() const
{
switch (i_)
{
case nan:
case neg_inf:
case pos_inf:
throw std::out_of_range("saturate special value can not convert to int_type");
}
return i_;
}
template <class I>
saturate<I>&
saturate<I>::operator+=(saturate x)
{
switch (i_)
{
case pos_inf:
switch (x.i_)
{
case neg_inf:
case nan:
i_ = nan;
}
return *this;
case nan:
return *this;
case neg_inf:
switch (x.i_)
{
case pos_inf:
case nan:
i_ = nan;
}
return *this;
}
switch (x.i_)
{
case pos_inf:
case neg_inf:
case nan:
i_ = x.i_;
return *this;
}
if (x.i_ >= 0)
{
if (i_ < pos_inf - x.i_)
i_ += x.i_;
else
i_ = pos_inf;
return *this;
}
if (i_ > neg_inf - x.i_)
i_ += x.i_;
else
i_ = neg_inf;
return *this;
}
template <class I>
saturate<I>&
saturate<I>::operator*=(saturate x)
{
switch (i_)
{
case 0:
switch (x.i_)
{
case pos_inf:
case neg_inf:
case nan:
i_ = nan;
}
return *this;
case pos_inf:
switch (x.i_)
{
case nan:
case 0:
i_ = nan;
return *this;
}
if (x.i_ < 0)
i_ = neg_inf;
return *this;
case nan:
return *this;
case neg_inf:
switch (x.i_)
{
case nan:
case 0:
i_ = nan;
return *this;
}
if (x.i_ < 0)
i_ = pos_inf;
return *this;
}
switch (x.i_)
{
case 0:
i_ = 0;
return *this;
case nan:
i_ = nan;
return *this;
case pos_inf:
if (i_ < 0)
i_ = neg_inf;
else
i_ = pos_inf;
return *this;
case neg_inf:
if (i_ < 0)
i_ = pos_inf;
else
i_ = neg_inf;
return *this;
}
int s = (i_ < 0 ? -1 : 1) * (x.i_ < 0 ? -1 : 1);
i_ = i_ < 0 ? -i_ : i_;
int_type x_i_ = x.i_ < 0 ? -x.i_ : x.i_;
if (i_ <= pos_inf / x_i_)
i_ *= x_i_;
else
i_ = pos_inf;
i_ *= s;
return *this;
}
template <class I>
saturate<I>&
saturate<I>::operator/=(saturate x)
{
switch (x.i_)
{
case pos_inf:
case neg_inf:
switch (i_)
{
case pos_inf:
case neg_inf:
case nan:
i_ = nan;
break;
default:
i_ = 0;
break;
}
return *this;
case nan:
i_ = nan;
return *this;
case 0:
switch (i_)
{
case pos_inf:
case neg_inf:
case nan:
return *this;
case 0:
i_ = nan;
return *this;
}
if (i_ > 0)
i_ = pos_inf;
else
i_ = neg_inf;
return *this;
}
switch (i_)
{
case 0:
case nan:
return *this;
case pos_inf:
case neg_inf:
if (x.i_ < 0)
i_ = -i_;
return *this;
}
i_ /= x.i_;
return *this;
}
template <class I>
saturate<I>&
saturate<I>::operator%=(saturate x)
{
switch (x.i_)
{
case nan:
case neg_inf:
case 0:
case pos_inf:
i_ = nan;
return *this;
}
switch (i_)
{
case neg_inf:
case pos_inf:
i_ = nan;
case nan:
return *this;
}
i_ %= x.i_;
return *this;
}
typedef boost::chrono::duration<saturate<long long>, boost::pico > picoseconds;
typedef boost::chrono::duration<saturate<long long>, boost::nano > nanoseconds;
typedef boost::chrono::duration<saturate<long long>, boost::micro > microseconds;
typedef boost::chrono::duration<saturate<long long>, boost::milli > milliseconds;
typedef boost::chrono::duration<saturate<long long> > seconds;
typedef boost::chrono::duration<saturate<long long>, boost::ratio< 60LL> > minutes;
typedef boost::chrono::duration<saturate<long long>, boost::ratio< 3600LL> > hours;
typedef boost::chrono::duration<saturate<long long>, boost::ratio< 86400LL> > days;
typedef boost::chrono::duration<saturate<long long>, boost::ratio< 31556952LL> > years;
typedef boost::chrono::duration<saturate<long long>, boost::ratio<31556952000LL> > millennium;
}
namespace User2 { namespace detail {
template <class T1, class T2, bool = boost::is_integral<T1>::value>
struct promote_helper;
template <class T1, class T2>
struct promote_helper<T1, saturate<T2>, true> {
typedef typename boost::common_type<T1, T2>::type rep;
typedef User2::saturate<rep> type;
};
template <class T1, class T2>
struct promote_helper<T1, saturate<T2>, false> {
typedef T1 type;
};
} }
namespace boost
{
template <class T1, class T2>
struct common_type<User2::saturate<T1>, User2::saturate<T2> >
{
typedef typename common_type<T1, T2>::type rep;
typedef User2::saturate<rep> type;
};
template <class T1, class T2>
struct common_type<T1, User2::saturate<T2> >
: User2::detail::promote_helper<T1, User2::saturate<T2> > {};
template <class T1, class T2>
struct common_type<User2::saturate<T1>, T2>
: User2::detail::promote_helper<T2, User2::saturate<T1> > {};
namespace chrono {
template <class I>
struct duration_values<User2::saturate<I> >
{
typedef User2::saturate<I> Rep;
public:
static Rep zero() {return Rep(0);}
static Rep max BOOST_PREVENT_MACRO_SUBSTITUTION () {return Rep(Rep::pos_inf-1);}
static Rep min BOOST_PREVENT_MACRO_SUBSTITUTION () {return -(max) ();}
};
}
}
void testUser2()
{
std::cout << "*************\n";
std::cout << "* testUser2 *\n";
std::cout << "*************\n";
using namespace User2;
typedef seconds::rep sat;
years yr(sat(100));
std::cout << "100 years expressed as years = " << yr.count() << '\n';
nanoseconds ns = yr;
std::cout << "100 years expressed as nanoseconds = " << ns.count() << '\n';
ns += yr;
std::cout << "200 years expressed as nanoseconds = " << ns.count() << '\n';
ns += yr;
std::cout << "300 years expressed as nanoseconds = " << ns.count() << '\n';
std::cout << "yr = ns; // does not compile\n";
std::cout << "ps = yr; // does not compile\n";
ns = yr;
picoseconds ps = ns;
std::cout << "100 years expressed as picoseconds = " << ps.count() << '\n';
ps = ns / sat(1000);
std::cout << "0.1 years expressed as picoseconds = " << ps.count() << '\n';
yr = years(sat(-200000000));
std::cout << "200 million years ago encoded in years: " << yr.count() << '\n';
days d = boost::chrono::duration_cast<days>(yr);
std::cout << "200 million years ago encoded in days: " << d.count() << '\n';
millennium c = boost::chrono::duration_cast<millennium>(yr);
std::cout << "200 million years ago encoded in millennium: " << c.count() << '\n';
std::cout << "Demonstrate \"uninitialized protection\" behavior:\n";
seconds sec;
for (++sec; sec < seconds(sat(10)); ++sec)
;
std::cout << sec.count() << '\n';
std::cout << "\n";
}
void testStdUser()
{
std::cout << "***************\n";
std::cout << "* testStdUser *\n";
std::cout << "***************\n";
using namespace boost::chrono;
hours hr = hours(100);
std::cout << "100 hours expressed as hours = " << hr.count() << '\n';
nanoseconds ns = hr;
std::cout << "100 hours expressed as nanoseconds = " << ns.count() << '\n';
ns += hr;
std::cout << "200 hours expressed as nanoseconds = " << ns.count() << '\n';
ns += hr;
std::cout << "300 hours expressed as nanoseconds = " << ns.count() << '\n';
std::cout << "hr = ns; // does not compile\n";
std::cout << "hr * ns; // does not compile\n";
duration<double> fs(2.5);
std::cout << "duration<double> has count() = " << fs.count() << '\n';
std::cout << "seconds sec = duration<double> won't compile\n";
seconds sec = duration_cast<seconds>(fs);
std::cout << "seconds has count() = " << sec.count() << '\n';
std::cout << "\n";
}
namespace timeval_demo
{
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();
}
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 << '}';}
};
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();
};
xtime_clock::time_point
xtime_clock::now()
{
time_point t(duration(xtime(0)));
gettimeofday((timeval*)&t, 0);
return t;
}
void test_xtime_clock()
{
using namespace boost::chrono;
std::cout << "timeval_demo system clock test\n";
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(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 " << nanoseconds(elapsed).count() << " nanoseconds\n";
}
}
namespace runtime_resolution
{
class duration
{
public:
typedef long long rep;
private:
rep rep_;
static const double ticks_per_nanosecond;
public:
typedef boost::chrono::duration<double, boost::nano> tonanosec;
duration() {} explicit duration(const rep& r) : rep_(r) {}
explicit duration(const tonanosec& d)
: rep_(static_cast<rep>(d.count() * ticks_per_nanosecond)) {}
operator tonanosec() const {return tonanosec(rep_/ticks_per_nanosecond);}
rep count() const {return rep_;}
duration& operator+=(const duration& d) {rep_ += d.rep_; return *this;}
duration& operator-=(const duration& d) {rep_ += d.rep_; return *this;}
duration& operator*=(rep rhs) {rep_ *= rhs; return *this;}
duration& operator/=(rep rhs) {rep_ /= rhs; return *this;}
duration operator+() const {return *this;}
duration operator-() const {return duration(-rep_);}
duration& operator++() {++rep_; return *this;}
duration operator++(int) {return duration(rep_++);}
duration& operator--() {--rep_; return *this;}
duration operator--(int) {return duration(rep_--);}
friend duration operator+(duration x, duration y) {return x += y;}
friend duration operator-(duration x, duration y) {return x -= y;}
friend duration operator*(duration x, rep y) {return x *= y;}
friend duration operator*(rep x, duration y) {return y *= x;}
friend duration operator/(duration x, rep y) {return x /= y;}
friend bool operator==(duration x, duration y) {return x.rep_ == y.rep_;}
friend bool operator!=(duration x, duration y) {return !(x == y);}
friend bool operator< (duration x, duration y) {return x.rep_ < y.rep_;}
friend bool operator<=(duration x, duration y) {return !(y < x);}
friend bool operator> (duration x, duration y) {return y < x;}
friend bool operator>=(duration x, duration y) {return !(x < y);}
};
static
double
init_duration()
{
return static_cast<double>(1) / 1000; }
const double duration::ticks_per_nanosecond = init_duration();
class clock;
class time_point
{
public:
typedef runtime_resolution::clock clock;
typedef long long rep;
private:
rep rep_;
rep count() const {return rep_;}
public:
time_point() : rep_(0) {}
explicit time_point(const duration& d)
: rep_(d.count()) {}
time_point& operator+=(const duration& d) {rep_ += d.count(); return *this;}
time_point& operator-=(const duration& d) {rep_ -= d.count(); return *this;}
friend time_point operator+(time_point x, duration y) {return x += y;}
friend time_point operator+(duration x, time_point y) {return y += x;}
friend time_point operator-(time_point x, duration y) {return x -= y;}
friend duration operator-(time_point x, time_point y) {return duration(x.rep_ - y.rep_);}
};
class clock
{
public:
typedef duration::rep rep;
typedef runtime_resolution::duration duration;
typedef runtime_resolution::time_point time_point;
static time_point now()
{
timeval tv;
gettimeofday( &tv, 0 );
return time_point(duration((static_cast<rep>(tv.tv_sec)<<32) | tv.tv_usec));
}
};
void test()
{
using namespace boost::chrono;
std::cout << "runtime_resolution test\n";
clock::duration delay(boost::chrono::milliseconds(5));
clock::time_point start = clock::now();
while (clock::now() - start <= delay)
;
clock::time_point stop = clock::now();
clock::duration elapsed = stop - start;
std::cout << "paused " << nanoseconds(duration_cast<nanoseconds>(duration::tonanosec(elapsed))).count()
<< " nanoseconds\n";
}
}
using namespace boost::chrono;
void physics_function(duration<double> d)
{
std::cout << "d = " << d.count() << '\n';
}
void drive_physics_function()
{
physics_function(nanoseconds(3));
physics_function(hours(3));
physics_function(duration<double>(2./3));
std::cout.precision(16);
physics_function( hours(3) + nanoseconds(-3) );
}
void test_range()
{
using namespace boost::chrono;
hours h1 = hours(24 * ( 365 * 292 + 292/4));
nanoseconds n1 = h1 + nanoseconds(1);
nanoseconds delta = n1 - h1;
std::cout << "292 years of hours = " << h1.count() << "hr\n";
std::cout << "Add a nanosecond = " << n1.count() << "ns\n";
std::cout << "Find the difference = " << delta.count() << "ns\n";
}
void test_extended_range()
{
using namespace boost::chrono;
hours h1 = hours(24 * ( 365 * 244000 + 244000/4));
microseconds u1 = h1 + microseconds(1);
microseconds delta = u1 - h1;
std::cout << "244,000 years of hours = " << h1.count() << "hr\n";
std::cout << "Add a microsecond = " << u1.count() << "us\n";
std::cout << "Find the difference = " << delta.count() << "us\n";
}
template <class Rep, class Period>
void inspect_duration(boost::chrono::duration<Rep, Period> d, const std::string& name)
{
typedef boost::chrono::duration<Rep, Period> Duration;
std::cout << "********* " << name << " *********\n";
std::cout << "The period of " << name << " is " << (double)Period::num/Period::den << " seconds.\n";
std::cout << "The frequency of " << name << " is " << (double)Period::den/Period::num << " Hz.\n";
std::cout << "The representation is ";
if (boost::is_floating_point<Rep>::value)
{
std::cout << "floating point\n";
std::cout << "The precision is the most significant ";
std::cout << std::numeric_limits<Rep>::digits10 << " decimal digits.\n";
}
else if (boost::is_integral<Rep>::value)
{
std::cout << "integral\n";
d = Duration(Rep(1));
boost::chrono::duration<double> dsec = d;
std::cout << "The precision is " << dsec.count() << " seconds.\n";
}
else
{
std::cout << "a class type\n";
d = Duration(Rep(1));
boost::chrono::duration<double> dsec = d;
std::cout << "The precision is " << dsec.count() << " seconds.\n";
}
d = Duration((std::numeric_limits<Rep>::max)());
using namespace boost::chrono;
using namespace std;
typedef duration<double, boost::ratio_multiply<boost::ratio<24*3652425,10000>, hours::period>::type> Years;
Years years = d;
std::cout << "The range is +/- " << years.count() << " years.\n";
std::cout << "sizeof(" << name << ") = " << sizeof(d) << '\n';
}
void inspect_all()
{
using namespace boost::chrono;
std::cout.precision(6);
inspect_duration(nanoseconds(), "nanoseconds");
inspect_duration(microseconds(), "microseconds");
inspect_duration(milliseconds(), "milliseconds");
inspect_duration(seconds(), "seconds");
inspect_duration(minutes(), "minutes");
inspect_duration(hours(), "hours");
inspect_duration(duration<double>(), "duration<double>");
}
void test_milliseconds()
{
using namespace boost::chrono;
milliseconds ms(250);
ms += milliseconds(1);
milliseconds ms2(150);
milliseconds msdiff = ms - ms2;
if (msdiff == milliseconds(101))
std::cout << "success\n";
else
std::cout << "failure: " << msdiff.count() << '\n';
}
using namespace std;
using namespace boost::chrono;
template <class To, class Rep, class Period>
To
round_up(duration<Rep, Period> d)
{
To result = duration_cast<To>(d);
if (result < d)
++result;
return result;
}
using namespace boost::chrono;
struct xtime
{
long sec;
unsigned long usec;
};
template <class Rep, class Period>
xtime
to_xtime_truncate(duration<Rep, Period> d)
{
xtime xt;
xt.sec = static_cast<long>(duration_cast<seconds>(d).count());
xt.usec = static_cast<long>(duration_cast<microseconds>(d - seconds(xt.sec)).count());
return xt;
}
template <class Rep, class Period>
xtime
to_xtime_round_up(duration<Rep, Period> d)
{
xtime xt;
xt.sec = static_cast<long>(duration_cast<seconds>(d).count());
xt.usec = static_cast<unsigned long>(round_up<microseconds>(d - seconds(xt.sec)).count());
return xt;
}
microseconds
from_xtime(xtime xt)
{
return seconds(xt.sec) + microseconds(xt.usec);
}
void print(xtime xt)
{
cout << '{' << xt.sec << ',' << xt.usec << "}\n";
}
void test_with_xtime()
{
cout << "test_with_xtime\n";
xtime xt = to_xtime_truncate(seconds(3) + milliseconds(251));
print(xt);
milliseconds ms = duration_cast<milliseconds>(from_xtime(xt));
cout << ms.count() << " milliseconds\n";
xt = to_xtime_round_up(ms);
print(xt);
xt = to_xtime_truncate(seconds(3) + nanoseconds(999));
print(xt);
xt = to_xtime_round_up(seconds(3) + nanoseconds(999));
print(xt);
}
void test_system_clock()
{
cout << "system_clock test" << endl;
system_clock::duration delay = milliseconds(5);
system_clock::time_point start = system_clock::now();
while (system_clock::now() - start <= delay)
;
system_clock::time_point stop = system_clock::now();
system_clock::duration elapsed = stop - start;
cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n";
start = system_clock::now();
stop = system_clock::now();
cout << "system_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n";
}
void test_steady_clock()
{
cout << "steady_clock test" << endl;
steady_clock::duration delay = milliseconds(5);
steady_clock::time_point start = steady_clock::now();
while (steady_clock::now() - start <= delay)
;
steady_clock::time_point stop = steady_clock::now();
steady_clock::duration elapsed = stop - start;
cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n";
start = steady_clock::now();
stop = steady_clock::now();
cout << "steady_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n";
}
void test_hi_resolution_clock()
{
cout << "high_resolution_clock test" << endl;
high_resolution_clock::duration delay = milliseconds(5);
high_resolution_clock::time_point start = high_resolution_clock::now();
while (high_resolution_clock::now() - start <= delay)
;
high_resolution_clock::time_point stop = high_resolution_clock::now();
high_resolution_clock::duration elapsed = stop - start;
cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n";
start = high_resolution_clock::now();
stop = high_resolution_clock::now();
cout << "high_resolution_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n";
}
void test_duration_division()
{
cout << hours(3) / milliseconds(5) << '\n';
cout << milliseconds(5) / hours(3) << '\n';
cout << hours(1) / milliseconds(1) << '\n';
}
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;
void test()
{
milliseconds ms;
cout << ms.count() << '\n';
}
}
template <class Rep, class Period>
void
print_duration(ostream& os, duration<Rep, Period> d)
{
os << d.count() << " * " << Period::num << '/' << Period::den << " seconds\n";
}
template <class Clock, class Duration1, class Duration2>
inline
typename boost::common_type<time_point<Clock, Duration1>,
time_point<Clock, Duration2> >::type
min BOOST_PREVENT_MACRO_SUBSTITUTION (time_point<Clock, Duration1> t1, time_point<Clock, Duration2> t2)
{
return t2 < t1 ? t2 : t1;
}
void test_min()
{
typedef time_point<system_clock,
boost::common_type<system_clock::duration, seconds>::type> T1;
typedef time_point<system_clock,
boost::common_type<system_clock::duration, nanoseconds>::type> T2;
typedef boost::common_type<T1, T2>::type T3;
T1 t1 = system_clock::now() + seconds(3);
T2 t2 = system_clock::now() + nanoseconds(3);
T3 t3 = (min)(t1, t2);
print_duration(cout, t1 - t3);
print_duration(cout, t2 - t3);
}
void explore_limits()
{
typedef duration<long long, boost::ratio_multiply<boost::ratio<24*3652425,10000>,
hours::period>::type> Years;
steady_clock::time_point t1( Years(250));
steady_clock::time_point t2(-Years(250));
microseconds d = time_point_cast<microseconds>(t1) - time_point_cast<microseconds>(t2);
cout << d.count() << " microseconds\n";
}
void manipulate_clock_object(system_clock clock)
{
system_clock::duration delay = milliseconds(5);
system_clock::time_point start = clock.now();
while (clock.now() - start <= delay)
;
system_clock::time_point stop = clock.now();
system_clock::duration elapsed = stop - start;
cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n";
};
template <long long speed>
struct cycle_count
{
typedef typename boost::ratio_multiply<boost::ratio<speed>, boost::mega>::type frequency; 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 time_point(duration(++tick)); }
};
template <long long speed>
struct approx_cycle_count
{
static const long long frequency = speed * 1000000; 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 time_point(duration(++tick * nanosec_per_sec / frequency));
}
};
void cycle_count_delay()
{
{
typedef cycle_count<400> clock;
cout << "\nSimulated " << clock::frequency::num / boost::mega::num << "MHz clock which has a tick period of "
<< duration<double, boost::nano>(clock::duration(1)).count() << " nanoseconds\n";
nanoseconds delayns(500);
clock::duration delay = duration_cast<clock::duration>(delayns);
cout << "delay = " << delayns.count() << " nanoseconds which is " << delay.count() << " cycles\n";
clock::time_point start = clock::now();
clock::time_point stop = start + delay;
while (clock::now() < stop) ;
clock::time_point end = clock::now();
clock::duration elapsed = end - start;
cout << "paused " << elapsed.count() << " cycles ";
cout << "which is " << duration_cast<nanoseconds>(elapsed).count() << " nanoseconds\n";
}
{
typedef approx_cycle_count<400> clock;
cout << "\nSimulated " << clock::frequency / 1000000 << "MHz clock modeled with nanoseconds\n";
clock::duration delay = nanoseconds(500);
cout << "delay = " << delay.count() << " nanoseconds\n";
clock::time_point start = clock::now();
clock::time_point stop = start + delay;
while (clock::now() < stop) ;
clock::time_point end = clock::now();
clock::duration elapsed = end - start;
cout << "paused " << elapsed.count() << " nanoseconds\n";
}
{
typedef cycle_count<1500> clock;
cout << "\nSimulated " << clock::frequency::num / boost::mega::num << "MHz clock which has a tick period of "
<< duration<double, boost::nano>(clock::duration(1)).count() << " nanoseconds\n";
nanoseconds delayns(500);
clock::duration delay = duration_cast<clock::duration>(delayns);
cout << "delay = " << delayns.count() << " nanoseconds which is " << delay.count() << " cycles\n";
clock::time_point start = clock::now();
clock::time_point stop = start + delay;
while (clock::now() < stop) ;
clock::time_point end = clock::now();
clock::duration elapsed = end - start;
cout << "paused " << elapsed.count() << " cycles ";
cout << "which is " << duration_cast<nanoseconds>(elapsed).count() << " nanoseconds\n";
}
{
typedef approx_cycle_count<1500> clock;
cout << "\nSimulated " << clock::frequency / 1000000 << "MHz clock modeled with nanoseconds\n";
clock::duration delay = nanoseconds(500);
cout << "delay = " << delay.count() << " nanoseconds\n";
clock::time_point start = clock::now();
clock::time_point stop = start + delay;
while (clock::now() < stop) ;
clock::time_point end = clock::now();
clock::duration elapsed = end - start;
cout << "paused " << elapsed.count() << " nanoseconds\n";
}
}
void test_special_values()
{
std::cout << "duration<unsigned>::min().count() = " << (duration<unsigned>::min)().count() << '\n';
std::cout << "duration<unsigned>::zero().count() = " << duration<unsigned>::zero().count() << '\n';
std::cout << "duration<unsigned>::max().count() = " << (duration<unsigned>::max)().count() << '\n';
std::cout << "duration<int>::min().count() = " << (duration<int>::min)().count() << '\n';
std::cout << "duration<int>::zero().count() = " << duration<int>::zero().count() << '\n';
std::cout << "duration<int>::max().count() = " << (duration<int>::max)().count() << '\n';
}
int main()
{
basic_examples();
testStdUser();
testUser1();
testUser2();
drive_physics_function();
test_range();
test_extended_range();
inspect_all();
test_milliseconds();
test_with_xtime();
test_system_clock();
test_steady_clock();
test_hi_resolution_clock();
timeval_demo::test_xtime_clock();
runtime_resolution::test();
test_duration_division();
I_dont_like_the_default_duration_behavior::test();
test_min();
inspect_duration(common_type<duration<double>, hours, microseconds>::type(),
"common_type<duration<double>, hours, microseconds>::type");
explore_limits();
manipulate_clock_object(system_clock());
duration<double, boost::milli> d = milliseconds(3) * 2.5;
inspect_duration(milliseconds(3) * 2.5, "milliseconds(3) * 2.5");
cout << d.count() << '\n';
cout << "milliseconds ms(3.5) doesn't compile\n";
cycle_count_delay();
test_special_values();
return 0;
}