]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/thread/test/util.inl
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / thread / test / util.inl
CommitLineData
7c673cae
FG
1// Copyright (C) 2001-2003
2// William E. Kempf
3// Copyright (C) 2007-8 Anthony Williams
4//
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)
7
8#if !defined(UTIL_INL_WEK01242003)
9#define UTIL_INL_WEK01242003
10
11#include <boost/thread/xtime.hpp>
12#include <boost/thread/mutex.hpp>
13#include <boost/thread/condition.hpp>
14#include <boost/thread/thread.hpp>
15
16#ifndef DEFAULT_EXECUTION_MONITOR_TYPE
17# define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition
18#endif
19
20// boostinspect:nounnamed
21
22
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
46}
47namespace boost
48{
49namespace threads
50{
51namespace test
52{
53inline bool in_range(const boost::xtime& xt, int secs=1)
54{
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);
59}
60}
61}
62}
63
64
65namespace
66{
67class execution_monitor
68{
69public:
70 enum wait_type { use_sleep_only, use_mutex, use_condition };
71
72 execution_monitor(wait_type type, int secs)
73 : done(false), type(type), secs(secs) { }
74 void start()
75 {
76 if (type != use_sleep_only) {
77 boost::unique_lock<boost::mutex> lock(mutex); done = false;
78 } else {
79 done = false;
80 }
81 }
82 void finish()
83 {
84 if (type != use_sleep_only) {
85 boost::unique_lock<boost::mutex> lock(mutex);
86 done = true;
87 if (type == use_condition)
88 cond.notify_one();
89 } else {
90 done = true;
91 }
92 }
93 bool wait()
94 {
95 boost::xtime xt = delay(secs);
92f5a8d4 96 if (type == use_sleep_only) {
7c673cae 97 boost::thread::sleep(xt);
92f5a8d4
TL
98 return done;
99 }
100 if (type == use_condition) {
7c673cae 101 boost::unique_lock<boost::mutex> lock(mutex);
92f5a8d4 102 while (!done) {
7c673cae
FG
103 if (!cond.timed_wait(lock, xt))
104 break;
105 }
106 return done;
107 }
92f5a8d4
TL
108 for (int i = 0; ; ++i) {
109 {
110 boost::unique_lock<boost::mutex> lock(mutex);
111 if (done)
112 return true;
113 else if (i > secs * 2)
114 return done;
115 }
116 boost::thread::sleep(delay(0, 500));
117 }
7c673cae
FG
118 }
119
120private:
121 boost::mutex mutex;
122 boost::condition cond;
123 bool done;
124 wait_type type;
125 int secs;
126};
127}
128namespace thread_detail_anon
129{
130template <typename F>
131class indirect_adapter
132{
133public:
134 indirect_adapter(F func, execution_monitor& monitor)
135 : func(func), monitor(monitor) { }
136 void operator()() const
137 {
138 try
139 {
140 boost::thread thrd(func);
141 thrd.join();
142 }
143 catch (...)
144 {
145 monitor.finish();
146 throw;
147 }
148 monitor.finish();
149 }
150
151private:
152 F func;
153 execution_monitor& monitor;
154 void operator=(indirect_adapter&);
155};
156
157}
158// boostinspect:nounnamed
159namespace
160{
161
162template <typename F>
163void timed_test(F func, int secs,
164 execution_monitor::wait_type type=DEFAULT_EXECUTION_MONITOR_TYPE)
165{
166 execution_monitor monitor(type, secs);
167 thread_detail_anon::indirect_adapter<F> ifunc(func, monitor);
168 monitor.start();
169 boost::thread thrd(ifunc);
170 BOOST_REQUIRE_MESSAGE(monitor.wait(),
171 "Timed test didn't complete in time, possible deadlock.");
172}
173
174}
175
176namespace thread_detail_anon
177{
178
179template <typename F, typename T>
180class thread_binder
181{
182public:
183 thread_binder(const F& func, const T& param)
184 : func(func), param(param) { }
185 void operator()() const { func(param); }
186
187private:
188 F func;
189 T param;
190};
191
192}
193
194// boostinspect:nounnamed
195namespace
196{
197template <typename F, typename T>
198thread_detail_anon::thread_binder<F, T> bind(const F& func, const T& param)
199{
200 return thread_detail_anon::thread_binder<F, T>(func, param);
201}
202}
203
204namespace thread_detail_anon
205{
206
207template <typename R, typename T>
208class thread_member_binder
209{
210public:
211 thread_member_binder(R (T::*func)(), T& param)
212 : func(func), param(param) { }
213 void operator()() const { (param.*func)(); }
214
215private:
216 void operator=(thread_member_binder&);
217
218 R (T::*func)();
219 T& param;
220};
221
222}
223
224// boostinspect:nounnamed
225namespace
226{
227template <typename R, typename T>
228thread_detail_anon::thread_member_binder<R, T> bind(R (T::*func)(), T& param)
229{
230 return thread_detail_anon::thread_member_binder<R, T>(func, param);
231}
232} // namespace
233
234#endif