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 {
print_time(boost::chrono::system_clock::time_point t)44 void print_time(boost::chrono::system_clock::time_point t)
45 {
46 using namespace boost::chrono;
47 time_t c_time = system_clock::to_time_t(t);
48 std::tm* tmptr = std::localtime(&c_time);
49 system_clock::duration d = t.time_since_epoch();
50 std::cout << tmptr->tm_hour << ':' << tmptr->tm_min << ':' << tmptr->tm_sec
51 << '.' << (d - duration_cast<seconds>(d)).count();
52 }
53 }
54
55 namespace boost {
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 ::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 ::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 ::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