1 //  time2_demo.cpp  ----------------------------------------------------------//
2 
3 //  Copyright 2008 Howard Hinnant
4 //  Copyright 2008 Beman Dawes
5 
6 //  Distributed under the Boost Software License, Version 1.0.
7 //  See http://www.boost.org/LICENSE_1_0.txt
8 
9 /*
10 
11 This code was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
12 Many thanks to Howard for making his code available under the Boost license.
13 The original code was modified to conform to Boost conventions and to section
14 20.9 Time utilities [time] of the C++ committee's working paper N2798.
15 See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
16 
17 time2_demo contained this comment:
18 
19     Much thanks to Andrei Alexandrescu,
20                    Walter Brown,
21                    Peter Dimov,
22                    Jeff Garland,
23                    Terry Golubiewski,
24                    Daniel Krugler,
25                    Anthony Williams.
26 */
27 
28 #define _CRT_SECURE_NO_WARNINGS  // disable VC++ foolishness
29 
30 #include <boost/chrono/chrono.hpp>
31 #include <boost/type_traits.hpp>
32 
33 #include <cassert>
34 #include <climits>
35 #include <iostream>
36 #include <ostream>
37 #include <stdexcept>
38 
39 #include <windows.h>
40 
41 namespace
42 {
43   //struct timeval {
44   //        long    tv_sec;         /* seconds */
45   //        long    tv_usec;        /* and microseconds */
46   //};
47 
gettimeofday(struct timeval * tp,void *)48   int gettimeofday(struct timeval * tp, void *)
49   {
50     FILETIME ft;
51     ::GetSystemTimeAsFileTime( &ft );  // never fails
52     long long t = (static_cast<long long>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
53   # if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // > VC++ 7.0
54     t -= 116444736000000000LL;
55   # else
56     t -= 116444736000000000;
57   # endif
58     t /= 10;  // microseconds
59     tp->tv_sec = static_cast<long>( t / 1000000UL);
60     tp->tv_usec = static_cast<long>( t % 1000000UL);
61     return 0;
62   }
63 }  // unnamed namespace
64 
65 //////////////////////////////////////////////////////////
66 ///////////// simulated thread interface /////////////////
67 //////////////////////////////////////////////////////////
68 
69 
70 namespace std {
71 
__print_time(boost::chrono::system_clock::time_point t)72 void __print_time(boost::chrono::system_clock::time_point t)
73 {
74     using namespace boost::chrono;
75     time_t c_time = system_clock::to_time_t(t);
76     std::tm* tmptr = std::localtime(&c_time);
77     system_clock::duration d = t.time_since_epoch();
78     std::cout << tmptr->tm_hour << ':' << tmptr->tm_min << ':' << tmptr->tm_sec
79               << '.' << (d - duration_cast<seconds>(d)).count();
80 }
81 
82 namespace this_thread {
83 
84 template <class Rep, class Period>
sleep_for(const boost::chrono::duration<Rep,Period> & d)85 void sleep_for(const boost::chrono::duration<Rep, Period>& d)
86 {
87     boost::chrono::microseconds t = boost::chrono::duration_cast<boost::chrono::microseconds>(d);
88     if (t < d)
89         ++t;
90     if (t > boost::chrono::microseconds(0))
91         std::cout << "sleep_for " << t.count() << " microseconds\n";
92 }
93 
94 template <class Clock, class Duration>
sleep_until(const boost::chrono::time_point<Clock,Duration> & t)95 void sleep_until(const boost::chrono::time_point<Clock, Duration>& t)
96 {
97     using namespace boost::chrono;
98     typedef time_point<Clock, Duration> Time;
99     typedef system_clock::time_point SysTime;
100     if (t > Clock::now())
101     {
102         typedef typename boost::common_type<typename Time::duration,
103                                      typename SysTime::duration>::type D;
104         /* auto */ D d = t - Clock::now();
105         microseconds us = duration_cast<microseconds>(d);
106         if (us < d)
107             ++us;
108         SysTime st = system_clock::now() + us;
109         std::cout << "sleep_until    ";
110         __print_time(st);
111         std::cout << " which is " << (st - system_clock::now()).count() << " microseconds away\n";
112     }
113 }
114 
115 }  // this_thread
116 
117 struct mutex {};
118 
119 struct timed_mutex
120 {
try_lockstd::timed_mutex121     bool try_lock() {std::cout << "timed_mutex::try_lock()\n"; return true;}
122 
123     template <class Rep, class Period>
try_lock_forstd::timed_mutex124         bool try_lock_for(const boost::chrono::duration<Rep, Period>& d)
125         {
126             boost::chrono::microseconds t = boost::chrono::duration_cast<boost::chrono::microseconds>(d);
127             if (t <= boost::chrono::microseconds(0))
128                 return try_lock();
129             std::cout << "try_lock_for " << t.count() << " microseconds\n";
130             return true;
131         }
132 
133     template <class Clock, class Duration>
try_lock_untilstd::timed_mutex134     bool try_lock_until(const boost::chrono::time_point<Clock, Duration>& t)
135     {
136         using namespace boost::chrono;
137         typedef time_point<Clock, Duration> Time;
138         typedef system_clock::time_point SysTime;
139         if (t <= Clock::now())
140             return try_lock();
141         typedef typename boost::common_type<typename Time::duration,
142           typename Clock::duration>::type D;
143         /* auto */ D d = t - Clock::now();
144         microseconds us = duration_cast<microseconds>(d);
145         SysTime st = system_clock::now() + us;
146         std::cout << "try_lock_until ";
147         __print_time(st);
148         std::cout << " which is " << (st - system_clock::now()).count()
149           << " microseconds away\n";
150         return true;
151     }
152 };
153 
154 struct condition_variable
155 {
156     template <class Rep, class Period>
wait_forstd::condition_variable157         bool wait_for(mutex&, const boost::chrono::duration<Rep, Period>& d)
158         {
159             boost::chrono::microseconds t = boost::chrono::duration_cast<boost::chrono::microseconds>(d);
160             std::cout << "wait_for " << t.count() << " microseconds\n";
161             return true;
162         }
163 
164     template <class Clock, class Duration>
wait_untilstd::condition_variable165     bool wait_until(mutex&, const boost::chrono::time_point<Clock, Duration>& t)
166     {
167         using namespace boost::chrono;
168         typedef time_point<Clock, Duration> Time;
169         typedef system_clock::time_point SysTime;
170         if (t <= Clock::now())
171             return false;
172         typedef typename boost::common_type<typename Time::duration,
173           typename Clock::duration>::type D;
174         /* auto */ D d = t - Clock::now();
175         microseconds us = duration_cast<microseconds>(d);
176         SysTime st = system_clock::now() + us;
177          std::cout << "wait_until     ";
178         __print_time(st);
179         std::cout << " which is " << (st - system_clock::now()).count()
180           << " microseconds away\n";
181         return true;
182     }
183 };
184 
185 } // namespace std
186 
187 //////////////////////////////////////////////////////////
188 //////////// Simple sleep and wait examples //////////////
189 //////////////////////////////////////////////////////////
190 
191 std::mutex m;
192 std::timed_mutex mut;
193 std::condition_variable cv;
194 
basic_examples()195 void basic_examples()
196 {
197     std::cout << "Running basic examples\n";
198     using namespace std;
199     using namespace boost::chrono;
200     system_clock::time_point time_limit = system_clock::now() + seconds(4) + milliseconds(500);
201     this_thread::sleep_for(seconds(3));
202     this_thread::sleep_for(nanoseconds(300));
203     this_thread::sleep_until(time_limit);
204 //    this_thread::sleep_for(time_limit);  // desired compile-time error
205 //    this_thread::sleep_until(seconds(3)); // desired compile-time error
206     mut.try_lock_for(milliseconds(30));
207     mut.try_lock_until(time_limit);
208 //    mut.try_lock_for(time_limit);        // desired compile-time error
209 //    mut.try_lock_until(milliseconds(30)); // desired compile-time error
210     cv.wait_for(m, minutes(1));    // real code would put this in a loop
211     cv.wait_until(m, time_limit);  // real code would put this in a loop
212     // For those who prefer floating point
213     this_thread::sleep_for(duration<double>(0.25));
214     this_thread::sleep_until(system_clock::now() + duration<double>(1.5));
215 }
216 
217 //////////////////////////////////////////////////////////
218 //////////////////// User1 Example ///////////////////////
219 //////////////////////////////////////////////////////////
220 
221 namespace User1
222 {
223 // Example type-safe "physics" code interoperating with boost::chrono::duration types
224 //  and taking advantage of the boost::ratio infrastructure and design philosophy.
225 
226 // length - mimics boost::chrono::duration except restricts representation to double.
227 //    Uses boost::ratio facilities for length units conversions.
228 
229 template <class Ratio>
230 class length
231 {
232 public:
233     typedef Ratio ratio;
234 private:
235     double len_;
236 public:
237 
length()238     length() : len_(1) {}
length(const double & len)239     length(const double& len) : len_(len) {}
240 
241     // conversions
242     template <class R>
length(const length<R> & d)243     length(const length<R>& d)
244             : len_(d.count() * boost::ratio_divide<Ratio, R>::type::den /
245                                boost::ratio_divide<Ratio, R>::type::num) {}
246 
247     // observer
248 
count() const249     double count() const {return len_;}
250 
251     // arithmetic
252 
operator +=(const length & d)253     length& operator+=(const length& d) {len_ += d.count(); return *this;}
operator -=(const length & d)254     length& operator-=(const length& d) {len_ -= d.count(); return *this;}
255 
operator +() const256     length operator+() const {return *this;}
operator -() const257     length operator-() const {return length(-len_);}
258 
operator *=(double rhs)259     length& operator*=(double rhs) {len_ *= rhs; return *this;}
operator /=(double rhs)260     length& operator/=(double rhs) {len_ /= rhs; return *this;}
261 };
262 
263 // Sparse sampling of length units
264 typedef length<boost::ratio<1> >          meter;        // set meter as "unity"
265 typedef length<boost::centi>              centimeter;   // 1/100 meter
266 typedef length<boost::kilo>               kilometer;    // 1000  meters
267 typedef length<boost::ratio<254, 10000> > inch;         // 254/10000 meters
268 // length takes ratio instead of two integral types so that definitions can be made like so:
269 typedef length<boost::ratio_multiply<boost::ratio<12>, inch::ratio>::type>   foot;  // 12 inchs
270 typedef length<boost::ratio_multiply<boost::ratio<5280>, foot::ratio>::type> mile;  // 5280 feet
271 
272 // Need a floating point definition of seconds
273 typedef boost::chrono::duration<double> seconds;                         // unity
274 // Demo of (scientific) support for sub-nanosecond resolutions
275 typedef boost::chrono::duration<double,  boost::pico> picosecond;  // 10^-12 seconds
276 typedef boost::chrono::duration<double, boost::femto> femtosecond; // 10^-15 seconds
277 typedef boost::chrono::duration<double,  boost::atto> attosecond;  // 10^-18 seconds
278 
279 // A very brief proof-of-concept for SIUnits-like library
280 //  Hard-wired to floating point seconds and meters, but accepts other units (shown in testUser1())
281 template <class R1, class R2>
282 class quantity
283 {
284     double q_;
285 public:
quantity()286     quantity() : q_(1) {}
287 
get() const288     double get() const {return q_;}
set(double q)289     void set(double q) {q_ = q;}
290 };
291 
292 template <>
293 class quantity<boost::ratio<1>, boost::ratio<0> >
294 {
295     double q_;
296 public:
quantity()297     quantity() : q_(1) {}
quantity(seconds d)298     quantity(seconds d) : q_(d.count()) {}  // note:  only User1::seconds needed here
299 
get() const300     double get() const {return q_;}
set(double q)301     void set(double q) {q_ = q;}
302 };
303 
304 template <>
305 class quantity<boost::ratio<0>, boost::ratio<1> >
306 {
307     double q_;
308 public:
quantity()309     quantity() : q_(1) {}
quantity(meter d)310     quantity(meter d) : q_(d.count()) {}  // note:  only User1::meter needed here
311 
get() const312     double get() const {return q_;}
set(double q)313     void set(double q) {q_ = q;}
314 };
315 
316 template <>
317 class quantity<boost::ratio<0>, boost::ratio<0> >
318 {
319     double q_;
320 public:
quantity()321     quantity() : q_(1) {}
quantity(double d)322     quantity(double d) : q_(d) {}
323 
get() const324     double get() const {return q_;}
set(double q)325     void set(double q) {q_ = q;}
326 };
327 
328 // Example SI-Units
329 typedef quantity<boost::ratio<0>, boost::ratio<0> >  Scalar;
330 typedef quantity<boost::ratio<1>, boost::ratio<0> >  Time;         // second
331 typedef quantity<boost::ratio<0>, boost::ratio<1> >  Distance;     // meter
332 typedef quantity<boost::ratio<-1>, boost::ratio<1> > Speed;        // meter/second
333 typedef quantity<boost::ratio<-2>, boost::ratio<1> > Acceleration; // meter/second^2
334 
335 template <class R1, class R2, class R3, class R4>
336 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)337 operator/(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
338 {
339     typedef quantity<typename boost::ratio_subtract<R1, R3>::type, typename boost::ratio_subtract<R2, R4>::type> R;
340     R r;
341     r.set(x.get() / y.get());
342     return r;
343 }
344 
345 template <class R1, class R2, class R3, class R4>
346 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)347 operator*(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
348 {
349     typedef quantity<typename boost::ratio_add<R1, R3>::type, typename boost::ratio_add<R2, R4>::type> R;
350     R r;
351     r.set(x.get() * y.get());
352     return r;
353 }
354 
355 template <class R1, class R2>
356 quantity<R1, R2>
operator +(const quantity<R1,R2> & x,const quantity<R1,R2> & y)357 operator+(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
358 {
359     typedef quantity<R1, R2> R;
360     R r;
361     r.set(x.get() + y.get());
362     return r;
363 }
364 
365 template <class R1, class R2>
366 quantity<R1, R2>
operator -(const quantity<R1,R2> & x,const quantity<R1,R2> & y)367 operator-(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
368 {
369     typedef quantity<R1, R2> R;
370     R r;
371     r.set(x.get() - y.get());
372     return r;
373 }
374 
375 // Example type-safe physics function
376 Distance
compute_distance(Speed v0,Time t,Acceleration a)377 compute_distance(Speed v0, Time t, Acceleration a)
378 {
379     return v0 * t + Scalar(.5) * a * t * t;  // if a units mistake is made here it won't compile
380 }
381 
382 } // User1
383 
384 
385 // Exercise example type-safe physics function and show interoperation
386 // of custom time durations (User1::seconds) and standard time durations (std::hours).
387 // Though input can be arbitrary (but type-safe) units, output is always in SI-units
388 //   (a limitation of the simplified Units lib demoed here).
testUser1()389 void testUser1()
390 {
391     std::cout << "*************\n";
392     std::cout << "* testUser1 *\n";
393     std::cout << "*************\n";
394     User1::Distance d( User1::mile(110) );
395     User1::Time t( boost::chrono::hours(2) );
396     User1::Speed s = d / t;
397     std::cout << "Speed = " << s.get() << " meters/sec\n";
398     User1::Acceleration a = User1::Distance( User1::foot(32.2) ) / User1::Time() / User1::Time();
399     std::cout << "Acceleration = " << a.get() << " meters/sec^2\n";
400     User1::Distance df = compute_distance(s, User1::Time( User1::seconds(0.5) ), a);
401     std::cout << "Distance = " << df.get() << " meters\n";
402     std::cout << "There are " << User1::mile::ratio::den << '/' << User1::mile::ratio::num << " miles/meter";
403     User1::meter mt = 1;
404     User1::mile mi = mt;
405     std::cout << " which is approximately " << mi.count() << '\n';
406     std::cout << "There are " << User1::mile::ratio::num << '/' << User1::mile::ratio::den << " meters/mile";
407     mi = 1;
408     mt = mi;
409     std::cout << " which is approximately " << mt.count() << '\n';
410     User1::attosecond as(1);
411     User1::seconds sec = as;
412     std::cout << "1 attosecond is " << sec.count() << " seconds\n";
413     std::cout << "sec = as;  // compiles\n";
414     sec = User1::seconds(1);
415     as = sec;
416     std::cout << "1 second is " << as.count() << " attoseconds\n";
417     std::cout << "as = sec;  // compiles\n";
418     std::cout << "\n";
419 }
420 
421 //////////////////////////////////////////////////////////
422 //////////////////// User2 Example ///////////////////////
423 //////////////////////////////////////////////////////////
424 
425 // Demonstrate User2:
426 // A "saturating" signed integral type  is developed.  This type has +/- infinity and a nan
427 // (like IEEE floating point) but otherwise obeys signed integral arithmetic.
428 // This class is subsequently used as the rep in boost::chrono::duration to demonstrate a
429 // duration class that does not silently ignore overflow.
430 
431 namespace User2
432 {
433 
434 template <class I>
435 class saturate
436 {
437 public:
438     typedef I int_type;
439 
440     static const int_type nan = int_type(int_type(1) << (sizeof(int_type) * CHAR_BIT - 1));
441     static const int_type neg_inf = nan + 1;
442     static const int_type pos_inf = -neg_inf;
443 private:
444     int_type i_;
445 
446 //     static_assert(std::is_integral<int_type>::value && std::is_signed<int_type>::value,
447 //                   "saturate only accepts signed integral types");
448 //     static_assert(nan == -nan && neg_inf < pos_inf,
449 //                   "saturate assumes two's complement hardware for signed integrals");
450 
451 public:
saturate()452     saturate() : i_(nan) {}
saturate(int_type i)453     explicit saturate(int_type i) : i_(i) {}
454     // explicit
455        operator int_type() const;
456 
457     saturate& operator+=(saturate x);
operator -=(saturate x)458     saturate& operator-=(saturate x) {return *this += -x;}
459     saturate& operator*=(saturate x);
460     saturate& operator/=(saturate x);
461     saturate& operator%=(saturate x);
462 
operator -() const463     saturate  operator- () const {return saturate(-i_);}
operator ++()464     saturate& operator++()       {*this += saturate(int_type(1)); return *this;}
operator ++(int)465     saturate  operator++(int)    {saturate tmp(*this); ++(*this); return tmp;}
operator --()466     saturate& operator--()       {*this -= saturate(int_type(1)); return *this;}
operator --(int)467     saturate  operator--(int)    {saturate tmp(*this); --(*this); return tmp;}
468 
operator +(saturate x,saturate y)469     friend saturate operator+(saturate x, saturate y) {return x += y;}
operator -(saturate x,saturate y)470     friend saturate operator-(saturate x, saturate y) {return x -= y;}
operator *(saturate x,saturate y)471     friend saturate operator*(saturate x, saturate y) {return x *= y;}
operator /(saturate x,saturate y)472     friend saturate operator/(saturate x, saturate y) {return x /= y;}
operator %(saturate x,saturate y)473     friend saturate operator%(saturate x, saturate y) {return x %= y;}
474 
operator ==(saturate x,saturate y)475     friend bool operator==(saturate x, saturate y)
476     {
477         if (x.i_ == nan || y.i_ == nan)
478             return false;
479         return x.i_ == y.i_;
480     }
481 
operator !=(saturate x,saturate y)482     friend bool operator!=(saturate x, saturate y) {return !(x == y);}
483 
operator <(saturate x,saturate y)484     friend bool operator<(saturate x, saturate y)
485     {
486         if (x.i_ == nan || y.i_ == nan)
487             return false;
488         return x.i_ < y.i_;
489     }
490 
operator <=(saturate x,saturate y)491     friend bool operator<=(saturate x, saturate y)
492     {
493         if (x.i_ == nan || y.i_ == nan)
494             return false;
495         return x.i_ <= y.i_;
496     }
497 
operator >(saturate x,saturate y)498     friend bool operator>(saturate x, saturate y)
499     {
500         if (x.i_ == nan || y.i_ == nan)
501             return false;
502         return x.i_ > y.i_;
503     }
504 
operator >=(saturate x,saturate y)505     friend bool operator>=(saturate x, saturate y)
506     {
507         if (x.i_ == nan || y.i_ == nan)
508             return false;
509         return x.i_ >= y.i_;
510     }
511 
operator <<(std::ostream & os,saturate s)512     friend std::ostream& operator<<(std::ostream& os, saturate s)
513     {
514         switch (s.i_)
515         {
516         case pos_inf:
517             return os << "inf";
518         case nan:
519             return os << "nan";
520         case neg_inf:
521             return os << "-inf";
522         };
523         return os << s.i_;
524     }
525 };
526 
527 template <class I>
operator int_type() const528 saturate<I>::operator int_type() const
529 {
530     switch (i_)
531     {
532     case nan:
533     case neg_inf:
534     case pos_inf:
535         throw std::out_of_range("saturate special value can not convert to int_type");
536     }
537     return i_;
538 }
539 
540 template <class I>
541 saturate<I>&
operator +=(saturate x)542 saturate<I>::operator+=(saturate x)
543 {
544     switch (i_)
545     {
546     case pos_inf:
547         switch (x.i_)
548         {
549         case neg_inf:
550         case nan:
551             i_ = nan;
552         }
553         return *this;
554     case nan:
555         return *this;
556     case neg_inf:
557         switch (x.i_)
558         {
559         case pos_inf:
560         case nan:
561             i_ = nan;
562         }
563         return *this;
564     }
565     switch (x.i_)
566     {
567     case pos_inf:
568     case neg_inf:
569     case nan:
570         i_ = x.i_;
571         return *this;
572     }
573     if (x.i_ >= 0)
574     {
575         if (i_ < pos_inf - x.i_)
576             i_ += x.i_;
577         else
578             i_ = pos_inf;
579         return *this;
580     }
581     if (i_ > neg_inf - x.i_)
582         i_ += x.i_;
583     else
584         i_ = neg_inf;
585     return *this;
586 }
587 
588 template <class I>
589 saturate<I>&
operator *=(saturate x)590 saturate<I>::operator*=(saturate x)
591 {
592     switch (i_)
593     {
594     case 0:
595         switch (x.i_)
596         {
597         case pos_inf:
598         case neg_inf:
599         case nan:
600             i_ = nan;
601         }
602         return *this;
603     case pos_inf:
604         switch (x.i_)
605         {
606         case nan:
607         case 0:
608             i_ = nan;
609             return *this;
610         }
611         if (x.i_ < 0)
612             i_ = neg_inf;
613         return *this;
614     case nan:
615         return *this;
616     case neg_inf:
617         switch (x.i_)
618         {
619         case nan:
620         case 0:
621             i_ = nan;
622             return *this;
623         }
624         if (x.i_ < 0)
625             i_ = pos_inf;
626         return *this;
627     }
628     switch (x.i_)
629     {
630     case 0:
631         i_ = 0;
632         return *this;
633     case nan:
634         i_ = nan;
635         return *this;
636     case pos_inf:
637         if (i_ < 0)
638             i_ = neg_inf;
639         else
640             i_ = pos_inf;
641         return *this;
642     case neg_inf:
643         if (i_ < 0)
644             i_ = pos_inf;
645         else
646             i_ = neg_inf;
647         return *this;
648     }
649     int s = (i_ < 0 ? -1 : 1) * (x.i_ < 0 ? -1 : 1);
650     i_ = i_ < 0 ? -i_ : i_;
651     int_type x_i_ = x.i_ < 0 ? -x.i_ : x.i_;
652     if (i_ <= pos_inf / x_i_)
653         i_ *= x_i_;
654     else
655         i_ = pos_inf;
656     i_ *= s;
657     return *this;
658 }
659 
660 template <class I>
661 saturate<I>&
operator /=(saturate x)662 saturate<I>::operator/=(saturate x)
663 {
664     switch (x.i_)
665     {
666     case pos_inf:
667     case neg_inf:
668         switch (i_)
669         {
670         case pos_inf:
671         case neg_inf:
672         case nan:
673             i_ = nan;
674             break;
675         default:
676             i_ = 0;
677             break;
678         }
679         return *this;
680     case nan:
681         i_ = nan;
682         return *this;
683     case 0:
684         switch (i_)
685         {
686         case pos_inf:
687         case neg_inf:
688         case nan:
689             return *this;
690         case 0:
691             i_ = nan;
692             return *this;
693         }
694         if (i_ > 0)
695             i_ = pos_inf;
696         else
697             i_ = neg_inf;
698         return *this;
699     }
700     switch (i_)
701     {
702     case 0:
703     case nan:
704         return *this;
705     case pos_inf:
706     case neg_inf:
707         if (x.i_ < 0)
708             i_ = -i_;
709         return *this;
710     }
711     i_ /= x.i_;
712     return *this;
713 }
714 
715 template <class I>
716 saturate<I>&
operator %=(saturate x)717 saturate<I>::operator%=(saturate x)
718 {
719 //    *this -= *this / x * x;  // definition
720     switch (x.i_)
721     {
722     case nan:
723     case neg_inf:
724     case 0:
725     case pos_inf:
726         i_ = nan;
727         return *this;
728     }
729     switch (i_)
730     {
731     case neg_inf:
732     case pos_inf:
733         i_ = nan;
734     case nan:
735         return *this;
736     }
737     i_ %= x.i_;
738     return *this;
739 }
740 
741 // Demo overflow-safe integral durations ranging from picoseconds resolution to millennium resolution
742 typedef boost::chrono::duration<saturate<long long>, boost::pico                 > picoseconds;
743 typedef boost::chrono::duration<saturate<long long>, boost::nano                 > nanoseconds;
744 typedef boost::chrono::duration<saturate<long long>, boost::micro                > microseconds;
745 typedef boost::chrono::duration<saturate<long long>, boost::milli                > milliseconds;
746 typedef boost::chrono::duration<saturate<long long>                            > seconds;
747 typedef boost::chrono::duration<saturate<long long>, boost::ratio<         60LL> > minutes;
748 typedef boost::chrono::duration<saturate<long long>, boost::ratio<       3600LL> > hours;
749 typedef boost::chrono::duration<saturate<long long>, boost::ratio<      86400LL> > days;
750 typedef boost::chrono::duration<saturate<long long>, boost::ratio<   31556952LL> > years;
751 typedef boost::chrono::duration<saturate<long long>, boost::ratio<31556952000LL> > millennium;
752 
753 }  // User2
754 
755 // Demonstrate custom promotion rules (needed only if there are no implicit conversions)
756 namespace User2 { namespace detail {
757 
758 template <class T1, class T2, bool = boost::is_integral<T1>::value>
759 struct promote_helper;
760 
761 template <class T1, class T2>
762 struct promote_helper<T1, saturate<T2>, true>  // integral
763 {
764     typedef typename boost::common_type<T1, T2>::type rep;
765     typedef User2::saturate<rep> type;
766 };
767 
768 template <class T1, class T2>
769 struct promote_helper<T1, saturate<T2>, false>  // floating
770 {
771     typedef T1 type;
772 };
773 
774 } }
775 
776 namespace boost
777 {
778 
779 template <class T1, class T2>
780 struct common_type<User2::saturate<T1>, User2::saturate<T2> >
781 {
782     typedef typename common_type<T1, T2>::type rep;
783     typedef User2::saturate<rep> type;
784 };
785 
786 template <class T1, class T2>
787 struct common_type<T1, User2::saturate<T2> >
788     : User2::detail::promote_helper<T1, User2::saturate<T2> > {};
789 
790 template <class T1, class T2>
791 struct common_type<User2::saturate<T1>, T2>
792     : User2::detail::promote_helper<T2, User2::saturate<T1> > {};
793 
794 
795 // Demonstrate specialization of duration_values:
796 
797 namespace chrono {
798 
799 template <class I>
800 struct duration_values<User2::saturate<I> >
801 {
802     typedef User2::saturate<I> Rep;
803 public:
zeroboost::chrono::duration_values804     static Rep zero() {return Rep(0);}
BOOST_PREVENT_MACRO_SUBSTITUTIONboost::chrono::duration_values805     static Rep max BOOST_PREVENT_MACRO_SUBSTITUTION ()  {return Rep(Rep::pos_inf-1);}
BOOST_PREVENT_MACRO_SUBSTITUTIONboost::chrono::duration_values806     static Rep min BOOST_PREVENT_MACRO_SUBSTITUTION ()  {return -(max) ();}
807 };
808 
809 }  // namespace chrono
810 
811 }  // namespace boost
812 
813 
testUser2()814 void testUser2()
815 {
816     std::cout << "*************\n";
817     std::cout << "* testUser2 *\n";
818     std::cout << "*************\n";
819     using namespace User2;
820     typedef seconds::rep sat;
821     years yr(sat(100));
822     std::cout << "100 years expressed as years = " << yr.count() << '\n';
823     nanoseconds ns = yr;
824     std::cout << "100 years expressed as nanoseconds = " << ns.count() << '\n';
825     ns += yr;
826     std::cout << "200 years expressed as nanoseconds = " << ns.count() << '\n';
827     ns += yr;
828     std::cout << "300 years expressed as nanoseconds = " << ns.count() << '\n';
829 //    yr = ns;  // does not compile
830     std::cout << "yr = ns;  // does not compile\n";
831 //    picoseconds ps1 = yr;  // does not compile, compile-time overflow in ratio arithmetic
832     std::cout << "ps = yr;  // does not compile\n";
833     ns = yr;
834     picoseconds ps = ns;
835     std::cout << "100 years expressed as picoseconds = " << ps.count() << '\n';
836     ps = ns / sat(1000);
837     std::cout << "0.1 years expressed as picoseconds = " << ps.count() << '\n';
838     yr = years(sat(-200000000));
839     std::cout << "200 million years ago encoded in years: " << yr.count() << '\n';
840     days d = boost::chrono::duration_cast<days>(yr);
841     std::cout << "200 million years ago encoded in days: " << d.count() << '\n';
842     millennium c = boost::chrono::duration_cast<millennium>(yr);
843     std::cout << "200 million years ago encoded in millennium: " << c.count() << '\n';
844     std::cout << "Demonstrate \"uninitialized protection\" behavior:\n";
845     seconds sec;
846     for (++sec; sec < seconds(sat(10)); ++sec)
847         ;
848     std::cout << sec.count() << '\n';
849     std::cout << "\n";
850 }
851 
testStdUser()852 void testStdUser()
853 {
854     std::cout << "***************\n";
855     std::cout << "* testStdUser *\n";
856     std::cout << "***************\n";
857     using namespace boost::chrono;
858     hours hr = hours(100);
859     std::cout << "100 hours expressed as hours = " << hr.count() << '\n';
860     nanoseconds ns = hr;
861     std::cout << "100 hours expressed as nanoseconds = " << ns.count() << '\n';
862     ns += hr;
863     std::cout << "200 hours expressed as nanoseconds = " << ns.count() << '\n';
864     ns += hr;
865     std::cout << "300 hours expressed as nanoseconds = " << ns.count() << '\n';
866 //    hr = ns;  // does not compile
867     std::cout << "hr = ns;  // does not compile\n";
868 //    hr * ns;  // does not compile
869     std::cout << "hr * ns;  // does not compile\n";
870     duration<double> fs(2.5);
871     std::cout << "duration<double> has count() = " << fs.count() << '\n';
872 //    seconds sec = fs;  // does not compile
873     std::cout << "seconds sec = duration<double> won't compile\n";
874     seconds sec = duration_cast<seconds>(fs);
875     std::cout << "seconds has count() = " << sec.count() << '\n';
876     std::cout << "\n";
877 }
878 
879 //  timeval clock demo
880 //     Demonstrate the use of a timeval-like struct to be used as the representation
881 //     type for both duraiton and time_point.
882 
883 namespace timeval_demo
884 {
885 
886 class xtime {
887 private:
888     long tv_sec;
889     long tv_usec;
890 
fixup()891     void fixup() {
892         if (tv_usec < 0) {
893             tv_usec += 1000000;
894             --tv_sec;
895         }
896     }
897 
898 public:
899 
xtime(long sec,long usec)900     explicit xtime(long sec, long usec) {
901         tv_sec = sec;
902         tv_usec = usec;
903         if (tv_usec < 0 || tv_usec >= 1000000) {
904             tv_sec += tv_usec / 1000000;
905             tv_usec %= 1000000;
906             fixup();
907         }
908     }
909 
xtime(long long usec)910     explicit xtime(long long usec)
911     {
912         tv_usec = static_cast<long>(usec % 1000000);
913         tv_sec  = static_cast<long>(usec / 1000000);
914         fixup();
915     }
916 
917     // explicit
operator long long() const918     operator long long() const {return static_cast<long long>(tv_sec) * 1000000 + tv_usec;}
919 
operator +=(xtime rhs)920     xtime& operator += (xtime rhs) {
921         tv_sec += rhs.tv_sec;
922         tv_usec += rhs.tv_usec;
923         if (tv_usec >= 1000000) {
924             tv_usec -= 1000000;
925             ++tv_sec;
926         }
927         return *this;
928     }
929 
operator -=(xtime rhs)930     xtime& operator -= (xtime rhs) {
931         tv_sec -= rhs.tv_sec;
932         tv_usec -= rhs.tv_usec;
933         fixup();
934         return *this;
935     }
936 
operator %=(xtime rhs)937     xtime& operator %= (xtime rhs) {
938         long long t = tv_sec * 1000000 + tv_usec;
939         long long r = rhs.tv_sec * 1000000 + rhs.tv_usec;
940         t %= r;
941         tv_sec = static_cast<long>(t / 1000000);
942         tv_usec = static_cast<long>(t % 1000000);
943         fixup();
944         return *this;
945     }
946 
operator +(xtime x,xtime y)947     friend xtime operator+(xtime x, xtime y) {return x += y;}
operator -(xtime x,xtime y)948     friend xtime operator-(xtime x, xtime y) {return x -= y;}
operator %(xtime x,xtime y)949     friend xtime operator%(xtime x, xtime y) {return x %= y;}
950 
operator ==(xtime x,xtime y)951     friend bool operator==(xtime x, xtime y)
952         { return (x.tv_sec == y.tv_sec && x.tv_usec == y.tv_usec); }
953 
operator <(xtime x,xtime y)954     friend bool operator<(xtime x, xtime y) {
955         if (x.tv_sec == y.tv_sec)
956             return (x.tv_usec < y.tv_usec);
957         return (x.tv_sec < y.tv_sec);
958     }
959 
operator !=(xtime x,xtime y)960     friend bool operator!=(xtime x, xtime y) { return !(x == y); }
operator >(xtime x,xtime y)961     friend bool operator> (xtime x, xtime y) { return y < x; }
operator <=(xtime x,xtime y)962     friend bool operator<=(xtime x, xtime y) { return !(y < x); }
operator >=(xtime x,xtime y)963     friend bool operator>=(xtime x, xtime y) { return !(x < y); }
964 
operator <<(std::ostream & os,xtime x)965     friend std::ostream& operator<<(std::ostream& os, xtime x)
966         {return os << '{' << x.tv_sec << ',' << x.tv_usec << '}';}
967 };
968 
969 class xtime_clock
970 {
971 public:
972     typedef xtime                                  rep;
973     typedef boost::micro                           period;
974     typedef boost::chrono::duration<rep, period>   duration;
975     typedef boost::chrono::time_point<xtime_clock> time_point;
976 
977     static time_point now();
978 };
979 
980 xtime_clock::time_point
now()981 xtime_clock::now()
982 {
983     time_point t(duration(xtime(0)));
984     gettimeofday((timeval*)&t, 0);
985     return t;
986 }
987 
test_xtime_clock()988 void test_xtime_clock()
989 {
990     using namespace boost::chrono;
991     std::cout << "timeval_demo system clock test\n";
992     std::cout << "sizeof xtime_clock::time_point = " << sizeof(xtime_clock::time_point) << '\n';
993     std::cout << "sizeof xtime_clock::duration = " << sizeof(xtime_clock::duration) << '\n';
994     std::cout << "sizeof xtime_clock::rep = " << sizeof(xtime_clock::rep) << '\n';
995     xtime_clock::duration delay(milliseconds(5));
996     xtime_clock::time_point start = xtime_clock::now();
997     while (xtime_clock::now() - start <= delay)
998     {
999     }
1000     xtime_clock::time_point stop = xtime_clock::now();
1001     xtime_clock::duration elapsed = stop - start;
1002     std::cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n";
1003 }
1004 
1005 }  // timeval_demo
1006 
1007 // Handle duration with resolution not known until run time
1008 
1009 namespace runtime_resolution
1010 {
1011 
1012 class duration
1013 {
1014 public:
1015     typedef long long rep;
1016 private:
1017     rep rep_;
1018 
1019     static const double ticks_per_nanosecond;
1020 
1021 public:
1022     typedef boost::chrono::duration<double, boost::nano> tonanosec;
1023 
duration()1024     duration() {} // = default;
duration(const rep & r)1025     explicit duration(const rep& r) : rep_(r) {}
1026 
1027     // conversions
duration(const tonanosec & d)1028     explicit duration(const tonanosec& d)
1029             : rep_(static_cast<rep>(d.count() * ticks_per_nanosecond)) {}
1030 
1031     // explicit
operator tonanosec() const1032        operator tonanosec() const {return tonanosec(rep_/ticks_per_nanosecond);}
1033 
1034     // observer
1035 
count() const1036     rep count() const {return rep_;}
1037 
1038     // arithmetic
1039 
operator +=(const duration & d)1040     duration& operator+=(const duration& d) {rep_ += d.rep_; return *this;}
operator -=(const duration & d)1041     duration& operator-=(const duration& d) {rep_ += d.rep_; return *this;}
operator *=(rep rhs)1042     duration& operator*=(rep rhs)           {rep_ *= rhs; return *this;}
operator /=(rep rhs)1043     duration& operator/=(rep rhs)           {rep_ /= rhs; return *this;}
1044 
operator +() const1045     duration  operator+() const {return *this;}
operator -() const1046     duration  operator-() const {return duration(-rep_);}
operator ++()1047     duration& operator++()      {++rep_; return *this;}
operator ++(int)1048     duration  operator++(int)   {return duration(rep_++);}
operator --()1049     duration& operator--()      {--rep_; return *this;}
operator --(int)1050     duration  operator--(int)   {return duration(rep_--);}
1051 
operator +(duration x,duration y)1052     friend duration operator+(duration x, duration y) {return x += y;}
operator -(duration x,duration y)1053     friend duration operator-(duration x, duration y) {return x -= y;}
operator *(duration x,rep y)1054     friend duration operator*(duration x, rep y)      {return x *= y;}
operator *(rep x,duration y)1055     friend duration operator*(rep x, duration y)      {return y *= x;}
operator /(duration x,rep y)1056     friend duration operator/(duration x, rep y)      {return x /= y;}
1057 
operator ==(duration x,duration y)1058     friend bool operator==(duration x, duration y) {return x.rep_ == y.rep_;}
operator !=(duration x,duration y)1059     friend bool operator!=(duration x, duration y) {return !(x == y);}
operator <(duration x,duration y)1060     friend bool operator< (duration x, duration y) {return x.rep_ < y.rep_;}
operator <=(duration x,duration y)1061     friend bool operator<=(duration x, duration y) {return !(y < x);}
operator >(duration x,duration y)1062     friend bool operator> (duration x, duration y) {return y < x;}
operator >=(duration x,duration y)1063     friend bool operator>=(duration x, duration y) {return !(x < y);}
1064 };
1065 
1066 static
1067 double
init_duration()1068 init_duration()
1069 {
1070     //mach_timebase_info_data_t MachInfo;
1071     //mach_timebase_info(&MachInfo);
1072     //return static_cast<double>(MachInfo.denom) / MachInfo.numer;
1073     return static_cast<double>(1) / 1000; // Windows FILETIME is 1 per microsec
1074 }
1075 
1076 const double duration::ticks_per_nanosecond = init_duration();
1077 
1078 class clock;
1079 
1080 class time_point
1081 {
1082 public:
1083     typedef runtime_resolution::clock clock;
1084     typedef long long rep;
1085 private:
1086     rep rep_;
1087 
1088 
count() const1089     rep count() const {return rep_;}
1090 public:
1091 
time_point()1092     time_point() : rep_(0) {}
time_point(const duration & d)1093     explicit time_point(const duration& d)
1094         : rep_(d.count()) {}
1095 
1096     // arithmetic
1097 
operator +=(const duration & d)1098     time_point& operator+=(const duration& d) {rep_ += d.count(); return *this;}
operator -=(const duration & d)1099     time_point& operator-=(const duration& d) {rep_ -= d.count(); return *this;}
1100 
operator +(time_point x,duration y)1101     friend time_point operator+(time_point x, duration y) {return x += y;}
operator +(duration x,time_point y)1102     friend time_point operator+(duration x, time_point y) {return y += x;}
operator -(time_point x,duration y)1103     friend time_point operator-(time_point x, duration y) {return x -= y;}
operator -(time_point x,time_point y)1104     friend duration operator-(time_point x, time_point y) {return duration(x.rep_ - y.rep_);}
1105 };
1106 
1107 class clock
1108 {
1109 public:
1110     typedef duration::rep rep;
1111     typedef runtime_resolution::duration duration;
1112     typedef runtime_resolution::time_point time_point;
1113 
now()1114     static time_point now()
1115     {
1116       timeval tv;
1117       gettimeofday( &tv, 0 );
1118       return time_point(duration((static_cast<rep>(tv.tv_sec)<<32) | tv.tv_usec));
1119     }
1120 };
1121 
test()1122 void test()
1123 {
1124     using namespace boost::chrono;
1125     std::cout << "runtime_resolution test\n";
1126     clock::duration delay(boost::chrono::milliseconds(5));
1127     clock::time_point start = clock::now();
1128     while (clock::now() - start <= delay)
1129       ;
1130     clock::time_point stop = clock::now();
1131     clock::duration elapsed = stop - start;
1132     std::cout << "paused " << nanoseconds(duration_cast<nanoseconds>(duration::tonanosec(elapsed))).count()
1133                            << " nanoseconds\n";
1134 }
1135 
1136 }  // runtime_resolution
1137 
1138 // miscellaneous tests and demos:
1139 
1140 
1141 using namespace boost::chrono;
1142 
physics_function(duration<double> d)1143 void physics_function(duration<double> d)
1144 {
1145     std::cout << "d = " << d.count() << '\n';
1146 }
1147 
drive_physics_function()1148 void drive_physics_function()
1149 {
1150     physics_function(nanoseconds(3));
1151     physics_function(hours(3));
1152     physics_function(duration<double>(2./3));
1153     std::cout.precision(16);
1154     physics_function( hours(3) + nanoseconds(-3) );
1155 }
1156 
test_range()1157 void test_range()
1158 {
1159     using namespace boost::chrono;
1160     hours h1 = hours(24 * ( 365 * 292 + 292/4));
1161     nanoseconds n1 = h1 + nanoseconds(1);
1162     nanoseconds delta = n1 - h1;
1163     std::cout << "292 years of hours = " << h1.count() << "hr\n";
1164     std::cout << "Add a nanosecond = " << n1.count() << "ns\n";
1165     std::cout << "Find the difference = " << delta.count() << "ns\n";
1166 }
1167 
test_extended_range()1168 void test_extended_range()
1169 {
1170     using namespace boost::chrono;
1171     hours h1 = hours(24 * ( 365 * 244000 + 244000/4));
1172     /*auto*/ microseconds u1 = h1 + microseconds(1);
1173     /*auto*/ microseconds delta = u1 - h1;
1174     std::cout << "244,000 years of hours = " << h1.count() << "hr\n";
1175     std::cout << "Add a microsecond = " << u1.count() << "us\n";
1176     std::cout << "Find the difference = " << delta.count() << "us\n";
1177 }
1178 
1179 template <class Rep, class Period>
inspect_duration(boost::chrono::duration<Rep,Period> d,const std::string & name)1180 void inspect_duration(boost::chrono::duration<Rep, Period> d, const std::string& name)
1181 {
1182     typedef boost::chrono::duration<Rep, Period> Duration;
1183     std::cout << "********* " << name << " *********\n";
1184     std::cout << "The period of " << name << " is " << (double)Period::num/Period::den << " seconds.\n";
1185     std::cout << "The frequency of " << name << " is " << (double)Period::den/Period::num << " Hz.\n";
1186     std::cout << "The representation is ";
1187     if (boost::is_floating_point<Rep>::value)
1188     {
1189         std::cout << "floating point\n";
1190         std::cout << "The precision is the most significant ";
1191         std::cout << std::numeric_limits<Rep>::digits10 << " decimal digits.\n";
1192     }
1193     else if (boost::is_integral<Rep>::value)
1194     {
1195         std::cout << "integral\n";
1196         d = Duration(Rep(1));
1197         boost::chrono::duration<double> dsec = d;
1198         std::cout << "The precision is " << dsec.count() << " seconds.\n";
1199     }
1200     else
1201     {
1202         std::cout << "a class type\n";
1203         d = Duration(Rep(1));
1204         boost::chrono::duration<double> dsec = d;
1205         std::cout << "The precision is " << dsec.count() << " seconds.\n";
1206     }
1207     d = Duration((std::numeric_limits<Rep>::max)());
1208     using namespace boost::chrono;
1209     using namespace std;
1210     typedef duration<double, boost::ratio_multiply<boost::ratio<24*3652425,10000>, hours::period>::type> Years;
1211     Years years = d;
1212     std::cout << "The range is +/- " << years.count() << " years.\n";
1213     std::cout << "sizeof(" << name << ") = " << sizeof(d) << '\n';
1214 }
1215 
inspect_all()1216 void inspect_all()
1217 {
1218     using namespace boost::chrono;
1219     std::cout.precision(6);
1220     inspect_duration(nanoseconds(), "nanoseconds");
1221     inspect_duration(microseconds(), "microseconds");
1222     inspect_duration(milliseconds(), "milliseconds");
1223     inspect_duration(seconds(), "seconds");
1224     inspect_duration(minutes(), "minutes");
1225     inspect_duration(hours(), "hours");
1226     inspect_duration(duration<double>(), "duration<double>");
1227 }
1228 
test_milliseconds()1229 void test_milliseconds()
1230 {
1231     using namespace boost::chrono;
1232     milliseconds ms(250);
1233     ms += milliseconds(1);
1234     milliseconds ms2(150);
1235     milliseconds msdiff = ms - ms2;
1236     if (msdiff == milliseconds(101))
1237         std::cout << "success\n";
1238     else
1239         std::cout << "failure: " << msdiff.count() << '\n';
1240 }
1241 
1242     using namespace std;
1243     using namespace boost::chrono;
1244 
1245 // Example round_up utility:  converts d to To, rounding up for inexact conversions
1246 //   Being able to *easily* write this function is a major feature!
1247 template <class To, class Rep, class Period>
1248 To
1249 round_up(duration<Rep, Period> d)
1250 {
1251     To result = duration_cast<To>(d);
1252     if (result < d)
1253         ++result;
1254     return result;
1255 }
1256 
1257 // demonstrate interaction with xtime-like facility:
1258 
1259 using namespace boost::chrono;
1260 
1261 struct xtime
1262 {
1263     long sec;
1264     unsigned long usec;
1265 };
1266 
1267 template <class Rep, class Period>
1268 xtime
to_xtime_truncate(duration<Rep,Period> d)1269 to_xtime_truncate(duration<Rep, Period> d)
1270 {
1271     xtime xt;
1272     xt.sec = static_cast<long>(duration_cast<seconds>(d).count());
1273     xt.usec = static_cast<long>(duration_cast<microseconds>(d - seconds(xt.sec)).count());
1274     return xt;
1275 }
1276 
1277 template <class Rep, class Period>
1278 xtime
to_xtime_round_up(duration<Rep,Period> d)1279 to_xtime_round_up(duration<Rep, Period> d)
1280 {
1281     xtime xt;
1282     xt.sec = static_cast<long>(duration_cast<seconds>(d).count());
1283     xt.usec = static_cast<unsigned long>(round_up<microseconds>(d - seconds(xt.sec)).count());
1284     return xt;
1285 }
1286 
1287 microseconds
from_xtime(xtime xt)1288 from_xtime(xtime xt)
1289 {
1290     return seconds(xt.sec) + microseconds(xt.usec);
1291 }
1292 
print(xtime xt)1293 void print(xtime xt)
1294 {
1295     cout << '{' << xt.sec << ',' << xt.usec << "}\n";
1296 }
1297 
test_with_xtime()1298 void test_with_xtime()
1299 {
1300     cout << "test_with_xtime\n";
1301     xtime xt = to_xtime_truncate(seconds(3) + milliseconds(251));
1302     print(xt);
1303     milliseconds ms = duration_cast<milliseconds>(from_xtime(xt));
1304     cout << ms.count() << " milliseconds\n";
1305     xt = to_xtime_round_up(ms);
1306     print(xt);
1307     xt = to_xtime_truncate(seconds(3) + nanoseconds(999));
1308     print(xt);
1309     xt = to_xtime_round_up(seconds(3) + nanoseconds(999));
1310     print(xt);
1311 }
1312 
test_system_clock()1313 void test_system_clock()
1314 {
1315     cout << "system_clock test" << endl;
1316     system_clock::duration delay = milliseconds(5);
1317     system_clock::time_point start = system_clock::now();
1318     while (system_clock::now() - start <= delay)
1319         ;
1320     system_clock::time_point stop = system_clock::now();
1321     system_clock::duration elapsed = stop - start;
1322     cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n";
1323     start = system_clock::now();
1324     stop = system_clock::now();
1325     cout << "system_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n";
1326 }
1327 
test_steady_clock()1328 void test_steady_clock()
1329 {
1330     cout << "steady_clock test" << endl;
1331     steady_clock::duration delay = milliseconds(5);
1332     steady_clock::time_point start = steady_clock::now();
1333     while (steady_clock::now() - start <= delay)
1334         ;
1335     steady_clock::time_point stop = steady_clock::now();
1336     steady_clock::duration elapsed = stop - start;
1337     cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n";
1338     start = steady_clock::now();
1339     stop = steady_clock::now();
1340     cout << "steady_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n";
1341 }
1342 
test_hi_resolution_clock()1343 void test_hi_resolution_clock()
1344 {
1345     cout << "high_resolution_clock test" << endl;
1346     high_resolution_clock::duration delay = milliseconds(5);
1347     high_resolution_clock::time_point start = high_resolution_clock::now();
1348     while (high_resolution_clock::now() - start <= delay)
1349       ;
1350     high_resolution_clock::time_point stop = high_resolution_clock::now();
1351     high_resolution_clock::duration elapsed = stop - start;
1352     cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n";
1353     start = high_resolution_clock::now();
1354     stop = high_resolution_clock::now();
1355     cout << "high_resolution_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n";
1356 }
1357 
1358 //void test_mixed_clock()
1359 //{
1360 //    cout << "mixed clock test" << endl;
1361 //    high_resolution_clock::time_point hstart = high_resolution_clock::now();
1362 //    cout << "Add 5 milliseconds to a high_resolution_clock::time_point\n";
1363 //    steady_clock::time_point mend = hstart + milliseconds(5);
1364 //    bool b = hstart == mend;
1365 //    system_clock::time_point sstart = system_clock::now();
1366 //    std::cout << "Subtracting system_clock::time_point from steady_clock::time_point doesn't compile\n";
1367 ////  mend - sstart; // doesn't compile
1368 //    cout << "subtract high_resolution_clock::time_point from steady_clock::time_point"
1369 //            " and add that to a system_clock::time_point\n";
1370 //    system_clock::time_point send = sstart + duration_cast<system_clock::duration>(mend - hstart);
1371 //    cout << "subtract two system_clock::time_point's and output that in microseconds:\n";
1372 //    microseconds ms = send - sstart;
1373 //    cout << ms.count() << " microseconds\n";
1374 //}
1375 //
1376 //void test_c_mapping()
1377 //{
1378 //    cout << "C map test\n";
1379 //    using namespace boost::chrono;
1380 //    system_clock::time_point t1 = system_clock::now();
1381 //    std::time_t c_time = system_clock::to_time_t(t1);
1382 //    std::tm* tmptr = std::localtime(&c_time);
1383 //    std::cout << "It is now " << tmptr->tm_hour << ':' << tmptr->tm_min << ':' << tmptr->tm_sec << ' '
1384 //              << tmptr->tm_year + 1900 << '-' << tmptr->tm_mon + 1 << '-' << tmptr->tm_mday << '\n';
1385 //    c_time = std::mktime(tmptr);
1386 //    system_clock::time_point t2 = system_clock::from_time_t(c_time);
1387 //    microseconds ms = t1 - t2;
1388 //    std::cout << "Round-tripping through the C interface truncated the precision by " << ms.count() << " microseconds\n";
1389 //}
1390 
test_duration_division()1391 void test_duration_division()
1392 {
1393     cout << hours(3) / milliseconds(5) << '\n';
1394     cout << milliseconds(5) / hours(3) << '\n';
1395     cout << hours(1) / milliseconds(1) << '\n';
1396 }
1397 
1398 namespace I_dont_like_the_default_duration_behavior
1399 {
1400 
1401 // Here's how you override the duration's default constructor to do anything you want (in this case zero)
1402 
1403 template <class R>
1404 class zero_default
1405 {
1406 public:
1407     typedef R rep;
1408 
1409 private:
1410     rep rep_;
1411 public:
zero_default(rep i=0)1412     zero_default(rep i = 0) : rep_(i) {}
operator rep() const1413     operator rep() const {return rep_;}
1414 
operator +=(zero_default x)1415     zero_default& operator+=(zero_default x) {rep_ += x.rep_; return *this;}
operator -=(zero_default x)1416     zero_default& operator-=(zero_default x) {rep_ -= x.rep_; return *this;}
operator *=(zero_default x)1417     zero_default& operator*=(zero_default x) {rep_ *= x.rep_; return *this;}
operator /=(zero_default x)1418     zero_default& operator/=(zero_default x) {rep_ /= x.rep_; return *this;}
1419 
operator +() const1420     zero_default  operator+ () const {return *this;}
operator -() const1421     zero_default  operator- () const {return zero_default(-rep_);}
operator ++()1422     zero_default& operator++()       {++rep_; return *this;}
operator ++(int)1423     zero_default  operator++(int)    {return zero_default(rep_++);}
operator --()1424     zero_default& operator--()       {--rep_; return *this;}
operator --(int)1425     zero_default  operator--(int)    {return zero_default(rep_--);}
1426 
operator +(zero_default x,zero_default y)1427     friend zero_default operator+(zero_default x, zero_default y) {return x += y;}
operator -(zero_default x,zero_default y)1428     friend zero_default operator-(zero_default x, zero_default y) {return x -= y;}
operator *(zero_default x,zero_default y)1429     friend zero_default operator*(zero_default x, zero_default y) {return x *= y;}
operator /(zero_default x,zero_default y)1430     friend zero_default operator/(zero_default x, zero_default y) {return x /= y;}
1431 
operator ==(zero_default x,zero_default y)1432     friend bool operator==(zero_default x, zero_default y) {return x.rep_ == y.rep_;}
operator !=(zero_default x,zero_default y)1433     friend bool operator!=(zero_default x, zero_default y) {return !(x == y);}
operator <(zero_default x,zero_default y)1434     friend bool operator< (zero_default x, zero_default y) {return x.rep_ < y.rep_;}
operator <=(zero_default x,zero_default y)1435     friend bool operator<=(zero_default x, zero_default y) {return !(y < x);}
operator >(zero_default x,zero_default y)1436     friend bool operator> (zero_default x, zero_default y) {return y < x;}
operator >=(zero_default x,zero_default y)1437     friend bool operator>=(zero_default x, zero_default y) {return !(x < y);}
1438 };
1439 
1440 typedef boost::chrono::duration<zero_default<long long>, boost::nano        > nanoseconds;
1441 typedef boost::chrono::duration<zero_default<long long>, boost::micro       > microseconds;
1442 typedef boost::chrono::duration<zero_default<long long>, boost::milli       > milliseconds;
1443 typedef boost::chrono::duration<zero_default<long long>                   > seconds;
1444 typedef boost::chrono::duration<zero_default<long long>, boost::ratio<60>   > minutes;
1445 typedef boost::chrono::duration<zero_default<long long>, boost::ratio<3600> > hours;
1446 
test()1447 void test()
1448 {
1449     milliseconds ms;
1450     cout << ms.count() << '\n';
1451 }
1452 
1453 }  // I_dont_like_the_default_duration_behavior
1454 
1455 // Build a min for two time_points
1456 
1457 template <class Rep, class Period>
1458 void
print_duration(ostream & os,duration<Rep,Period> d)1459 print_duration(ostream& os, duration<Rep, Period> d)
1460 {
1461     os << d.count() << " * " << Period::num << '/' << Period::den << " seconds\n";
1462 }
1463 
1464 // Example min utility:  returns the earliest time_point
1465 //   Being able to *easily* write this function is a major feature!
1466 template <class Clock, class Duration1, class Duration2>
1467 inline
1468 typename boost::common_type<time_point<Clock, Duration1>,
1469                      time_point<Clock, Duration2> >::type
BOOST_PREVENT_MACRO_SUBSTITUTION(time_point<Clock,Duration1> t1,time_point<Clock,Duration2> t2)1470 min BOOST_PREVENT_MACRO_SUBSTITUTION (time_point<Clock, Duration1> t1, time_point<Clock, Duration2> t2)
1471 {
1472     return t2 < t1 ? t2 : t1;
1473 }
1474 
test_min()1475 void test_min()
1476 {
1477     typedef time_point<system_clock,
1478       boost::common_type<system_clock::duration, seconds>::type> T1;
1479     typedef time_point<system_clock,
1480       boost::common_type<system_clock::duration, nanoseconds>::type> T2;
1481     typedef boost::common_type<T1, T2>::type T3;
1482     /*auto*/ T1 t1 = system_clock::now() + seconds(3);
1483     /*auto*/ T2 t2 = system_clock::now() + nanoseconds(3);
1484     /*auto*/ T3 t3 = (min)(t1, t2);
1485     print_duration(cout, t1 - t3);
1486     print_duration(cout, t2 - t3);
1487 }
1488 
explore_limits()1489 void explore_limits()
1490 {
1491     typedef duration<long long, boost::ratio_multiply<boost::ratio<24*3652425,10000>,
1492       hours::period>::type> Years;
1493     steady_clock::time_point t1( Years(250));
1494     steady_clock::time_point t2(-Years(250));
1495     // nanosecond resolution is likely to overflow.  "up cast" to microseconds.
1496     //   The "up cast" trades precision for range.
1497     microseconds d = time_point_cast<microseconds>(t1) - time_point_cast<microseconds>(t2);
1498     cout << d.count() << " microseconds\n";
1499 }
1500 
manipulate_clock_object(system_clock clock)1501 void manipulate_clock_object(system_clock clock)
1502 {
1503     system_clock::duration delay = milliseconds(5);
1504     system_clock::time_point start = clock.now();
1505     while (clock.now() - start <= delay)
1506       ;
1507     system_clock::time_point stop = clock.now();
1508     system_clock::duration elapsed = stop - start;
1509     cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n";
1510 };
1511 
1512 template <long long speed>
1513 struct cycle_count
1514 {
1515     typedef typename boost::ratio_multiply<boost::ratio<speed>, boost::mega>::type frequency;  // Mhz
1516     typedef typename boost::ratio_divide<boost::ratio<1>, frequency>::type period;
1517     typedef long long rep;
1518     typedef boost::chrono::duration<rep, period> duration;
1519     typedef boost::chrono::time_point<cycle_count> time_point;
1520 
nowcycle_count1521     static time_point now()
1522     {
1523         static long long tick = 0;
1524         // return exact cycle count
1525         return time_point(duration(++tick));  // fake access to clock cycle count
1526     }
1527 };
1528 
1529 template <long long speed>
1530 struct approx_cycle_count
1531 {
1532     static const long long frequency = speed * 1000000;  // MHz
1533     typedef nanoseconds duration;
1534     typedef duration::rep rep;
1535     typedef duration::period period;
1536     static const long long nanosec_per_sec = period::den;
1537     typedef boost::chrono::time_point<approx_cycle_count> time_point;
1538 
nowapprox_cycle_count1539     static time_point now()
1540     {
1541         static long long tick = 0;
1542         // return cycle count as an approximate number of nanoseconds
1543         // compute as if nanoseconds is only duration in the std::lib
1544         return time_point(duration(++tick * nanosec_per_sec / frequency));
1545     }
1546 };
1547 
cycle_count_delay()1548 void cycle_count_delay()
1549 {
1550     {
1551     typedef cycle_count<400> clock;
1552     cout << "\nSimulated " << clock::frequency::num / boost::mega::num << "MHz clock which has a tick period of "
1553          << duration<double, boost::nano>(clock::duration(1)).count() << " nanoseconds\n";
1554     nanoseconds delayns(500);
1555     clock::duration delay = duration_cast<clock::duration>(delayns);
1556     cout << "delay = " << delayns.count() << " nanoseconds which is " << delay.count() << " cycles\n";
1557     clock::time_point start = clock::now();
1558     clock::time_point stop = start + delay;
1559     while (clock::now() < stop)  // no multiplies or divides in this loop
1560         ;
1561     clock::time_point end = clock::now();
1562     clock::duration elapsed = end - start;
1563     cout << "paused " << elapsed.count() << " cycles ";
1564     cout << "which is " << duration_cast<nanoseconds>(elapsed).count() << " nanoseconds\n";
1565     }
1566     {
1567     typedef approx_cycle_count<400> clock;
1568     cout << "\nSimulated " << clock::frequency / 1000000 << "MHz clock modeled with nanoseconds\n";
1569     clock::duration delay = nanoseconds(500);
1570     cout << "delay = " << delay.count() << " nanoseconds\n";
1571     clock::time_point start = clock::now();
1572     clock::time_point stop = start + delay;
1573     while (clock::now() < stop) // 1 multiplication and 1 division in this loop
1574         ;
1575     clock::time_point end = clock::now();
1576     clock::duration elapsed = end - start;
1577     cout << "paused " << elapsed.count() << " nanoseconds\n";
1578     }
1579     {
1580     typedef cycle_count<1500> clock;
1581     cout << "\nSimulated " << clock::frequency::num / boost::mega::num << "MHz clock which has a tick period of "
1582          << duration<double, boost::nano>(clock::duration(1)).count() << " nanoseconds\n";
1583     nanoseconds delayns(500);
1584     clock::duration delay = duration_cast<clock::duration>(delayns);
1585     cout << "delay = " << delayns.count() << " nanoseconds which is " << delay.count() << " cycles\n";
1586     clock::time_point start = clock::now();
1587     clock::time_point stop = start + delay;
1588     while (clock::now() < stop)  // no multiplies or divides in this loop
1589         ;
1590     clock::time_point end = clock::now();
1591     clock::duration elapsed = end - start;
1592     cout << "paused " << elapsed.count() << " cycles ";
1593     cout << "which is " << duration_cast<nanoseconds>(elapsed).count() << " nanoseconds\n";
1594     }
1595     {
1596     typedef approx_cycle_count<1500> clock;
1597     cout << "\nSimulated " << clock::frequency / 1000000 << "MHz clock modeled with nanoseconds\n";
1598     clock::duration delay = nanoseconds(500);
1599     cout << "delay = " << delay.count() << " nanoseconds\n";
1600     clock::time_point start = clock::now();
1601     clock::time_point stop = start + delay;
1602     while (clock::now() < stop) // 1 multiplication and 1 division in this loop
1603         ;
1604     clock::time_point end = clock::now();
1605     clock::duration elapsed = end - start;
1606     cout << "paused " << elapsed.count() << " nanoseconds\n";
1607     }
1608 }
1609 
test_special_values()1610 void test_special_values()
1611 {
1612     std::cout << "duration<unsigned>::min().count()  = " << (duration<unsigned>::min)().count() << '\n';
1613     std::cout << "duration<unsigned>::zero().count() = " << duration<unsigned>::zero().count() << '\n';
1614     std::cout << "duration<unsigned>::max().count()  = " << (duration<unsigned>::max)().count() << '\n';
1615     std::cout << "duration<int>::min().count()       = " << (duration<int>::min)().count() << '\n';
1616     std::cout << "duration<int>::zero().count()      = " << duration<int>::zero().count() << '\n';
1617     std::cout << "duration<int>::max().count()       = " << (duration<int>::max)().count() << '\n';
1618 }
1619 
main()1620 int main()
1621 {
1622     basic_examples();
1623     testStdUser();
1624     testUser1();
1625     testUser2();
1626     drive_physics_function();
1627     test_range();
1628     test_extended_range();
1629     inspect_all();
1630     test_milliseconds();
1631     test_with_xtime();
1632     test_system_clock();
1633     test_steady_clock();
1634     test_hi_resolution_clock();
1635     //test_mixed_clock();
1636     timeval_demo::test_xtime_clock();
1637     runtime_resolution::test();
1638     //test_c_mapping();
1639     test_duration_division();
1640     I_dont_like_the_default_duration_behavior::test();
1641     test_min();
1642     inspect_duration(common_type<duration<double>, hours, microseconds>::type(),
1643                     "common_type<duration<double>, hours, microseconds>::type");
1644     explore_limits();
1645     manipulate_clock_object(system_clock());
1646     duration<double, boost::milli> d = milliseconds(3) * 2.5;
1647     inspect_duration(milliseconds(3) * 2.5, "milliseconds(3) * 2.5");
1648     cout << d.count() << '\n';
1649 //    milliseconds ms(3.5);  // doesn't compile
1650     cout << "milliseconds ms(3.5) doesn't compile\n";
1651     cycle_count_delay();
1652     test_special_values();
1653     return 0;
1654 }
1655 
1656