From 244cfd3f01b84eabdfd193d413af24c97d1551fb Mon Sep 17 00:00:00 2001 From: nobody Date: Mon, 27 Jan 2003 22:44:08 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'thread_dev'. [SVN r17055] --- test/util.inl | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 test/util.inl diff --git a/test/util.inl b/test/util.inl new file mode 100644 index 00000000..446c039f --- /dev/null +++ b/test/util.inl @@ -0,0 +1,150 @@ +#if !defined(UTIL_INL_WEK01242003) +#define UTIL_INL_WEK01242003 + +#include +#include +#include +#include + +#ifndef DEFAULT_EXECUTION_MONITOR_TYPE +# define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition +#endif + +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; + BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC), + static_cast(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; + } + + 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); + } + + 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::mutex::scoped_lock lock(mutex); done = false; + } else { + done = false; + } + } + void finish() + { + if (type != use_sleep_only) { + boost::mutex::scoped_lock lock(mutex); + done = true; + if (type == use_condition) + cond.notify_one(); + } else { + done = true; + } + } + bool wait() + { + boost::xtime xt = delay(secs); + if (type != use_condition) + boost::thread::sleep(xt); + if (type != use_sleep_only) { + boost::mutex::scoped_lock lock(mutex); + while (type == use_condition && !done) { + if (!cond.timed_wait(lock, xt)) + break; + } + return done; + } + return done; + } + + private: + boost::mutex mutex; + boost::condition cond; + bool done; + wait_type type; + int secs; + }; + + template + class indirect_adapter + { + public: + indirect_adapter(F func, execution_monitor& monitor) + : func(func), monitor(monitor) { } + void operator()() const + { + try + { + boost::thread thrd(func); + thrd.join(); + } + catch (...) + { + monitor.finish(); + throw; + } + monitor.finish(); + } + + private: + F func; + execution_monitor& monitor; + }; + + template + void timed_test(F func, int secs, + execution_monitor::wait_type type=DEFAULT_EXECUTION_MONITOR_TYPE) + { + execution_monitor monitor(type, secs); + indirect_adapter ifunc(func, monitor); + monitor.start(); + boost::thread thrd(ifunc); + BOOST_REQUIRE_MESSAGE(monitor.wait(), + "Timed test didn't complete in time, possible deadlock."); + } + + template + class binder + { + public: + binder(const F& func, const T& param) + : func(func), param(param) { } + void operator()() const { func(param); } + + private: + F func; + T param; + }; + + template + binder bind(const F& func, const T& param) + { + return binder(func, param); + } +} // namespace + +#endif