// vim:ts=4:sw=4:et #include <iostream> #if defined(HAVE_BOOST) #include <boost/thread/thread.hpp> #endif #if !defined(BOOST_HAS_THREADS) int main() { std::cout << "/////////////////////////////////////////////////////////\n"; std::cout << "\n"; std::cout << " object_with_id test (MT)\n"; std::cout << "\n"; std::cout << "/////////////////////////////////////////////////////////\n"; std::cout << "\n"; std::cout << "Test skipped\n"; return 0; }; #else #undef SPIRIT_THREADSAFE #define SPIRIT_THREADSAFE #include <boost/spirit/core/impl/object_with_id.ipp> #include <vector> #include <algorithm> #include <cassert> #include <cstdlib> using spirit::impl::object_with_id; struct tag1 {}; typedef object_with_id<tag1> class1; struct thread_test { static unsigned int size() { return 1000000; } void run() { // create lots of objects v1.reserve(size()); for (unsigned long i=0; i<size(); ++i) { //boost::thread().yield(); v1.push_back(new class1); } } std::vector<class1*> v1; }; struct test_wrapper { test_wrapper(thread_test &t) : test(&t) {} test_wrapper(test_wrapper const &other) : test(other.test) {} ~test_wrapper() {} void operator()() const { test->run(); } private: thread_test *test; }; void check_ascending(thread_test const &t) { typedef std::vector<class1*>::const_iterator iter; iter p(t.v1.begin()); iter const e(t.v1.end()); iter n(p); while (++n!=e) { if ((**n).get_object_id()<=(**p).get_object_id()) { using namespace std; cerr << "object ids out of order"; exit(EXIT_FAILURE); } p = n; } }; struct less1 { bool operator()(class1 const *p, class1 const *q) const { return p->get_object_id() < q->get_object_id(); } }; void check_not_contained_in( thread_test const &candidate, thread_test const &in ) { typedef std::vector<class1*>::const_iterator iter; iter p(candidate.v1.begin()); iter const e(candidate.v1.end()); while (p!=e) { iter found = std::lower_bound(in.v1.begin(),in.v1.end(),*p,less1()); if (found!=in.v1.end() && (**found).get_object_id() == (**p).get_object_id()) { using namespace std; cerr << "object ids not unique"; exit(EXIT_FAILURE); } ++p; } }; int main() { std::cout << "/////////////////////////////////////////////////////////\n"; std::cout << "\n"; std::cout << " object_with_id test (MT)\n"; std::cout << "\n"; std::cout << "/////////////////////////////////////////////////////////\n"; std::cout << "\n"; thread_test test1; test_wrapper tw1(test1); thread_test test2; test_wrapper tw2(test2); thread_test test3; test_wrapper tw3(test3); boost::thread thread1(tw1); boost::thread thread2(tw2); boost::thread thread3(tw3); std::cout << "preparing ..." << std::flush; thread1.join(); thread2.join(); thread3.join(); // now all objects should have unique ids, // the ids must be ascending within each vector std::cout << "checking \n"; assert(test1.v1.size()==thread_test::size()); assert(test2.v1.size()==thread_test::size()); assert(test3.v1.size()==thread_test::size()); // check for ascending ids check_ascending(test1); check_ascending(test2); check_ascending(test3); // check for 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); std::cout << "Test concluded successfully\n"; } #endif