1 /*=============================================================================
2 Copyright (c) 2002-2004 Martin Wille
3 http://spirit.sourceforge.net/
5 Use, modification and distribution is subject to the Boost Software
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
10 // std::lower_bound seems to perform awfully slow with _GLIBCXX_DEBUG enabled
14 #include <boost/config.hpp>
15 #include <boost/core/lightweight_test.hpp>
17 #if !defined(BOOST_HAS_THREADS) || defined(DONT_HAVE_BOOST) || defined(BOOST_DISABLE_THREADS)
20 std::cout
<< "skipped\n";
31 ////////////////////////////////////////////////////////////////////////////////
33 static const unsigned long initial_test_size
= 5000UL;
34 #if defined(_DEBUG) && (BOOST_MSVC >= 1400)
35 static const unsigned long maximum_test_size
= 10000UL;
37 static const unsigned long maximum_test_size
= 1000000UL;
40 ////////////////////////////////////////////////////////////////////////////////
42 #undef BOOST_SPIRIT_THREADSAFE
43 #define BOOST_SPIRIT_THREADSAFE
45 #include <boost/thread/thread.hpp>
46 #include <boost/spirit/home/classic/core/non_terminal/impl/object_with_id.ipp>
47 #include <boost/ref.hpp>
48 #include <boost/thread/xtime.hpp>
49 #include <boost/thread/mutex.hpp>
50 #include <boost/thread/lock_types.hpp>
53 #include <boost/core/lightweight_test.hpp>
55 using BOOST_SPIRIT_CLASSIC_NS::impl::object_with_id
;
58 typedef object_with_id
<tag1
> class1
;
60 unsigned long test_size
= initial_test_size
;
61 boost::xtime start_time
;
63 template <typename ClassT
>
66 test_task() : v(), m(), progress(0) {}
69 { // create lots of objects
72 v
.reserve(maximum_test_size
);
75 for (; i
<test_size
; ++i
)
76 v
.push_back(new ClassT
);
78 while ( i
< increase_test_size(i
) );
82 increase_test_size(unsigned long size
)
84 static boost::mutex m
;
85 boost::unique_lock
<boost::mutex
> l(m
);
87 if (size
<test_size
|| test_size
== maximum_test_size
)
91 boost::xtime_get(&now
, boost::TIME_UTC_
);
92 boost::xtime::xtime_sec_t seconds
= now
.sec
- start_time
.sec
;
96 if (test_size
> maximum_test_size
)
97 test_size
= maximum_test_size
;
103 std::vector
<ClassT
*> const &data() const
109 std::vector
<ClassT
*> v
;
111 unsigned int progress
;
114 template <typename T
>
115 class callable_reference_wrapper
116 : public boost::reference_wrapper
<T
>
119 explicit callable_reference_wrapper(T
& t
)
120 : boost::reference_wrapper
<T
>(t
)
122 inline void operator()() { this->get().operator()(); }
125 template <typename T
>
126 callable_reference_wrapper
<T
>
129 return callable_reference_wrapper
<T
>(t
);
132 test_task
<class1
> test1
;
133 test_task
<class1
> test2
;
134 test_task
<class1
> test3
;
137 template <typename ClassT
>
139 check_ascending(test_task
<ClassT
> const &t
)
141 typedef typename
std::vector
<ClassT
*>::const_iterator iter
;
142 iter
p(t
.data().begin());
143 iter
const e(t
.data().end());
148 if ((**n
).get_object_id()<=(**p
).get_object_id())
151 throw std::runtime_error("object ids out of order");
159 bool operator()(class1
const *p
, class1
const *q
) const
161 return p
->get_object_id() < q
->get_object_id();
165 template <typename ClassT
>
167 check_not_contained_in(
168 test_task
<ClassT
> const &candidate
,
169 test_task
<ClassT
> const &in
172 typedef typename
std::vector
<ClassT
*>::const_iterator iter
;
173 iter
p(candidate
.data().begin());
174 iter
const e(candidate
.data().end());
178 iter found
= std::lower_bound(in
.data().begin(),in
.data().end(),*p
,less1());
179 if (found
!=in
.data().end() &&
180 (**found
).get_object_id() == (**p
).get_object_id())
183 throw std::runtime_error("object ids not unqiue");
189 void concurrent_creation_of_objects()
192 boost::xtime_get(&start_time
, boost::TIME_UTC_
);
193 boost::thread
thread1(callable_ref(test1
));
194 boost::thread
thread2(callable_ref(test2
));
195 boost::thread
thread3(callable_ref(test3
));
203 void local_uniqueness()
207 BOOST_TEST(test1
.data().size()==test_size
);
208 BOOST_TEST(test2
.data().size()==test_size
);
209 BOOST_TEST(test3
.data().size()==test_size
);
212 void local_ordering_and_uniqueness()
214 // now all objects should have unique ids,
215 // the ids must be ascending within each vector
216 // check for ascending ids
217 check_ascending(test1
);
218 check_ascending(test2
);
219 check_ascending(test3
);
222 void global_uniqueness()
224 check_not_contained_in(test1
,test3
);
225 check_not_contained_in(test1
,test2
);
226 check_not_contained_in(test2
,test1
);
227 check_not_contained_in(test2
,test3
);
228 check_not_contained_in(test3
,test2
);
229 check_not_contained_in(test3
,test1
);
235 concurrent_creation_of_objects();
236 local_ordering_and_uniqueness();
238 return boost::report_errors();
241 #endif // BOOST_HAS_THREADS