Chris@16
|
1 #ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
|
Chris@16
|
2 #define BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
|
Chris@16
|
3 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
4 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 // (C) Copyright 2007-8 Anthony Williams
|
Chris@16
|
7 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
Chris@16
|
8
|
Chris@16
|
9 #include <boost/thread/win32/thread_primitives.hpp>
|
Chris@16
|
10 #include <boost/thread/win32/thread_data.hpp>
|
Chris@16
|
11 #include <boost/thread/win32/thread_data.hpp>
|
Chris@16
|
12 #include <boost/thread/win32/interlocked_read.hpp>
|
Chris@16
|
13 #include <boost/thread/cv_status.hpp>
|
Chris@16
|
14 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
15 #include <boost/thread/xtime.hpp>
|
Chris@16
|
16 #endif
|
Chris@16
|
17 #include <boost/thread/mutex.hpp>
|
Chris@16
|
18 #include <boost/thread/thread_time.hpp>
|
Chris@16
|
19 #include <boost/thread/lock_guard.hpp>
|
Chris@16
|
20 #include <boost/thread/lock_types.hpp>
|
Chris@16
|
21
|
Chris@16
|
22 #include <boost/assert.hpp>
|
Chris@16
|
23 #include <boost/intrusive_ptr.hpp>
|
Chris@16
|
24
|
Chris@16
|
25 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
26 #include <boost/chrono/system_clocks.hpp>
|
Chris@16
|
27 #include <boost/chrono/ceil.hpp>
|
Chris@16
|
28 #endif
|
Chris@16
|
29
|
Chris@16
|
30 #include <limits.h>
|
Chris@16
|
31 #include <algorithm>
|
Chris@16
|
32 #include <vector>
|
Chris@16
|
33
|
Chris@16
|
34 #include <boost/config/abi_prefix.hpp>
|
Chris@16
|
35
|
Chris@16
|
36 namespace boost
|
Chris@16
|
37 {
|
Chris@16
|
38 namespace detail
|
Chris@16
|
39 {
|
Chris@16
|
40 class basic_cv_list_entry;
|
Chris@16
|
41 void intrusive_ptr_add_ref(basic_cv_list_entry * p);
|
Chris@16
|
42 void intrusive_ptr_release(basic_cv_list_entry * p);
|
Chris@16
|
43
|
Chris@16
|
44 class basic_cv_list_entry
|
Chris@16
|
45 {
|
Chris@16
|
46 private:
|
Chris@16
|
47 detail::win32::handle_manager semaphore;
|
Chris@16
|
48 detail::win32::handle_manager wake_sem;
|
Chris@16
|
49 long waiters;
|
Chris@16
|
50 bool notified;
|
Chris@16
|
51 long references;
|
Chris@16
|
52
|
Chris@16
|
53 public:
|
Chris@16
|
54 BOOST_THREAD_NO_COPYABLE(basic_cv_list_entry)
|
Chris@16
|
55 explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_):
|
Chris@16
|
56 semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)),
|
Chris@16
|
57 wake_sem(wake_sem_.duplicate()),
|
Chris@16
|
58 waiters(1),notified(false),references(0)
|
Chris@16
|
59 {}
|
Chris@16
|
60
|
Chris@16
|
61 static bool no_waiters(boost::intrusive_ptr<basic_cv_list_entry> const& entry)
|
Chris@16
|
62 {
|
Chris@16
|
63 return !detail::interlocked_read_acquire(&entry->waiters);
|
Chris@16
|
64 }
|
Chris@16
|
65
|
Chris@16
|
66 void add_waiter()
|
Chris@16
|
67 {
|
Chris@16
|
68 BOOST_INTERLOCKED_INCREMENT(&waiters);
|
Chris@16
|
69 }
|
Chris@16
|
70
|
Chris@16
|
71 void remove_waiter()
|
Chris@16
|
72 {
|
Chris@16
|
73 BOOST_INTERLOCKED_DECREMENT(&waiters);
|
Chris@16
|
74 }
|
Chris@16
|
75
|
Chris@16
|
76 void release(unsigned count_to_release)
|
Chris@16
|
77 {
|
Chris@16
|
78 notified=true;
|
Chris@16
|
79 detail::win32::ReleaseSemaphore(semaphore,count_to_release,0);
|
Chris@16
|
80 }
|
Chris@16
|
81
|
Chris@16
|
82 void release_waiters()
|
Chris@16
|
83 {
|
Chris@16
|
84 release(detail::interlocked_read_acquire(&waiters));
|
Chris@16
|
85 }
|
Chris@16
|
86
|
Chris@16
|
87 bool is_notified() const
|
Chris@16
|
88 {
|
Chris@16
|
89 return notified;
|
Chris@16
|
90 }
|
Chris@16
|
91
|
Chris@16
|
92 bool wait(timeout abs_time)
|
Chris@16
|
93 {
|
Chris@16
|
94 return this_thread::interruptible_wait(semaphore,abs_time);
|
Chris@16
|
95 }
|
Chris@16
|
96
|
Chris@16
|
97 bool woken()
|
Chris@16
|
98 {
|
Chris@101
|
99 unsigned long const woken_result=detail::win32::WaitForSingleObjectEx(wake_sem,0,0);
|
Chris@16
|
100 BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0));
|
Chris@16
|
101 return woken_result==0;
|
Chris@16
|
102 }
|
Chris@16
|
103
|
Chris@16
|
104 friend void intrusive_ptr_add_ref(basic_cv_list_entry * p);
|
Chris@16
|
105 friend void intrusive_ptr_release(basic_cv_list_entry * p);
|
Chris@16
|
106 };
|
Chris@16
|
107
|
Chris@16
|
108 inline void intrusive_ptr_add_ref(basic_cv_list_entry * p)
|
Chris@16
|
109 {
|
Chris@16
|
110 BOOST_INTERLOCKED_INCREMENT(&p->references);
|
Chris@16
|
111 }
|
Chris@16
|
112
|
Chris@16
|
113 inline void intrusive_ptr_release(basic_cv_list_entry * p)
|
Chris@16
|
114 {
|
Chris@16
|
115 if(!BOOST_INTERLOCKED_DECREMENT(&p->references))
|
Chris@16
|
116 {
|
Chris@16
|
117 delete p;
|
Chris@16
|
118 }
|
Chris@16
|
119 }
|
Chris@16
|
120
|
Chris@16
|
121 class basic_condition_variable
|
Chris@16
|
122 {
|
Chris@16
|
123 boost::mutex internal_mutex;
|
Chris@16
|
124 long total_count;
|
Chris@16
|
125 unsigned active_generation_count;
|
Chris@16
|
126
|
Chris@16
|
127 typedef basic_cv_list_entry list_entry;
|
Chris@16
|
128
|
Chris@16
|
129 typedef boost::intrusive_ptr<list_entry> entry_ptr;
|
Chris@16
|
130 typedef std::vector<entry_ptr> generation_list;
|
Chris@16
|
131
|
Chris@16
|
132 generation_list generations;
|
Chris@16
|
133 detail::win32::handle_manager wake_sem;
|
Chris@16
|
134
|
Chris@16
|
135 void wake_waiters(long count_to_wake)
|
Chris@16
|
136 {
|
Chris@16
|
137 detail::interlocked_write_release(&total_count,total_count-count_to_wake);
|
Chris@16
|
138 detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
|
Chris@16
|
139 }
|
Chris@16
|
140
|
Chris@16
|
141 template<typename lock_type>
|
Chris@16
|
142 struct relocker
|
Chris@16
|
143 {
|
Chris@16
|
144 BOOST_THREAD_NO_COPYABLE(relocker)
|
Chris@16
|
145 lock_type& lock;
|
Chris@16
|
146 bool unlocked;
|
Chris@16
|
147
|
Chris@16
|
148 relocker(lock_type& lock_):
|
Chris@16
|
149 lock(lock_),unlocked(false)
|
Chris@16
|
150 {}
|
Chris@16
|
151 void unlock()
|
Chris@16
|
152 {
|
Chris@16
|
153 lock.unlock();
|
Chris@16
|
154 unlocked=true;
|
Chris@16
|
155 }
|
Chris@16
|
156 ~relocker()
|
Chris@16
|
157 {
|
Chris@16
|
158 if(unlocked)
|
Chris@16
|
159 {
|
Chris@16
|
160 lock.lock();
|
Chris@16
|
161 }
|
Chris@16
|
162
|
Chris@16
|
163 }
|
Chris@16
|
164 };
|
Chris@16
|
165
|
Chris@16
|
166
|
Chris@16
|
167 entry_ptr get_wait_entry()
|
Chris@16
|
168 {
|
Chris@16
|
169 boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
|
Chris@16
|
170
|
Chris@16
|
171 if(!wake_sem)
|
Chris@16
|
172 {
|
Chris@16
|
173 wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
Chris@16
|
174 BOOST_ASSERT(wake_sem);
|
Chris@16
|
175 }
|
Chris@16
|
176
|
Chris@16
|
177 detail::interlocked_write_release(&total_count,total_count+1);
|
Chris@16
|
178 if(generations.empty() || generations.back()->is_notified())
|
Chris@16
|
179 {
|
Chris@16
|
180 entry_ptr new_entry(new list_entry(wake_sem));
|
Chris@16
|
181 generations.push_back(new_entry);
|
Chris@16
|
182 return new_entry;
|
Chris@16
|
183 }
|
Chris@16
|
184 else
|
Chris@16
|
185 {
|
Chris@16
|
186 generations.back()->add_waiter();
|
Chris@16
|
187 return generations.back();
|
Chris@16
|
188 }
|
Chris@16
|
189 }
|
Chris@16
|
190
|
Chris@16
|
191 struct entry_manager
|
Chris@16
|
192 {
|
Chris@16
|
193 entry_ptr const entry;
|
Chris@16
|
194 boost::mutex& internal_mutex;
|
Chris@16
|
195
|
Chris@16
|
196 BOOST_THREAD_NO_COPYABLE(entry_manager)
|
Chris@16
|
197 entry_manager(entry_ptr const& entry_, boost::mutex& mutex_):
|
Chris@16
|
198 entry(entry_), internal_mutex(mutex_)
|
Chris@16
|
199 {}
|
Chris@16
|
200
|
Chris@16
|
201 ~entry_manager()
|
Chris@16
|
202 {
|
Chris@16
|
203 boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
|
Chris@16
|
204 entry->remove_waiter();
|
Chris@16
|
205 }
|
Chris@16
|
206
|
Chris@16
|
207 list_entry* operator->()
|
Chris@16
|
208 {
|
Chris@16
|
209 return entry.get();
|
Chris@16
|
210 }
|
Chris@16
|
211 };
|
Chris@16
|
212
|
Chris@16
|
213
|
Chris@16
|
214 protected:
|
Chris@16
|
215 template<typename lock_type>
|
Chris@16
|
216 bool do_wait(lock_type& lock,timeout abs_time)
|
Chris@16
|
217 {
|
Chris@16
|
218 relocker<lock_type> locker(lock);
|
Chris@16
|
219
|
Chris@16
|
220 entry_manager entry(get_wait_entry(), internal_mutex);
|
Chris@16
|
221
|
Chris@16
|
222 locker.unlock();
|
Chris@16
|
223
|
Chris@16
|
224 bool woken=false;
|
Chris@16
|
225 while(!woken)
|
Chris@16
|
226 {
|
Chris@16
|
227 if(!entry->wait(abs_time))
|
Chris@16
|
228 {
|
Chris@16
|
229 return false;
|
Chris@16
|
230 }
|
Chris@16
|
231
|
Chris@16
|
232 woken=entry->woken();
|
Chris@16
|
233 }
|
Chris@16
|
234 return woken;
|
Chris@16
|
235 }
|
Chris@16
|
236
|
Chris@16
|
237 template<typename lock_type,typename predicate_type>
|
Chris@16
|
238 bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred)
|
Chris@16
|
239 {
|
Chris@16
|
240 while (!pred())
|
Chris@16
|
241 {
|
Chris@16
|
242 if(!do_wait(m, abs_time))
|
Chris@16
|
243 return pred();
|
Chris@16
|
244 }
|
Chris@16
|
245 return true;
|
Chris@16
|
246 }
|
Chris@16
|
247
|
Chris@16
|
248 basic_condition_variable(const basic_condition_variable& other);
|
Chris@16
|
249 basic_condition_variable& operator=(const basic_condition_variable& other);
|
Chris@16
|
250
|
Chris@16
|
251 public:
|
Chris@16
|
252 basic_condition_variable():
|
Chris@16
|
253 total_count(0),active_generation_count(0),wake_sem(0)
|
Chris@16
|
254 {}
|
Chris@16
|
255
|
Chris@16
|
256 ~basic_condition_variable()
|
Chris@16
|
257 {}
|
Chris@16
|
258
|
Chris@16
|
259 void notify_one() BOOST_NOEXCEPT
|
Chris@16
|
260 {
|
Chris@16
|
261 if(detail::interlocked_read_acquire(&total_count))
|
Chris@16
|
262 {
|
Chris@16
|
263 boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
|
Chris@16
|
264 if(!total_count)
|
Chris@16
|
265 {
|
Chris@16
|
266 return;
|
Chris@16
|
267 }
|
Chris@16
|
268 wake_waiters(1);
|
Chris@16
|
269
|
Chris@16
|
270 for(generation_list::iterator it=generations.begin(),
|
Chris@16
|
271 end=generations.end();
|
Chris@16
|
272 it!=end;++it)
|
Chris@16
|
273 {
|
Chris@16
|
274 (*it)->release(1);
|
Chris@16
|
275 }
|
Chris@16
|
276 generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end());
|
Chris@16
|
277 }
|
Chris@16
|
278 }
|
Chris@16
|
279
|
Chris@16
|
280 void notify_all() BOOST_NOEXCEPT
|
Chris@16
|
281 {
|
Chris@16
|
282 if(detail::interlocked_read_acquire(&total_count))
|
Chris@16
|
283 {
|
Chris@16
|
284 boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
|
Chris@16
|
285 if(!total_count)
|
Chris@16
|
286 {
|
Chris@16
|
287 return;
|
Chris@16
|
288 }
|
Chris@16
|
289 wake_waiters(total_count);
|
Chris@16
|
290 for(generation_list::iterator it=generations.begin(),
|
Chris@16
|
291 end=generations.end();
|
Chris@16
|
292 it!=end;++it)
|
Chris@16
|
293 {
|
Chris@16
|
294 (*it)->release_waiters();
|
Chris@16
|
295 }
|
Chris@16
|
296 generations.clear();
|
Chris@16
|
297 wake_sem=detail::win32::handle(0);
|
Chris@16
|
298 }
|
Chris@16
|
299 }
|
Chris@16
|
300
|
Chris@16
|
301 };
|
Chris@16
|
302 }
|
Chris@16
|
303
|
Chris@16
|
304 class condition_variable:
|
Chris@16
|
305 private detail::basic_condition_variable
|
Chris@16
|
306 {
|
Chris@16
|
307 public:
|
Chris@16
|
308 BOOST_THREAD_NO_COPYABLE(condition_variable)
|
Chris@16
|
309 condition_variable()
|
Chris@16
|
310 {}
|
Chris@16
|
311
|
Chris@16
|
312 using detail::basic_condition_variable::notify_one;
|
Chris@16
|
313 using detail::basic_condition_variable::notify_all;
|
Chris@16
|
314
|
Chris@16
|
315 void wait(unique_lock<mutex>& m)
|
Chris@16
|
316 {
|
Chris@16
|
317 do_wait(m,detail::timeout::sentinel());
|
Chris@16
|
318 }
|
Chris@16
|
319
|
Chris@16
|
320 template<typename predicate_type>
|
Chris@16
|
321 void wait(unique_lock<mutex>& m,predicate_type pred)
|
Chris@16
|
322 {
|
Chris@16
|
323 while(!pred()) wait(m);
|
Chris@16
|
324 }
|
Chris@16
|
325
|
Chris@16
|
326
|
Chris@16
|
327 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
328 bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time)
|
Chris@16
|
329 {
|
Chris@16
|
330 return do_wait(m,abs_time);
|
Chris@16
|
331 }
|
Chris@16
|
332
|
Chris@16
|
333 bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time)
|
Chris@16
|
334 {
|
Chris@16
|
335 return do_wait(m,system_time(abs_time));
|
Chris@16
|
336 }
|
Chris@16
|
337 template<typename duration_type>
|
Chris@16
|
338 bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
|
Chris@16
|
339 {
|
Chris@101
|
340 if (wait_duration.is_pos_infinity())
|
Chris@101
|
341 {
|
Chris@101
|
342 wait(m); // or do_wait(m,detail::timeout::sentinel());
|
Chris@101
|
343 return true;
|
Chris@101
|
344 }
|
Chris@101
|
345 if (wait_duration.is_special())
|
Chris@101
|
346 {
|
Chris@101
|
347 return true;
|
Chris@101
|
348 }
|
Chris@101
|
349 return do_wait(m,wait_duration.total_milliseconds());
|
Chris@16
|
350 }
|
Chris@16
|
351
|
Chris@16
|
352 template<typename predicate_type>
|
Chris@16
|
353 bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time,predicate_type pred)
|
Chris@16
|
354 {
|
Chris@16
|
355 return do_wait(m,abs_time,pred);
|
Chris@16
|
356 }
|
Chris@16
|
357 template<typename predicate_type>
|
Chris@16
|
358 bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time,predicate_type pred)
|
Chris@16
|
359 {
|
Chris@16
|
360 return do_wait(m,system_time(abs_time),pred);
|
Chris@16
|
361 }
|
Chris@16
|
362 template<typename duration_type,typename predicate_type>
|
Chris@16
|
363 bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
|
Chris@16
|
364 {
|
Chris@16
|
365 return do_wait(m,wait_duration.total_milliseconds(),pred);
|
Chris@16
|
366 }
|
Chris@16
|
367 #endif
|
Chris@16
|
368 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
369
|
Chris@16
|
370 template <class Clock, class Duration>
|
Chris@16
|
371 cv_status
|
Chris@16
|
372 wait_until(
|
Chris@16
|
373 unique_lock<mutex>& lock,
|
Chris@16
|
374 const chrono::time_point<Clock, Duration>& t)
|
Chris@16
|
375 {
|
Chris@16
|
376 using namespace chrono;
|
Chris@16
|
377 chrono::time_point<Clock, Duration> now = Clock::now();
|
Chris@16
|
378 if (t<=now) {
|
Chris@16
|
379 return cv_status::timeout;
|
Chris@16
|
380 }
|
Chris@16
|
381 do_wait(lock, ceil<milliseconds>(t-now).count());
|
Chris@16
|
382 return Clock::now() < t ? cv_status::no_timeout :
|
Chris@16
|
383 cv_status::timeout;
|
Chris@16
|
384 }
|
Chris@16
|
385
|
Chris@16
|
386 template <class Rep, class Period>
|
Chris@16
|
387 cv_status
|
Chris@16
|
388 wait_for(
|
Chris@16
|
389 unique_lock<mutex>& lock,
|
Chris@16
|
390 const chrono::duration<Rep, Period>& d)
|
Chris@16
|
391 {
|
Chris@16
|
392 using namespace chrono;
|
Chris@16
|
393 if (d<=chrono::duration<Rep, Period>::zero()) {
|
Chris@16
|
394 return cv_status::timeout;
|
Chris@16
|
395 }
|
Chris@16
|
396
|
Chris@16
|
397 steady_clock::time_point c_now = steady_clock::now();
|
Chris@16
|
398 do_wait(lock, ceil<milliseconds>(d).count());
|
Chris@16
|
399 return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
Chris@16
|
400 cv_status::timeout;
|
Chris@16
|
401 }
|
Chris@16
|
402
|
Chris@16
|
403 template <class Clock, class Duration, class Predicate>
|
Chris@16
|
404 bool
|
Chris@16
|
405 wait_until(
|
Chris@16
|
406 unique_lock<mutex>& lock,
|
Chris@16
|
407 const chrono::time_point<Clock, Duration>& t,
|
Chris@16
|
408 Predicate pred)
|
Chris@16
|
409 {
|
Chris@16
|
410 while (!pred())
|
Chris@16
|
411 {
|
Chris@16
|
412 if (wait_until(lock, t) == cv_status::timeout)
|
Chris@16
|
413 return pred();
|
Chris@16
|
414 }
|
Chris@16
|
415 return true;
|
Chris@16
|
416 }
|
Chris@16
|
417 template <class Rep, class Period, class Predicate>
|
Chris@16
|
418 bool
|
Chris@16
|
419 wait_for(
|
Chris@16
|
420 unique_lock<mutex>& lock,
|
Chris@16
|
421 const chrono::duration<Rep, Period>& d,
|
Chris@16
|
422 Predicate pred)
|
Chris@16
|
423 {
|
Chris@16
|
424 return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
Chris@16
|
425 }
|
Chris@16
|
426 #endif
|
Chris@16
|
427 };
|
Chris@16
|
428
|
Chris@16
|
429 class condition_variable_any:
|
Chris@16
|
430 private detail::basic_condition_variable
|
Chris@16
|
431 {
|
Chris@16
|
432 public:
|
Chris@16
|
433 BOOST_THREAD_NO_COPYABLE(condition_variable_any)
|
Chris@16
|
434 condition_variable_any()
|
Chris@16
|
435 {}
|
Chris@16
|
436
|
Chris@16
|
437 using detail::basic_condition_variable::notify_one;
|
Chris@16
|
438 using detail::basic_condition_variable::notify_all;
|
Chris@16
|
439
|
Chris@16
|
440 template<typename lock_type>
|
Chris@16
|
441 void wait(lock_type& m)
|
Chris@16
|
442 {
|
Chris@16
|
443 do_wait(m,detail::timeout::sentinel());
|
Chris@16
|
444 }
|
Chris@16
|
445
|
Chris@16
|
446 template<typename lock_type,typename predicate_type>
|
Chris@16
|
447 void wait(lock_type& m,predicate_type pred)
|
Chris@16
|
448 {
|
Chris@16
|
449 while(!pred()) wait(m);
|
Chris@16
|
450 }
|
Chris@16
|
451
|
Chris@16
|
452 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
453 template<typename lock_type>
|
Chris@16
|
454 bool timed_wait(lock_type& m,boost::system_time const& abs_time)
|
Chris@16
|
455 {
|
Chris@16
|
456 return do_wait(m,abs_time);
|
Chris@16
|
457 }
|
Chris@16
|
458
|
Chris@16
|
459 template<typename lock_type>
|
Chris@16
|
460 bool timed_wait(lock_type& m,boost::xtime const& abs_time)
|
Chris@16
|
461 {
|
Chris@16
|
462 return do_wait(m,system_time(abs_time));
|
Chris@16
|
463 }
|
Chris@16
|
464
|
Chris@16
|
465 template<typename lock_type,typename duration_type>
|
Chris@16
|
466 bool timed_wait(lock_type& m,duration_type const& wait_duration)
|
Chris@16
|
467 {
|
Chris@16
|
468 return do_wait(m,wait_duration.total_milliseconds());
|
Chris@16
|
469 }
|
Chris@16
|
470
|
Chris@16
|
471 template<typename lock_type,typename predicate_type>
|
Chris@16
|
472 bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred)
|
Chris@16
|
473 {
|
Chris@16
|
474 return do_wait(m,abs_time,pred);
|
Chris@16
|
475 }
|
Chris@16
|
476
|
Chris@16
|
477 template<typename lock_type,typename predicate_type>
|
Chris@16
|
478 bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred)
|
Chris@16
|
479 {
|
Chris@16
|
480 return do_wait(m,system_time(abs_time),pred);
|
Chris@16
|
481 }
|
Chris@16
|
482
|
Chris@16
|
483 template<typename lock_type,typename duration_type,typename predicate_type>
|
Chris@16
|
484 bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
|
Chris@16
|
485 {
|
Chris@16
|
486 return do_wait(m,wait_duration.total_milliseconds(),pred);
|
Chris@16
|
487 }
|
Chris@16
|
488 #endif
|
Chris@16
|
489 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
490
|
Chris@16
|
491 template <class lock_type, class Clock, class Duration>
|
Chris@16
|
492 cv_status
|
Chris@16
|
493 wait_until(
|
Chris@16
|
494 lock_type& lock,
|
Chris@16
|
495 const chrono::time_point<Clock, Duration>& t)
|
Chris@16
|
496 {
|
Chris@16
|
497 using namespace chrono;
|
Chris@16
|
498 chrono::time_point<Clock, Duration> now = Clock::now();
|
Chris@16
|
499 if (t<=now) {
|
Chris@16
|
500 return cv_status::timeout;
|
Chris@16
|
501 }
|
Chris@16
|
502 do_wait(lock, ceil<milliseconds>(t-now).count());
|
Chris@16
|
503 return Clock::now() < t ? cv_status::no_timeout :
|
Chris@16
|
504 cv_status::timeout;
|
Chris@16
|
505 }
|
Chris@16
|
506
|
Chris@16
|
507 template <class lock_type, class Rep, class Period>
|
Chris@16
|
508 cv_status
|
Chris@16
|
509 wait_for(
|
Chris@16
|
510 lock_type& lock,
|
Chris@16
|
511 const chrono::duration<Rep, Period>& d)
|
Chris@16
|
512 {
|
Chris@16
|
513 using namespace chrono;
|
Chris@16
|
514 if (d<=chrono::duration<Rep, Period>::zero()) {
|
Chris@16
|
515 return cv_status::timeout;
|
Chris@16
|
516 }
|
Chris@16
|
517 steady_clock::time_point c_now = steady_clock::now();
|
Chris@16
|
518 do_wait(lock, ceil<milliseconds>(d).count());
|
Chris@16
|
519 return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
Chris@16
|
520 cv_status::timeout;
|
Chris@16
|
521 }
|
Chris@16
|
522
|
Chris@16
|
523 template <class lock_type, class Clock, class Duration, class Predicate>
|
Chris@16
|
524 bool
|
Chris@16
|
525 wait_until(
|
Chris@16
|
526 lock_type& lock,
|
Chris@16
|
527 const chrono::time_point<Clock, Duration>& t,
|
Chris@16
|
528 Predicate pred)
|
Chris@16
|
529 {
|
Chris@16
|
530 while (!pred())
|
Chris@16
|
531 {
|
Chris@16
|
532 if (wait_until(lock, t) == cv_status::timeout)
|
Chris@16
|
533 return pred();
|
Chris@16
|
534 }
|
Chris@16
|
535 return true;
|
Chris@16
|
536 }
|
Chris@16
|
537
|
Chris@16
|
538 template <class lock_type, class Rep, class Period, class Predicate>
|
Chris@16
|
539 bool
|
Chris@16
|
540 wait_for(
|
Chris@16
|
541 lock_type& lock,
|
Chris@16
|
542 const chrono::duration<Rep, Period>& d,
|
Chris@16
|
543 Predicate pred)
|
Chris@16
|
544 {
|
Chris@16
|
545 return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
Chris@16
|
546 }
|
Chris@16
|
547 #endif
|
Chris@16
|
548 };
|
Chris@16
|
549
|
Chris@16
|
550 BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
|
Chris@16
|
551 }
|
Chris@16
|
552
|
Chris@16
|
553 #include <boost/config/abi_suffix.hpp>
|
Chris@16
|
554
|
Chris@16
|
555 #endif
|