Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/thread/test/util.inl @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 3.8 KB
Line 
1// Copyright (C) 2001-2003
2// William E. Kempf
3//
4//  Distributed under the Boost Software License, Version 1.0. (See accompanying
5//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7#if !defined(UTIL_INL_WEK01242003)
8#define UTIL_INL_WEK01242003
9
10#include <boost/thread/xtime.hpp>
11#include <boost/thread/mutex.hpp>
12#include <boost/thread/condition.hpp>
13#include <boost/thread/thread.hpp>
14
15#ifndef DEFAULT_EXECUTION_MONITOR_TYPE
16#   define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition
17#endif
18
19// boostinspect:nounnamed
20
21namespace
22{
23inline boost::xtime delay(int secs, int msecs=0, int nsecs=0)
24{
25    const int MILLISECONDS_PER_SECOND = 1000;
26    const int NANOSECONDS_PER_SECOND = 1000000000;
27    const int NANOSECONDS_PER_MILLISECOND = 1000000;
28
29    boost::xtime xt;
30    if (boost::TIME_UTC != boost::xtime_get (&xt, boost::TIME_UTC))
31        BOOST_ERROR ("boost::xtime_get != boost::TIME_UTC");
32
33    nsecs += xt.nsec;
34    msecs += nsecs / NANOSECONDS_PER_MILLISECOND;
35    secs += msecs / MILLISECONDS_PER_SECOND;
36    nsecs += (msecs % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
37    xt.nsec = nsecs % NANOSECONDS_PER_SECOND;
38    xt.sec += secs + (nsecs / NANOSECONDS_PER_SECOND);
39
40    return xt;
41}
42
43inline bool in_range(const boost::xtime& xt, int secs=1)
44{
45    boost::xtime min = delay(-secs);
46    boost::xtime max = delay(0);
47    return (boost::xtime_cmp(xt, min) >= 0) &&
48        (boost::xtime_cmp(xt, max) <= 0);
49}
50
51class execution_monitor
52{
53public:
54    enum wait_type { use_sleep_only, use_mutex, use_condition };
55
56    execution_monitor(wait_type type, int secs)
57        : done(false), type(type), secs(secs) { }
58    void start()
59    {
60        if (type != use_sleep_only) {
61            boost::mutex::scoped_lock lock(mutex); done = false;
62        } else {
63            done = false;
64        }
65    }
66    void finish()
67    {
68        if (type != use_sleep_only) {
69            boost::mutex::scoped_lock lock(mutex);
70            done = true;
71            if (type == use_condition)
72                cond.notify_one();
73        } else {
74            done = true;
75        }
76    }
77    bool wait()
78    {
79        boost::xtime xt = delay(secs);
80        if (type != use_condition)
81            boost::thread::sleep(xt);
82        if (type != use_sleep_only) {
83            boost::mutex::scoped_lock lock(mutex);
84            while (type == use_condition && !done) {
85                if (!cond.timed_wait(lock, xt))
86                    break;
87            }
88            return done;
89        }
90        return done;
91    }
92
93private:
94    boost::mutex mutex;
95    boost::condition cond;
96    bool done;
97    wait_type type;
98    int secs;
99};
100
101template <typename F>
102class indirect_adapter
103{
104public:
105    indirect_adapter(F func, execution_monitor& monitor)
106        : func(func), monitor(monitor) { }
107    void operator()() const
108    {
109        try
110        {
111            boost::thread thrd(func);
112            thrd.join();
113        }
114        catch (...)
115        {
116            monitor.finish();
117            throw;
118        }
119        monitor.finish();
120    }
121
122private:
123    F func;
124    execution_monitor& monitor;
125};
126
127template <typename F>
128void timed_test(F func, int secs,
129    execution_monitor::wait_type type=DEFAULT_EXECUTION_MONITOR_TYPE)
130{
131    execution_monitor monitor(type, secs);
132    indirect_adapter<F> ifunc(func, monitor);
133    monitor.start();
134    boost::thread thrd(ifunc);
135    BOOST_REQUIRE_MESSAGE(monitor.wait(),
136        "Timed test didn't complete in time, possible deadlock.");
137}
138
139template <typename F, typename T>
140class thread_binder
141{
142public:
143    thread_binder(const F& func, const T& param)
144        : func(func), param(param) { }
145    void operator()() const { func(param); }
146
147private:
148    F func;
149    T param;
150};
151
152template <typename F, typename T>
153thread_binder<F, T> bind(const F& func, const T& param)
154{
155    return thread_binder<F, T>(func, param);
156}
157} // namespace
158
159#endif
Note: See TracBrowser for help on using the repository browser.