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
11This code was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
12Many thanks to Howard for making his code available under the Boost license.
13The original code was modified to conform to Boost conventions and to section
1420.9 Time utilities [time] of the C++ committee's working paper N2798.
15See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
16
17time2_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
41namespace
42{
43 //struct timeval {
44 // long tv_sec; /* seconds */
45 // long tv_usec; /* and microseconds */
46 //};
47
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
70namespace std {
71
72void __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(timer: &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>(fd: d)).count();
80}
81
82namespace this_thread {
83
84template <class Rep, class Period>
85void 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
94template <class Clock, class Duration>
95void 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(t: st);
111 std::cout << " which is " << (st - system_clock::now()).count() << " microseconds away\n";
112 }
113}
114
115} // this_thread
116
117struct mutex {};
118
119struct timed_mutex
120{
121 bool try_lock() {std::cout << "timed_mutex::try_lock()\n"; return true;}
122
123 template <class Rep, class Period>
124 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>
134 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
154struct condition_variable
155{
156 template <class Rep, class Period>
157 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>
165 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(t: 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
191std::mutex m;
192std::timed_mutex mut;
193std::condition_variable cv;
194
195void 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(d: seconds(3));
202 this_thread::sleep_for(d: nanoseconds(300));
203 this_thread::sleep_until(t: 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, d: minutes(1)); // real code would put this in a loop
211 cv.wait_until(m, t: time_limit); // real code would put this in a loop
212 // For those who prefer floating point
213 this_thread::sleep_for(d: duration<double>(0.25));
214 this_thread::sleep_until(t: system_clock::now() + duration<double>(1.5));
215}
216
217//////////////////////////////////////////////////////////
218//////////////////// User1 Example ///////////////////////
219//////////////////////////////////////////////////////////
220
221namespace 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
229template <class Ratio>
230class length
231{
232public:
233 typedef Ratio ratio;
234private:
235 double len_;
236public:
237
238 length() : len_(1) {}
239 length(const double& len) : len_(len) {}
240
241 // conversions
242 template <class R>
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
249 double count() const {return len_;}
250
251 // arithmetic
252
253 length& operator+=(const length& d) {len_ += d.count(); return *this;}
254 length& operator-=(const length& d) {len_ -= d.count(); return *this;}
255
256 length operator+() const {return *this;}
257 length operator-() const {return length(-len_);}
258
259 length& operator*=(double rhs) {len_ *= rhs; return *this;}
260 length& operator/=(double rhs) {len_ /= rhs; return *this;}
261};
262
263// Sparse sampling of length units
264typedef length<boost::ratio<1> > meter; // set meter as "unity"
265typedef length<boost::centi> centimeter; // 1/100 meter
266typedef length<boost::kilo> kilometer; // 1000 meters
267typedef 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:
269typedef length<boost::ratio_multiply<boost::ratio<12>, inch::ratio>::type> foot; // 12 inchs
270typedef length<boost::ratio_multiply<boost::ratio<5280>, foot::ratio>::type> mile; // 5280 feet
271
272// Need a floating point definition of seconds
273typedef boost::chrono::duration<double> seconds; // unity
274// Demo of (scientific) support for sub-nanosecond resolutions
275typedef boost::chrono::duration<double, boost::pico> picosecond; // 10^-12 seconds
276typedef boost::chrono::duration<double, boost::femto> femtosecond; // 10^-15 seconds
277typedef 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())
281template <class R1, class R2>
282class quantity
283{
284 double q_;
285public:
286 quantity() : q_(1) {}
287
288 double get() const {return q_;}
289 void set(double q) {q_ = q;}
290};
291
292template <>
293class quantity<boost::ratio<1>, boost::ratio<0> >
294{
295 double q_;
296public:
297 quantity() : q_(1) {}
298 quantity(seconds d) : q_(d.count()) {} // note: only User1::seconds needed here
299
300 double get() const {return q_;}
301 void set(double q) {q_ = q;}
302};
303
304template <>
305class quantity<boost::ratio<0>, boost::ratio<1> >
306{
307 double q_;
308public:
309 quantity() : q_(1) {}
310 quantity(meter d) : q_(d.count()) {} // note: only User1::meter needed here
311
312 double get() const {return q_;}
313 void set(double q) {q_ = q;}
314};
315
316template <>
317class quantity<boost::ratio<0>, boost::ratio<0> >
318{
319 double q_;
320public:
321 quantity() : q_(1) {}
322 quantity(double d) : q_(d) {}
323
324 double get() const {return q_;}
325 void set(double q) {q_ = q;}
326};
327
328// Example SI-Units
329typedef quantity<boost::ratio<0>, boost::ratio<0> > Scalar;
330typedef quantity<boost::ratio<1>, boost::ratio<0> > Time; // second
331typedef quantity<boost::ratio<0>, boost::ratio<1> > Distance; // meter
332typedef quantity<boost::ratio<-1>, boost::ratio<1> > Speed; // meter/second
333typedef quantity<boost::ratio<-2>, boost::ratio<1> > Acceleration; // meter/second^2
334
335template <class R1, class R2, class R3, class R4>
336quantity<typename boost::ratio_subtract<R1, R3>::type, typename boost::ratio_subtract<R2, R4>::type>
337operator/(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
345template <class R1, class R2, class R3, class R4>
346quantity<typename boost::ratio_add<R1, R3>::type, typename boost::ratio_add<R2, R4>::type>
347operator*(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
355template <class R1, class R2>
356quantity<R1, R2>
357operator+(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
365template <class R1, class R2>
366quantity<R1, R2>
367operator-(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
376Distance
377compute_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).
389void 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(v0: s, t: 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
431namespace User2
432{
433
434template <class I>
435class saturate
436{
437public:
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;
443private:
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
451public:
452 saturate() : i_(nan) {}
453 explicit saturate(int_type i) : i_(i) {}
454 // explicit
455 operator int_type() const;
456
457 saturate& 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
463 saturate operator- () const {return saturate(-i_);}
464 saturate& operator++() {*this += saturate(int_type(1)); return *this;}
465 saturate operator++(int) {saturate tmp(*this); ++(*this); return tmp;}
466 saturate& operator--() {*this -= saturate(int_type(1)); return *this;}
467 saturate operator--(int) {saturate tmp(*this); --(*this); return tmp;}
468
469 friend saturate operator+(saturate x, saturate y) {return x += y;}
470 friend saturate operator-(saturate x, saturate y) {return x -= y;}
471 friend saturate operator*(saturate x, saturate y) {return x *= y;}
472 friend saturate operator/(saturate x, saturate y) {return x /= y;}
473 friend saturate operator%(saturate x, saturate y) {return x %= y;}
474
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
482 friend bool operator!=(saturate x, saturate y) {return !(x == y);}
483
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
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
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
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
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
527template <class I>
528saturate<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
540template <class I>
541saturate<I>&
542saturate<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
588template <class I>
589saturate<I>&
590saturate<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
660template <class I>
661saturate<I>&
662saturate<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
715template <class I>
716saturate<I>&
717saturate<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
742typedef boost::chrono::duration<saturate<long long>, boost::pico > picoseconds;
743typedef boost::chrono::duration<saturate<long long>, boost::nano > nanoseconds;
744typedef boost::chrono::duration<saturate<long long>, boost::micro > microseconds;
745typedef boost::chrono::duration<saturate<long long>, boost::milli > milliseconds;
746typedef boost::chrono::duration<saturate<long long> > seconds;
747typedef boost::chrono::duration<saturate<long long>, boost::ratio< 60LL> > minutes;
748typedef boost::chrono::duration<saturate<long long>, boost::ratio< 3600LL> > hours;
749typedef boost::chrono::duration<saturate<long long>, boost::ratio< 86400LL> > days;
750typedef boost::chrono::duration<saturate<long long>, boost::ratio< 31556952LL> > years;
751typedef 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)
756namespace User2 { namespace detail {
757
758template <class T1, class T2, bool = boost::is_integral<T1>::value>
759struct promote_helper;
760
761template <class T1, class T2>
762struct 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
768template <class T1, class T2>
769struct promote_helper<T1, saturate<T2>, false> // floating
770{
771 typedef T1 type;
772};
773
774} }
775
776namespace boost
777{
778
779template <class T1, class T2>
780struct 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
786template <class T1, class T2>
787struct common_type<T1, User2::saturate<T2> >
788 : User2::detail::promote_helper<T1, User2::saturate<T2> > {};
789
790template <class T1, class T2>
791struct common_type<User2::saturate<T1>, T2>
792 : User2::detail::promote_helper<T2, User2::saturate<T1> > {};
793
794
795// Demonstrate specialization of duration_values:
796
797namespace chrono {
798
799template <class I>
800struct duration_values<User2::saturate<I> >
801{
802 typedef User2::saturate<I> Rep;
803public:
804 static Rep zero() {return Rep(0);}
805 static Rep max BOOST_PREVENT_MACRO_SUBSTITUTION () {return Rep(Rep::pos_inf-1);}
806 static Rep min BOOST_PREVENT_MACRO_SUBSTITUTION () {return -(max) ();}
807};
808
809} // namespace chrono
810
811} // namespace boost
812
813
814void 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>(fd: yr);
841 std::cout << "200 million years ago encoded in days: " << d.count() << '\n';
842 millennium c = boost::chrono::duration_cast<millennium>(fd: 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
852void 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>(fd: 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
883namespace timeval_demo
884{
885
886class xtime {
887private:
888 long tv_sec;
889 long tv_usec;
890
891 void fixup() {
892 if (tv_usec < 0) {
893 tv_usec += 1000000;
894 --tv_sec;
895 }
896 }
897
898public:
899
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
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
918 operator long long() const {return static_cast<long long>(tv_sec) * 1000000 + tv_usec;}
919
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
930 xtime& operator -= (xtime rhs) {
931 tv_sec -= rhs.tv_sec;
932 tv_usec -= rhs.tv_usec;
933 fixup();
934 return *this;
935 }
936
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
947 friend xtime operator+(xtime x, xtime y) {return x += y;}
948 friend xtime operator-(xtime x, xtime y) {return x -= y;}
949 friend xtime operator%(xtime x, xtime y) {return x %= y;}
950
951 friend bool operator==(xtime x, xtime y)
952 { return (x.tv_sec == y.tv_sec && x.tv_usec == y.tv_usec); }
953
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
960 friend bool operator!=(xtime x, xtime y) { return !(x == y); }
961 friend bool operator> (xtime x, xtime y) { return y < x; }
962 friend bool operator<=(xtime x, xtime y) { return !(y < x); }
963 friend bool operator>=(xtime x, xtime y) { return !(x < y); }
964
965 friend std::ostream& operator<<(std::ostream& os, xtime x)
966 {return os << '{' << x.tv_sec << ',' << x.tv_usec << '}';}
967};
968
969class xtime_clock
970{
971public:
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
980xtime_clock::time_point
981xtime_clock::now()
982{
983 time_point t(duration(xtime(0)));
984 gettimeofday(tp: (timeval*)&t, 0);
985 return t;
986}
987
988void 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
1009namespace runtime_resolution
1010{
1011
1012class duration
1013{
1014public:
1015 typedef long long rep;
1016private:
1017 rep rep_;
1018
1019 static const double ticks_per_nanosecond;
1020
1021public:
1022 typedef boost::chrono::duration<double, boost::nano> tonanosec;
1023
1024 duration() {} // = default;
1025 explicit duration(const rep& r) : rep_(r) {}
1026
1027 // conversions
1028 explicit duration(const tonanosec& d)
1029 : rep_(static_cast<rep>(d.count() * ticks_per_nanosecond)) {}
1030
1031 // explicit
1032 operator tonanosec() const {return tonanosec(rep_/ticks_per_nanosecond);}
1033
1034 // observer
1035
1036 rep count() const {return rep_;}
1037
1038 // arithmetic
1039
1040 duration& operator+=(const duration& d) {rep_ += d.rep_; return *this;}
1041 duration& operator-=(const duration& d) {rep_ += d.rep_; return *this;}
1042 duration& operator*=(rep rhs) {rep_ *= rhs; return *this;}
1043 duration& operator/=(rep rhs) {rep_ /= rhs; return *this;}
1044
1045 duration operator+() const {return *this;}
1046 duration operator-() const {return duration(-rep_);}
1047 duration& operator++() {++rep_; return *this;}
1048 duration operator++(int) {return duration(rep_++);}
1049 duration& operator--() {--rep_; return *this;}
1050 duration operator--(int) {return duration(rep_--);}
1051
1052 friend duration operator+(duration x, duration y) {return x += y;}
1053 friend duration operator-(duration x, duration y) {return x -= y;}
1054 friend duration operator*(duration x, rep y) {return x *= y;}
1055 friend duration operator*(rep x, duration y) {return y *= x;}
1056 friend duration operator/(duration x, rep y) {return x /= y;}
1057
1058 friend bool operator==(duration x, duration y) {return x.rep_ == y.rep_;}
1059 friend bool operator!=(duration x, duration y) {return !(x == y);}
1060 friend bool operator< (duration x, duration y) {return x.rep_ < y.rep_;}
1061 friend bool operator<=(duration x, duration y) {return !(y < x);}
1062 friend bool operator> (duration x, duration y) {return y < x;}
1063 friend bool operator>=(duration x, duration y) {return !(x < y);}
1064};
1065
1066static
1067double
1068init_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
1076const double duration::ticks_per_nanosecond = init_duration();
1077
1078class clock;
1079
1080class time_point
1081{
1082public:
1083 typedef runtime_resolution::clock clock;
1084 typedef long long rep;
1085private:
1086 rep rep_;
1087
1088
1089 rep count() const {return rep_;}
1090public:
1091
1092 time_point() : rep_(0) {}
1093 explicit time_point(const duration& d)
1094 : rep_(d.count()) {}
1095
1096 // arithmetic
1097
1098 time_point& operator+=(const duration& d) {rep_ += d.count(); return *this;}
1099 time_point& operator-=(const duration& d) {rep_ -= d.count(); return *this;}
1100
1101 friend time_point operator+(time_point x, duration y) {return x += y;}
1102 friend time_point operator+(duration x, time_point y) {return y += x;}
1103 friend time_point operator-(time_point x, duration y) {return x -= y;}
1104 friend duration operator-(time_point x, time_point y) {return duration(x.rep_ - y.rep_);}
1105};
1106
1107class clock
1108{
1109public:
1110 typedef duration::rep rep;
1111 typedef runtime_resolution::duration duration;
1112 typedef runtime_resolution::time_point time_point;
1113
1114 static time_point now()
1115 {
1116 timeval tv;
1117 gettimeofday( tp: &tv, 0 );
1118 return time_point(duration((static_cast<rep>(tv.tv_sec)<<32) | tv.tv_usec));
1119 }
1120};
1121
1122void 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>(fd: duration::tonanosec(elapsed))).count()
1133 << " nanoseconds\n";
1134}
1135
1136} // runtime_resolution
1137
1138// miscellaneous tests and demos:
1139
1140
1141using namespace boost::chrono;
1142
1143void physics_function(duration<double> d)
1144{
1145 std::cout << "d = " << d.count() << '\n';
1146}
1147
1148void drive_physics_function()
1149{
1150 physics_function(d: nanoseconds(3));
1151 physics_function(d: hours(3));
1152 physics_function(d: duration<double>(2./3));
1153 std::cout.precision(prec: 16);
1154 physics_function( d: hours(3) + nanoseconds(-3) );
1155}
1156
1157void 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
1168void 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
1179template <class Rep, class Period>
1180void 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
1216void inspect_all()
1217{
1218 using namespace boost::chrono;
1219 std::cout.precision(prec: 6);
1220 inspect_duration(d: nanoseconds(), name: "nanoseconds");
1221 inspect_duration(d: microseconds(), name: "microseconds");
1222 inspect_duration(d: milliseconds(), name: "milliseconds");
1223 inspect_duration(d: seconds(), name: "seconds");
1224 inspect_duration(d: minutes(), name: "minutes");
1225 inspect_duration(d: hours(), name: "hours");
1226 inspect_duration(d: duration<double>(), name: "duration<double>");
1227}
1228
1229void 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!
1247template <class To, class Rep, class Period>
1248To
1249round_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
1259using namespace boost::chrono;
1260
1261struct xtime
1262{
1263 long sec;
1264 unsigned long usec;
1265};
1266
1267template <class Rep, class Period>
1268xtime
1269to_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
1277template <class Rep, class Period>
1278xtime
1279to_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
1287microseconds
1288from_xtime(xtime xt)
1289{
1290 return seconds(xt.sec) + microseconds(xt.usec);
1291}
1292
1293void print(xtime xt)
1294{
1295 cout << '{' << xt.sec << ',' << xt.usec << "}\n";
1296}
1297
1298void test_with_xtime()
1299{
1300 cout << "test_with_xtime\n";
1301 xtime xt = to_xtime_truncate(d: seconds(3) + milliseconds(251));
1302 print(xt);
1303 milliseconds ms = duration_cast<milliseconds>(fd: from_xtime(xt));
1304 cout << ms.count() << " milliseconds\n";
1305 xt = to_xtime_round_up(d: ms);
1306 print(xt);
1307 xt = to_xtime_truncate(d: seconds(3) + nanoseconds(999));
1308 print(xt);
1309 xt = to_xtime_round_up(d: seconds(3) + nanoseconds(999));
1310 print(xt);
1311}
1312
1313void 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
1328void 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
1343void 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
1391void 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
1398namespace 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
1403template <class R>
1404class zero_default
1405{
1406public:
1407 typedef R rep;
1408
1409private:
1410 rep rep_;
1411public:
1412 zero_default(rep i = 0) : rep_(i) {}
1413 operator rep() const {return rep_;}
1414
1415 zero_default& operator+=(zero_default x) {rep_ += x.rep_; return *this;}
1416 zero_default& operator-=(zero_default x) {rep_ -= x.rep_; return *this;}
1417 zero_default& operator*=(zero_default x) {rep_ *= x.rep_; return *this;}
1418 zero_default& operator/=(zero_default x) {rep_ /= x.rep_; return *this;}
1419
1420 zero_default operator+ () const {return *this;}
1421 zero_default operator- () const {return zero_default(-rep_);}
1422 zero_default& operator++() {++rep_; return *this;}
1423 zero_default operator++(int) {return zero_default(rep_++);}
1424 zero_default& operator--() {--rep_; return *this;}
1425 zero_default operator--(int) {return zero_default(rep_--);}
1426
1427 friend zero_default operator+(zero_default x, zero_default y) {return x += y;}
1428 friend zero_default operator-(zero_default x, zero_default y) {return x -= y;}
1429 friend zero_default operator*(zero_default x, zero_default y) {return x *= y;}
1430 friend zero_default operator/(zero_default x, zero_default y) {return x /= y;}
1431
1432 friend bool operator==(zero_default x, zero_default y) {return x.rep_ == y.rep_;}
1433 friend bool operator!=(zero_default x, zero_default y) {return !(x == y);}
1434 friend bool operator< (zero_default x, zero_default y) {return x.rep_ < y.rep_;}
1435 friend bool operator<=(zero_default x, zero_default y) {return !(y < x);}
1436 friend bool operator> (zero_default x, zero_default y) {return y < x;}
1437 friend bool operator>=(zero_default x, zero_default y) {return !(x < y);}
1438};
1439
1440typedef boost::chrono::duration<zero_default<long long>, boost::nano > nanoseconds;
1441typedef boost::chrono::duration<zero_default<long long>, boost::micro > microseconds;
1442typedef boost::chrono::duration<zero_default<long long>, boost::milli > milliseconds;
1443typedef boost::chrono::duration<zero_default<long long> > seconds;
1444typedef boost::chrono::duration<zero_default<long long>, boost::ratio<60> > minutes;
1445typedef boost::chrono::duration<zero_default<long long>, boost::ratio<3600> > hours;
1446
1447void 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
1457template <class Rep, class Period>
1458void
1459print_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!
1466template <class Clock, class Duration1, class Duration2>
1467inline
1468typename boost::common_type<time_point<Clock, Duration1>,
1469 time_point<Clock, Duration2> >::type
1470min BOOST_PREVENT_MACRO_SUBSTITUTION (time_point<Clock, Duration1> t1, time_point<Clock, Duration2> t2)
1471{
1472 return t2 < t1 ? t2 : t1;
1473}
1474
1475void 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(os&: cout, d: t1 - t3);
1486 print_duration(os&: cout, d: t2 - t3);
1487}
1488
1489void 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>(t: t1) - time_point_cast<microseconds>(t: t2);
1498 cout << d.count() << " microseconds\n";
1499}
1500
1501void 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
1512template <long long speed>
1513struct 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
1521 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
1529template <long long speed>
1530struct 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
1539 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
1548void 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>(fd: 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>(fd: 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>(fd: 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>(fd: 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
1610void 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
1620int 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(d: common_type<duration<double>, hours, microseconds>::type(),
1643 name: "common_type<duration<double>, hours, microseconds>::type");
1644 explore_limits();
1645 manipulate_clock_object(clock: system_clock());
1646 duration<double, boost::milli> d = milliseconds(3) * 2.5;
1647 inspect_duration(d: milliseconds(3) * 2.5, name: "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

source code of boost/libs/chrono/example/time2_demo.cpp