summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/thread/test/util.inl
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/thread/test/util.inl')
-rw-r--r--src/boost/libs/thread/test/util.inl243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/boost/libs/thread/test/util.inl b/src/boost/libs/thread/test/util.inl
new file mode 100644
index 000000000..e4709bc3e
--- /dev/null
+++ b/src/boost/libs/thread/test/util.inl
@@ -0,0 +1,243 @@
+// Copyright (C) 2001-2003
+// William E. Kempf
+// Copyright (C) 2007-8 Anthony Williams
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(UTIL_INL_WEK01242003)
+#define UTIL_INL_WEK01242003
+
+#include <boost/thread/xtime.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/config.hpp>
+
+#ifndef DEFAULT_EXECUTION_MONITOR_TYPE
+# define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition
+#endif
+
+// boostinspect:nounnamed
+
+
+
+namespace
+{
+inline boost::xtime delay(int secs, int msecs=0, int nsecs=0)
+{
+ const int MILLISECONDS_PER_SECOND = 1000;
+ const int NANOSECONDS_PER_SECOND = 1000000000;
+ const int NANOSECONDS_PER_MILLISECOND = 1000000;
+
+ boost::xtime xt;
+ if (boost::TIME_UTC_ != boost::xtime_get (&xt, boost::TIME_UTC_))
+ BOOST_ERROR ("boost::xtime_get != boost::TIME_UTC_");
+
+ nsecs += xt.nsec;
+ msecs += nsecs / NANOSECONDS_PER_MILLISECOND;
+ secs += msecs / MILLISECONDS_PER_SECOND;
+ nsecs += (msecs % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
+ xt.nsec = nsecs % NANOSECONDS_PER_SECOND;
+ xt.sec += secs + (nsecs / NANOSECONDS_PER_SECOND);
+
+ return xt;
+}
+
+}
+namespace boost
+{
+namespace threads
+{
+namespace test
+{
+inline bool in_range(const boost::xtime& xt, int secs=1)
+{
+ boost::xtime min = delay(-secs);
+ boost::xtime max = delay(0);
+ return (boost::xtime_cmp(xt, min) >= 0) &&
+ (boost::xtime_cmp(xt, max) <= 0);
+}
+}
+}
+}
+
+
+namespace
+{
+class execution_monitor
+{
+public:
+ enum wait_type { use_sleep_only, use_mutex, use_condition };
+
+ execution_monitor(wait_type type, int secs)
+ : done(false), type(type), secs(secs) { }
+ void start()
+ {
+ if (type != use_sleep_only) {
+ boost::unique_lock<boost::mutex> lock(mutex); done = false;
+ } else {
+ done = false;
+ }
+ }
+ void finish()
+ {
+ if (type != use_sleep_only) {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ done = true;
+ if (type == use_condition)
+ cond.notify_one();
+ } else {
+ done = true;
+ }
+ }
+ bool wait()
+ {
+ boost::xtime xt = delay(secs);
+ if (type == use_sleep_only) {
+ boost::thread::sleep(xt);
+ return done;
+ }
+ if (type == use_condition) {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ while (!done) {
+ if (!cond.timed_wait(lock, xt))
+ break;
+ }
+ return done;
+ }
+ for (int i = 0; ; ++i) {
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ if (done)
+ return true;
+ else if (i > secs * 2)
+ return done;
+ }
+ boost::thread::sleep(delay(0, 500));
+ }
+ }
+
+private:
+ boost::mutex mutex;
+ boost::condition cond;
+ bool done;
+ wait_type type;
+ int secs;
+};
+}
+namespace thread_detail_anon
+{
+template <typename F>
+class indirect_adapter
+{
+public:
+ indirect_adapter(F func, execution_monitor& monitor)
+ : func(func), monitor(monitor) { }
+#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
+ indirect_adapter(indirect_adapter const&) = default;
+#endif
+
+ void operator()() const
+ {
+ try
+ {
+ boost::thread thrd(func);
+ thrd.join();
+ }
+ catch (...)
+ {
+ monitor.finish();
+ throw;
+ }
+ monitor.finish();
+ }
+
+private:
+ F func;
+ execution_monitor& monitor;
+ void operator=(indirect_adapter&);
+};
+
+}
+// boostinspect:nounnamed
+namespace
+{
+
+template <typename F>
+void timed_test(F func, int secs,
+ execution_monitor::wait_type type=DEFAULT_EXECUTION_MONITOR_TYPE)
+{
+ execution_monitor monitor(type, secs);
+ thread_detail_anon::indirect_adapter<F> ifunc(func, monitor);
+ monitor.start();
+ boost::thread thrd(ifunc);
+ BOOST_REQUIRE_MESSAGE(monitor.wait(),
+ "Timed test didn't complete in time, possible deadlock.");
+}
+
+}
+
+namespace thread_detail_anon
+{
+
+template <typename F, typename T>
+class thread_binder
+{
+public:
+ thread_binder(const F& func, const T& param)
+ : func(func), param(param) { }
+ void operator()() const { func(param); }
+
+private:
+ F func;
+ T param;
+};
+
+}
+
+// boostinspect:nounnamed
+namespace
+{
+template <typename F, typename T>
+thread_detail_anon::thread_binder<F, T> bind(const F& func, const T& param)
+{
+ return thread_detail_anon::thread_binder<F, T>(func, param);
+}
+}
+
+namespace thread_detail_anon
+{
+
+template <typename R, typename T>
+class thread_member_binder
+{
+public:
+ thread_member_binder(R (T::*func)(), T& param)
+ : func(func), param(param) { }
+#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
+ thread_member_binder(thread_member_binder const&) = default;
+#endif
+
+ void operator()() const { (param.*func)(); }
+
+private:
+ void operator=(thread_member_binder&);
+
+ R (T::*func)();
+ T& param;
+};
+
+}
+
+// boostinspect:nounnamed
+namespace
+{
+template <typename R, typename T>
+thread_detail_anon::thread_member_binder<R, T> bind(R (T::*func)(), T& param)
+{
+ return thread_detail_anon::thread_member_binder<R, T>(func, param);
+}
+} // namespace
+
+#endif