Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/thread/test/util.inl @ 14

Last change on this file since 14 was 12, checked in by landauf, 17 years ago

added boost

File size: 4.1 KB
Line 
1// Copyright (C) 2001-2003
2// William E. Kempf
3//
4// Permission to use, copy, modify, distribute and sell this software
5// and its documentation for any purpose is hereby granted without fee,
6// provided that the above copyright notice appear in all copies and
7// that both that copyright notice and this permission notice appear
8// in supporting documentation.  William E. Kempf makes no representations
9// about the suitability of this software for any purpose.
10// It is provided "as is" without express or implied warranty.
11
12#if !defined(UTIL_INL_WEK01242003)
13#define UTIL_INL_WEK01242003
14
15#include <boost/thread/xtime.hpp>
16#include <boost/thread/mutex.hpp>
17#include <boost/thread/condition.hpp>
18#include <boost/thread/thread.hpp>
19
20#ifndef DEFAULT_EXECUTION_MONITOR_TYPE
21#   define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition
22#endif
23
24namespace
25{
26inline boost::xtime delay(int secs, int msecs=0, int nsecs=0)
27{
28    const int MILLISECONDS_PER_SECOND = 1000;
29    const int NANOSECONDS_PER_SECOND = 1000000000;
30    const int NANOSECONDS_PER_MILLISECOND = 1000000;
31
32    boost::xtime xt;
33    if (boost::TIME_UTC != boost::xtime_get (&xt, boost::TIME_UTC))
34        BOOST_ERROR ("boost::xtime_get != boost::TIME_UTC");
35
36    nsecs += xt.nsec;
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);
42
43    return xt;
44}
45
46inline bool in_range(const boost::xtime& xt, int secs=1)
47{
48    boost::xtime min = delay(-secs);
49    boost::xtime max = delay(0);
50    return (boost::xtime_cmp(xt, min) >= 0) &&
51        (boost::xtime_cmp(xt, max) <= 0);
52}
53
54class execution_monitor
55{
56public:
57    enum wait_type { use_sleep_only, use_mutex, use_condition };
58
59    execution_monitor(wait_type type, int secs)
60        : done(false), type(type), secs(secs) { }
61    void start()
62    {
63        if (type != use_sleep_only) {
64            boost::mutex::scoped_lock lock(mutex); done = false;
65        } else {
66            done = false;
67        }
68    }
69    void finish()
70    {
71        if (type != use_sleep_only) {
72            boost::mutex::scoped_lock lock(mutex);
73            done = true;
74            if (type == use_condition)
75                cond.notify_one();
76        } else {
77            done = true;
78        }
79    }
80    bool wait()
81    {
82        boost::xtime xt = delay(secs);
83        if (type != use_condition)
84            boost::thread::sleep(xt);
85        if (type != use_sleep_only) {
86            boost::mutex::scoped_lock lock(mutex);
87            while (type == use_condition && !done) {
88                if (!cond.timed_wait(lock, xt))
89                    break;
90            }
91            return done;
92        }
93        return done;
94    }
95
96private:
97    boost::mutex mutex;
98    boost::condition cond;
99    bool done;
100    wait_type type;
101    int secs;
102};
103
104template <typename F>
105class indirect_adapter
106{
107public:
108    indirect_adapter(F func, execution_monitor& monitor)
109        : func(func), monitor(monitor) { }
110    void operator()() const
111    {
112        try
113        {
114            boost::thread thrd(func);
115            thrd.join();
116        }
117        catch (...)
118        {
119            monitor.finish();
120            throw;
121        }
122        monitor.finish();
123    }
124
125private:
126    F func;
127    execution_monitor& monitor;
128};
129
130template <typename F>
131void timed_test(F func, int secs,
132    execution_monitor::wait_type type=DEFAULT_EXECUTION_MONITOR_TYPE)
133{
134    execution_monitor monitor(type, secs);
135    indirect_adapter<F> ifunc(func, monitor);
136    monitor.start();
137    boost::thread thrd(ifunc);
138    BOOST_REQUIRE_MESSAGE(monitor.wait(),
139        "Timed test didn't complete in time, possible deadlock.");
140}
141
142template <typename F, typename T>
143class thread_binder
144{
145public:
146    thread_binder(const F& func, const T& param)
147        : func(func), param(param) { }
148    void operator()() const { func(param); }
149
150private:
151    F func;
152    T param;
153};
154
155template <typename F, typename T>
156thread_binder<F, T> bind(const F& func, const T& param)
157{
158    return thread_binder<F, T>(func, param);
159}
160} // namespace
161
162#endif
Note: See TracBrowser for help on using the repository browser.