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 { |
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(timer: &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>(fd: d)).count(); |
52 | } |
53 | } |
54 | |
55 | namespace boost { |
56 | namespace this_thread { |
57 | |
58 | template <class Rep, class Period> |
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> |
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(t: 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 | { |
95 | bool try_lock() {std::cout << "timed_mutex::try_lock()\n" ; return true;} |
96 | |
97 | template <class Rep, class Period> |
98 | 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> |
108 | 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(t: 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> |
131 | 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> |
139 | 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(t: 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 | |
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(d: seconds(3)); |
176 | this_thread::sleep_for(d: nanoseconds(300)); |
177 | this_thread::sleep_until(t: 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(d: milliseconds(30)); |
181 | mut.try_lock_until(t: 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, d: minutes(1)); // real code would put this in a loop |
185 | cv.wait_until(m, t: time_limit); // real code would put this in a loop |
186 | // For those who prefer floating point |
187 | this_thread::sleep_for(d: duration<double>(0.25)); |
188 | this_thread::sleep_until(t: system_clock::now() + duration<double>(1.5)); |
189 | } |
190 | |
191 | |
192 | |
193 | int main() |
194 | { |
195 | basic_examples(); |
196 | return 0; |
197 | } |
198 | |
199 | |