1 // Copyright (C) 2001-2003
3 // Copyright (C) 2007-8 Anthony Williams
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 #if !defined(UTIL_INL_WEK01242003)
9 #define UTIL_INL_WEK01242003
11 #include <boost/thread/xtime.hpp>
12 #include <boost/thread/mutex.hpp>
13 #include <boost/thread/condition.hpp>
14 #include <boost/thread/thread.hpp>
16 #ifndef DEFAULT_EXECUTION_MONITOR_TYPE
17 # define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition
20 // boostinspect:nounnamed
26 inline boost::xtime delay(int secs, int msecs=0, int nsecs=0)
28 const int MILLISECONDS_PER_SECOND = 1000;
29 const int NANOSECONDS_PER_SECOND = 1000000000;
30 const int NANOSECONDS_PER_MILLISECOND = 1000000;
33 if (boost::TIME_UTC_ != boost::xtime_get (&xt, boost::TIME_UTC_))
34 BOOST_ERROR ("boost::xtime_get != boost::TIME_UTC_");
37 msecs += nsecs / NANOSECONDS_PER_MILLISECOND;
38 secs += msecs / MILLISECONDS_PER_SECOND;
39 nsecs += (msecs % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
40 xt.nsec = nsecs % NANOSECONDS_PER_SECOND;
41 xt.sec += secs + (nsecs / NANOSECONDS_PER_SECOND);
53 inline bool in_range(const boost::xtime& xt, int secs=1)
55 boost::xtime min = delay(-secs);
56 boost::xtime max = delay(0);
57 return (boost::xtime_cmp(xt, min) >= 0) &&
58 (boost::xtime_cmp(xt, max) <= 0);
67 class execution_monitor
70 enum wait_type { use_sleep_only, use_mutex, use_condition };
72 execution_monitor(wait_type type, int secs)
73 : done(false), type(type), secs(secs) { }
76 if (type != use_sleep_only) {
77 boost::unique_lock<boost::mutex> lock(mutex); done = false;
84 if (type != use_sleep_only) {
85 boost::unique_lock<boost::mutex> lock(mutex);
87 if (type == use_condition)
95 boost::xtime xt = delay(secs);
96 if (type != use_condition)
97 boost::thread::sleep(xt);
98 if (type != use_sleep_only) {
99 boost::unique_lock<boost::mutex> lock(mutex);
100 while (type == use_condition && !done) {
101 if (!cond.timed_wait(lock, xt))
111 boost::condition cond;
117 namespace thread_detail_anon
119 template <typename F>
120 class indirect_adapter
123 indirect_adapter(F func, execution_monitor& monitor)
124 : func(func), monitor(monitor) { }
125 void operator()() const
129 boost::thread thrd(func);
142 execution_monitor& monitor;
143 void operator=(indirect_adapter&);
147 // boostinspect:nounnamed
151 template <typename F>
152 void timed_test(F func, int secs,
153 execution_monitor::wait_type type=DEFAULT_EXECUTION_MONITOR_TYPE)
155 execution_monitor monitor(type, secs);
156 thread_detail_anon::indirect_adapter<F> ifunc(func, monitor);
158 boost::thread thrd(ifunc);
159 BOOST_REQUIRE_MESSAGE(monitor.wait(),
160 "Timed test didn't complete in time, possible deadlock.");
165 namespace thread_detail_anon
168 template <typename F, typename T>
172 thread_binder(const F& func, const T& param)
173 : func(func), param(param) { }
174 void operator()() const { func(param); }
183 // boostinspect:nounnamed
186 template <typename F, typename T>
187 thread_detail_anon::thread_binder<F, T> bind(const F& func, const T& param)
189 return thread_detail_anon::thread_binder<F, T>(func, param);
193 namespace thread_detail_anon
196 template <typename R, typename T>
197 class thread_member_binder
200 thread_member_binder(R (T::*func)(), T& param)
201 : func(func), param(param) { }
202 void operator()() const { (param.*func)(); }
205 void operator=(thread_member_binder&);
213 // boostinspect:nounnamed
216 template <typename R, typename T>
217 thread_detail_anon::thread_member_binder<R, T> bind(R (T::*func)(), T& param)
219 return thread_detail_anon::thread_member_binder<R, T>(func, param);