1 //  simulated_thread_interface_demo.cpp  ----------------------------------------------------------//
2 
3 //  Copyright 2008 Howard Hinnant
4 //  Copyright 2008 Beman Dawes
5 //  Copyright 2009 Vicente J. Botet Escriba
6 
7 //  Distributed under the Boost Software License, Version 1.0.
8 //  See http://www.boost.org/LICENSE_1_0.txt
9 
10 /*
11 This code was extracted by Vicente J. Botet Escriba from Beman Dawes time2_demo.cpp which
12 was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
13 Many thanks to Howard for making his code available under the Boost license.
14 The original code was modified to conform to Boost conventions and to section
15 20.9 Time utilities [time] of the C++ committee's working paper N2798.
16 See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
17 
18 time2_demo contained this comment:
19 
20     Much thanks to Andrei Alexandrescu,
21                    Walter Brown,
22                    Peter Dimov,
23                    Jeff Garland,
24                    Terry Golubiewski,
25                    Daniel Krugler,
26                    Anthony Williams.
27 */
28 
29 #define _CRT_SECURE_NO_WARNINGS  // disable VC++ foolishness
30 
31 #include <boost/chrono/chrono.hpp>
32 #include <boost/type_traits.hpp>
33 
34 #include <iostream>
35 #include <ostream>
36 #include <stdexcept>
37 #include <climits>
38 
39 //////////////////////////////////////////////////////////
40 ///////////// simulated thread interface /////////////////
41 //////////////////////////////////////////////////////////
42 
43 namespace boost {
44 
45 namespace detail {
print_time(boost::chrono::system_clock::time_point t)46 void print_time(boost::chrono::system_clock::time_point t)
47 {
48     using namespace boost::chrono;
49     time_t c_time = system_clock::to_time_t(t);
50     std::tm* tmptr = std::localtime(&c_time);
51     system_clock::duration d = t.time_since_epoch();
52     std::cout << tmptr->tm_hour << ':' << tmptr->tm_min << ':' << tmptr->tm_sec
53               << '.' << (d - duration_cast<seconds>(d)).count();
54 }
55 }
56 namespace this_thread {
57 
58 template <class Rep, class Period>
sleep_for(const boost::chrono::duration<Rep,Period> & d)59 void sleep_for(const boost::chrono::duration<Rep, Period>& d)
60 {
61     boost::chrono::microseconds t = boost::chrono::duration_cast<boost::chrono::microseconds>(d);
62     if (t < d)
63         ++t;
64     if (t > boost::chrono::microseconds(0))
65         std::cout << "sleep_for " << t.count() << " microseconds\n";
66 }
67 
68 template <class Clock, class Duration>
sleep_until(const boost::chrono::time_point<Clock,Duration> & t)69 void sleep_until(const boost::chrono::time_point<Clock, Duration>& t)
70 {
71     using namespace boost::chrono;
72     typedef time_point<Clock, Duration> Time;
73     typedef system_clock::time_point SysTime;
74     if (t > Clock::now())
75     {
76         typedef typename boost::common_type<typename Time::duration,
77                                      typename SysTime::duration>::type D;
78         /* auto */ D d = t - Clock::now();
79         microseconds us = duration_cast<microseconds>(d);
80         if (us < d)
81             ++us;
82         SysTime st = system_clock::now() + us;
83         std::cout << "sleep_until    ";
84         boost::detail::print_time(st);
85         std::cout << " which is " << (st - system_clock::now()).count() << " microseconds away\n";
86     }
87 }
88 
89 }  // this_thread
90 
91 struct mutex {};
92 
93 struct timed_mutex
94 {
try_lockboost::timed_mutex95     bool try_lock() {std::cout << "timed_mutex::try_lock()\n"; return true;}
96 
97     template <class Rep, class Period>
try_lock_forboost::timed_mutex98         bool try_lock_for(const boost::chrono::duration<Rep, Period>& d)
99         {
100             boost::chrono::microseconds t = boost::chrono::duration_cast<boost::chrono::microseconds>(d);
101             if (t <= boost::chrono::microseconds(0))
102                 return try_lock();
103             std::cout << "try_lock_for " << t.count() << " microseconds\n";
104             return true;
105         }
106 
107     template <class Clock, class Duration>
try_lock_untilboost::timed_mutex108     bool try_lock_until(const boost::chrono::time_point<Clock, Duration>& t)
109     {
110         using namespace boost::chrono;
111         typedef time_point<Clock, Duration> Time;
112         typedef system_clock::time_point SysTime;
113         if (t <= Clock::now())
114             return try_lock();
115         typedef typename boost::common_type<typename Time::duration,
116           typename Clock::duration>::type D;
117         /* auto */ D d = t - Clock::now();
118         microseconds us = duration_cast<microseconds>(d);
119         SysTime st = system_clock::now() + us;
120         std::cout << "try_lock_until ";
121         boost::detail::print_time(st);
122         std::cout << " which is " << (st - system_clock::now()).count()
123           << " microseconds away\n";
124         return true;
125     }
126 };
127 
128 struct condition_variable
129 {
130     template <class Rep, class Period>
wait_forboost::condition_variable131         bool wait_for(mutex&, const boost::chrono::duration<Rep, Period>& d)
132         {
133             boost::chrono::microseconds t = boost::chrono::duration_cast<boost::chrono::microseconds>(d);
134             std::cout << "wait_for " << t.count() << " microseconds\n";
135             return true;
136         }
137 
138     template <class Clock, class Duration>
wait_untilboost::condition_variable139     bool wait_until(mutex&, const boost::chrono::time_point<Clock, Duration>& t)
140     {
141         using namespace boost::chrono;
142         typedef time_point<Clock, Duration> Time;
143         typedef system_clock::time_point SysTime;
144         if (t <= Clock::now())
145             return false;
146         typedef typename boost::common_type<typename Time::duration,
147           typename Clock::duration>::type D;
148         /* auto */ D d = t - Clock::now();
149         microseconds us = duration_cast<microseconds>(d);
150         SysTime st = system_clock::now() + us;
151          std::cout << "wait_until     ";
152         boost::detail::print_time(st);
153         std::cout << " which is " << (st - system_clock::now()).count()
154           << " microseconds away\n";
155         return true;
156     }
157 };
158 
159 }
160 
161 //////////////////////////////////////////////////////////
162 //////////// Simple sleep and wait examples //////////////
163 //////////////////////////////////////////////////////////
164 
165 boost::mutex m;
166 boost::timed_mutex mut;
167 boost::condition_variable cv;
168 
basic_examples()169 void basic_examples()
170 {
171     std::cout << "Running basic examples\n";
172     using namespace boost;
173     using namespace boost::chrono;
174     system_clock::time_point time_limit = system_clock::now() + seconds(4) + milliseconds(500);
175     this_thread::sleep_for(seconds(3));
176     this_thread::sleep_for(nanoseconds(300));
177     this_thread::sleep_until(time_limit);
178 //    this_thread::sleep_for(time_limit);  // desired compile-time error
179 //    this_thread::sleep_until(seconds(3)); // desired compile-time error
180     mut.try_lock_for(milliseconds(30));
181     mut.try_lock_until(time_limit);
182 //    mut.try_lock_for(time_limit);        // desired compile-time error
183 //    mut.try_lock_until(milliseconds(30)); // desired compile-time error
184     cv.wait_for(m, minutes(1));    // real code would put this in a loop
185     cv.wait_until(m, time_limit);  // real code would put this in a loop
186     // For those who prefer floating point
187     this_thread::sleep_for(duration<double>(0.25));
188     this_thread::sleep_until(system_clock::now() + duration<double>(1.5));
189 }
190 
191 
192 
main()193 int main()
194 {
195     basic_examples();
196     return 0;
197 }
198 
199