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@16
|
99 unsigned long const woken_result=detail::win32::WaitForSingleObject(wake_sem,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@16
|
340 return do_wait(m,wait_duration.total_milliseconds());
|
Chris@16
|
341 }
|
Chris@16
|
342
|
Chris@16
|
343 template<typename predicate_type>
|
Chris@16
|
344 bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time,predicate_type pred)
|
Chris@16
|
345 {
|
Chris@16
|
346 return do_wait(m,abs_time,pred);
|
Chris@16
|
347 }
|
Chris@16
|
348 template<typename predicate_type>
|
Chris@16
|
349 bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time,predicate_type pred)
|
Chris@16
|
350 {
|
Chris@16
|
351 return do_wait(m,system_time(abs_time),pred);
|
Chris@16
|
352 }
|
Chris@16
|
353 template<typename duration_type,typename predicate_type>
|
Chris@16
|
354 bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
|
Chris@16
|
355 {
|
Chris@16
|
356 return do_wait(m,wait_duration.total_milliseconds(),pred);
|
Chris@16
|
357 }
|
Chris@16
|
358 #endif
|
Chris@16
|
359 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
360
|
Chris@16
|
361 template <class Clock, class Duration>
|
Chris@16
|
362 cv_status
|
Chris@16
|
363 wait_until(
|
Chris@16
|
364 unique_lock<mutex>& lock,
|
Chris@16
|
365 const chrono::time_point<Clock, Duration>& t)
|
Chris@16
|
366 {
|
Chris@16
|
367 using namespace chrono;
|
Chris@16
|
368 chrono::time_point<Clock, Duration> now = Clock::now();
|
Chris@16
|
369 if (t<=now) {
|
Chris@16
|
370 return cv_status::timeout;
|
Chris@16
|
371 }
|
Chris@16
|
372 do_wait(lock, ceil<milliseconds>(t-now).count());
|
Chris@16
|
373 return Clock::now() < t ? cv_status::no_timeout :
|
Chris@16
|
374 cv_status::timeout;
|
Chris@16
|
375 }
|
Chris@16
|
376
|
Chris@16
|
377 template <class Rep, class Period>
|
Chris@16
|
378 cv_status
|
Chris@16
|
379 wait_for(
|
Chris@16
|
380 unique_lock<mutex>& lock,
|
Chris@16
|
381 const chrono::duration<Rep, Period>& d)
|
Chris@16
|
382 {
|
Chris@16
|
383 using namespace chrono;
|
Chris@16
|
384 if (d<=chrono::duration<Rep, Period>::zero()) {
|
Chris@16
|
385 return cv_status::timeout;
|
Chris@16
|
386 }
|
Chris@16
|
387
|
Chris@16
|
388 steady_clock::time_point c_now = steady_clock::now();
|
Chris@16
|
389 do_wait(lock, ceil<milliseconds>(d).count());
|
Chris@16
|
390 return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
Chris@16
|
391 cv_status::timeout;
|
Chris@16
|
392 }
|
Chris@16
|
393
|
Chris@16
|
394 template <class Clock, class Duration, class Predicate>
|
Chris@16
|
395 bool
|
Chris@16
|
396 wait_until(
|
Chris@16
|
397 unique_lock<mutex>& lock,
|
Chris@16
|
398 const chrono::time_point<Clock, Duration>& t,
|
Chris@16
|
399 Predicate pred)
|
Chris@16
|
400 {
|
Chris@16
|
401 while (!pred())
|
Chris@16
|
402 {
|
Chris@16
|
403 if (wait_until(lock, t) == cv_status::timeout)
|
Chris@16
|
404 return pred();
|
Chris@16
|
405 }
|
Chris@16
|
406 return true;
|
Chris@16
|
407 }
|
Chris@16
|
408 template <class Rep, class Period, class Predicate>
|
Chris@16
|
409 bool
|
Chris@16
|
410 wait_for(
|
Chris@16
|
411 unique_lock<mutex>& lock,
|
Chris@16
|
412 const chrono::duration<Rep, Period>& d,
|
Chris@16
|
413 Predicate pred)
|
Chris@16
|
414 {
|
Chris@16
|
415 return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
Chris@16
|
416 }
|
Chris@16
|
417 #endif
|
Chris@16
|
418 };
|
Chris@16
|
419
|
Chris@16
|
420 class condition_variable_any:
|
Chris@16
|
421 private detail::basic_condition_variable
|
Chris@16
|
422 {
|
Chris@16
|
423 public:
|
Chris@16
|
424 BOOST_THREAD_NO_COPYABLE(condition_variable_any)
|
Chris@16
|
425 condition_variable_any()
|
Chris@16
|
426 {}
|
Chris@16
|
427
|
Chris@16
|
428 using detail::basic_condition_variable::notify_one;
|
Chris@16
|
429 using detail::basic_condition_variable::notify_all;
|
Chris@16
|
430
|
Chris@16
|
431 template<typename lock_type>
|
Chris@16
|
432 void wait(lock_type& m)
|
Chris@16
|
433 {
|
Chris@16
|
434 do_wait(m,detail::timeout::sentinel());
|
Chris@16
|
435 }
|
Chris@16
|
436
|
Chris@16
|
437 template<typename lock_type,typename predicate_type>
|
Chris@16
|
438 void wait(lock_type& m,predicate_type pred)
|
Chris@16
|
439 {
|
Chris@16
|
440 while(!pred()) wait(m);
|
Chris@16
|
441 }
|
Chris@16
|
442
|
Chris@16
|
443 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
444 template<typename lock_type>
|
Chris@16
|
445 bool timed_wait(lock_type& m,boost::system_time const& abs_time)
|
Chris@16
|
446 {
|
Chris@16
|
447 return do_wait(m,abs_time);
|
Chris@16
|
448 }
|
Chris@16
|
449
|
Chris@16
|
450 template<typename lock_type>
|
Chris@16
|
451 bool timed_wait(lock_type& m,boost::xtime const& abs_time)
|
Chris@16
|
452 {
|
Chris@16
|
453 return do_wait(m,system_time(abs_time));
|
Chris@16
|
454 }
|
Chris@16
|
455
|
Chris@16
|
456 template<typename lock_type,typename duration_type>
|
Chris@16
|
457 bool timed_wait(lock_type& m,duration_type const& wait_duration)
|
Chris@16
|
458 {
|
Chris@16
|
459 return do_wait(m,wait_duration.total_milliseconds());
|
Chris@16
|
460 }
|
Chris@16
|
461
|
Chris@16
|
462 template<typename lock_type,typename predicate_type>
|
Chris@16
|
463 bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred)
|
Chris@16
|
464 {
|
Chris@16
|
465 return do_wait(m,abs_time,pred);
|
Chris@16
|
466 }
|
Chris@16
|
467
|
Chris@16
|
468 template<typename lock_type,typename predicate_type>
|
Chris@16
|
469 bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred)
|
Chris@16
|
470 {
|
Chris@16
|
471 return do_wait(m,system_time(abs_time),pred);
|
Chris@16
|
472 }
|
Chris@16
|
473
|
Chris@16
|
474 template<typename lock_type,typename duration_type,typename predicate_type>
|
Chris@16
|
475 bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
|
Chris@16
|
476 {
|
Chris@16
|
477 return do_wait(m,wait_duration.total_milliseconds(),pred);
|
Chris@16
|
478 }
|
Chris@16
|
479 #endif
|
Chris@16
|
480 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
481
|
Chris@16
|
482 template <class lock_type, class Clock, class Duration>
|
Chris@16
|
483 cv_status
|
Chris@16
|
484 wait_until(
|
Chris@16
|
485 lock_type& lock,
|
Chris@16
|
486 const chrono::time_point<Clock, Duration>& t)
|
Chris@16
|
487 {
|
Chris@16
|
488 using namespace chrono;
|
Chris@16
|
489 chrono::time_point<Clock, Duration> now = Clock::now();
|
Chris@16
|
490 if (t<=now) {
|
Chris@16
|
491 return cv_status::timeout;
|
Chris@16
|
492 }
|
Chris@16
|
493 do_wait(lock, ceil<milliseconds>(t-now).count());
|
Chris@16
|
494 return Clock::now() < t ? cv_status::no_timeout :
|
Chris@16
|
495 cv_status::timeout;
|
Chris@16
|
496 }
|
Chris@16
|
497
|
Chris@16
|
498 template <class lock_type, class Rep, class Period>
|
Chris@16
|
499 cv_status
|
Chris@16
|
500 wait_for(
|
Chris@16
|
501 lock_type& lock,
|
Chris@16
|
502 const chrono::duration<Rep, Period>& d)
|
Chris@16
|
503 {
|
Chris@16
|
504 using namespace chrono;
|
Chris@16
|
505 if (d<=chrono::duration<Rep, Period>::zero()) {
|
Chris@16
|
506 return cv_status::timeout;
|
Chris@16
|
507 }
|
Chris@16
|
508 steady_clock::time_point c_now = steady_clock::now();
|
Chris@16
|
509 do_wait(lock, ceil<milliseconds>(d).count());
|
Chris@16
|
510 return steady_clock::now() - c_now < d ? cv_status::no_timeout :
|
Chris@16
|
511 cv_status::timeout;
|
Chris@16
|
512 }
|
Chris@16
|
513
|
Chris@16
|
514 template <class lock_type, class Clock, class Duration, class Predicate>
|
Chris@16
|
515 bool
|
Chris@16
|
516 wait_until(
|
Chris@16
|
517 lock_type& lock,
|
Chris@16
|
518 const chrono::time_point<Clock, Duration>& t,
|
Chris@16
|
519 Predicate pred)
|
Chris@16
|
520 {
|
Chris@16
|
521 while (!pred())
|
Chris@16
|
522 {
|
Chris@16
|
523 if (wait_until(lock, t) == cv_status::timeout)
|
Chris@16
|
524 return pred();
|
Chris@16
|
525 }
|
Chris@16
|
526 return true;
|
Chris@16
|
527 }
|
Chris@16
|
528
|
Chris@16
|
529 template <class lock_type, class Rep, class Period, class Predicate>
|
Chris@16
|
530 bool
|
Chris@16
|
531 wait_for(
|
Chris@16
|
532 lock_type& lock,
|
Chris@16
|
533 const chrono::duration<Rep, Period>& d,
|
Chris@16
|
534 Predicate pred)
|
Chris@16
|
535 {
|
Chris@16
|
536 return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
|
Chris@16
|
537 }
|
Chris@16
|
538 #endif
|
Chris@16
|
539 };
|
Chris@16
|
540
|
Chris@16
|
541 BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
|
Chris@16
|
542 }
|
Chris@16
|
543
|
Chris@16
|
544 #include <boost/config/abi_suffix.hpp>
|
Chris@16
|
545
|
Chris@16
|
546 #endif
|