/*============================================================================= Copyright (c) 2002-2004 Martin Wille http://spirit.sourceforge.net/ Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ // std::lower_bound seems to perform awfully slow with _GLIBCXX_DEBUG enabled #undef _GLIBCXX_DEBUG #include #include #include #if !defined(BOOST_HAS_THREADS) || defined(DONT_HAVE_BOOST) || defined(BOOST_DISABLE_THREADS) static void skipped() { std::cout << "skipped\n"; } int main() { skipped(); return 0; } #else //////////////////////////////////////////////////////////////////////////////// static const unsigned long initial_test_size = 5000UL; #if defined(_DEBUG) && (BOOST_MSVC >= 1400) static const unsigned long maximum_test_size = 10000UL; #else static const unsigned long maximum_test_size = 1000000UL; #endif //////////////////////////////////////////////////////////////////////////////// #undef BOOST_SPIRIT_THREADSAFE #define BOOST_SPIRIT_THREADSAFE #include #include #include #include #include #include #include #include #include using BOOST_SPIRIT_CLASSIC_NS::impl::object_with_id; struct tag1 {}; typedef object_with_id class1; unsigned long test_size = initial_test_size; boost::xtime start_time; template struct test_task { test_task() : v(), m(), progress(0) {} void operator ()() { // create lots of objects unsigned long i = 0; v.reserve(maximum_test_size); do { for (; i l(m); if (size maximum_test_size) test_size = maximum_test_size; } return test_size; } std::vector const &data() const { return v; } private: std::vector v; boost::mutex m; unsigned int progress; }; template class callable_reference_wrapper : public boost::reference_wrapper { public: explicit callable_reference_wrapper(T& t) : boost::reference_wrapper(t) {} inline void operator()() { this->get().operator()(); } }; template callable_reference_wrapper callable_ref(T &t) { return callable_reference_wrapper(t); } test_task test1; test_task test2; test_task test3; template void check_ascending(test_task const &t) { typedef typename std::vector::const_iterator iter; iter p(t.data().begin()); iter const e(t.data().end()); iter n(p); while (++n!=e) { if ((**n).get_object_id()<=(**p).get_object_id()) { using namespace std; throw std::runtime_error("object ids out of order"); } p = n; } } struct less1 { bool operator()(class1 const *p, class1 const *q) const { return p->get_object_id() < q->get_object_id(); } }; template void check_not_contained_in( test_task const &candidate, test_task const &in ) { typedef typename std::vector::const_iterator iter; iter p(candidate.data().begin()); iter const e(candidate.data().end()); while (p!=e) { iter found = std::lower_bound(in.data().begin(),in.data().end(),*p,less1()); if (found!=in.data().end() && (**found).get_object_id() == (**p).get_object_id()) { using namespace std; throw std::runtime_error("object ids not unqiue"); } ++p; } } void concurrent_creation_of_objects() { { boost::xtime_get(&start_time, boost::TIME_UTC_); boost::thread thread1(callable_ref(test1)); boost::thread thread2(callable_ref(test2)); boost::thread thread3(callable_ref(test3)); thread1.join(); thread2.join(); thread3.join(); } } void local_uniqueness() { BOOST_TEST(test1.data().size()==test_size); BOOST_TEST(test2.data().size()==test_size); BOOST_TEST(test3.data().size()==test_size); } void local_ordering_and_uniqueness() { // now all objects should have unique ids, // the ids must be ascending within each vector // check for ascending ids check_ascending(test1); check_ascending(test2); check_ascending(test3); } void global_uniqueness() { check_not_contained_in(test1,test3); check_not_contained_in(test1,test2); check_not_contained_in(test2,test1); check_not_contained_in(test2,test3); check_not_contained_in(test3,test2); check_not_contained_in(test3,test1); } int main() { concurrent_creation_of_objects(); local_ordering_and_uniqueness(); global_uniqueness(); return boost::report_errors(); } #endif // BOOST_HAS_THREADS