owi_mt_tests.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*=============================================================================
  2. Copyright (c) 2002-2004 Martin Wille
  3. http://spirit.sourceforge.net/
  4. Use, modification and distribution is subject to the Boost Software
  5. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. // std::lower_bound seems to perform awfully slow with _GLIBCXX_DEBUG enabled
  9. #undef _GLIBCXX_DEBUG
  10. #include <iostream>
  11. #include <boost/config.hpp>
  12. #include <boost/detail/lightweight_test.hpp>
  13. #if !defined(BOOST_HAS_THREADS) || defined(DONT_HAVE_BOOST) || defined(BOOST_DISABLE_THREADS)
  14. static void skipped()
  15. {
  16. std::cout << "skipped\n";
  17. }
  18. int
  19. main()
  20. {
  21. skipped();
  22. return 0;
  23. }
  24. #else
  25. ////////////////////////////////////////////////////////////////////////////////
  26. static const unsigned long initial_test_size = 5000UL;
  27. #if defined(_DEBUG) && (BOOST_MSVC >= 1400)
  28. static const unsigned long maximum_test_size = 10000UL;
  29. #else
  30. static const unsigned long maximum_test_size = 1000000UL;
  31. #endif
  32. ////////////////////////////////////////////////////////////////////////////////
  33. #undef BOOST_SPIRIT_THREADSAFE
  34. #define BOOST_SPIRIT_THREADSAFE
  35. #include <boost/thread/thread.hpp>
  36. #include <boost/spirit/home/classic/core/non_terminal/impl/object_with_id.ipp>
  37. #include <boost/ref.hpp>
  38. #include <boost/thread/xtime.hpp>
  39. #include <boost/thread/mutex.hpp>
  40. #include <boost/thread/lock_types.hpp>
  41. #include <vector>
  42. #include <algorithm>
  43. #include <boost/detail/lightweight_test.hpp>
  44. using BOOST_SPIRIT_CLASSIC_NS::impl::object_with_id;
  45. struct tag1 {};
  46. typedef object_with_id<tag1> class1;
  47. unsigned long test_size = initial_test_size;
  48. boost::xtime start_time;
  49. template <typename ClassT>
  50. struct test_task
  51. {
  52. test_task() : v(), m(), progress(0) {}
  53. void operator ()()
  54. { // create lots of objects
  55. unsigned long i = 0;
  56. v.reserve(maximum_test_size);
  57. do
  58. {
  59. for (; i<test_size; ++i)
  60. v.push_back(new ClassT);
  61. }
  62. while ( i < increase_test_size(i) );
  63. }
  64. static unsigned long
  65. increase_test_size(unsigned long size)
  66. {
  67. static boost::mutex m;
  68. boost::unique_lock<boost::mutex> l(m);
  69. if (size<test_size || test_size == maximum_test_size)
  70. return test_size;
  71. boost::xtime now;
  72. boost::xtime_get(&now, boost::TIME_UTC_);
  73. boost::xtime::xtime_sec_t seconds = now.sec - start_time.sec;
  74. if (seconds < 4)
  75. {
  76. test_size *= 2;
  77. if (test_size > maximum_test_size)
  78. test_size = maximum_test_size;
  79. }
  80. return test_size;
  81. }
  82. std::vector<ClassT*> const &data() const
  83. {
  84. return v;
  85. }
  86. private:
  87. std::vector<ClassT*> v;
  88. boost::mutex m;
  89. unsigned int progress;
  90. };
  91. template <typename T>
  92. class callable_reference_wrapper
  93. : public boost::reference_wrapper<T>
  94. {
  95. public:
  96. explicit callable_reference_wrapper(T& t)
  97. : boost::reference_wrapper<T>(t)
  98. {}
  99. inline void operator()() { this->get().operator()(); }
  100. };
  101. template <typename T>
  102. callable_reference_wrapper<T>
  103. callable_ref(T &t)
  104. {
  105. return callable_reference_wrapper<T>(t);
  106. }
  107. test_task<class1> test1;
  108. test_task<class1> test2;
  109. test_task<class1> test3;
  110. template <typename ClassT>
  111. void
  112. check_ascending(test_task<ClassT> const &t)
  113. {
  114. typedef typename std::vector<ClassT*>::const_iterator iter;
  115. iter p(t.data().begin());
  116. iter const e(t.data().end());
  117. iter n(p);
  118. while (++n!=e)
  119. {
  120. if ((**n).get_object_id()<=(**p).get_object_id())
  121. {
  122. using namespace std;
  123. throw std::runtime_error("object ids out of order");
  124. }
  125. p = n;
  126. }
  127. }
  128. struct less1
  129. {
  130. bool operator()(class1 const *p, class1 const *q) const
  131. {
  132. return p->get_object_id() < q->get_object_id();
  133. }
  134. };
  135. template <typename ClassT>
  136. void
  137. check_not_contained_in(
  138. test_task<ClassT> const &candidate,
  139. test_task<ClassT> const &in
  140. )
  141. {
  142. typedef typename std::vector<ClassT*>::const_iterator iter;
  143. iter p(candidate.data().begin());
  144. iter const e(candidate.data().end());
  145. while (p!=e)
  146. {
  147. iter found = std::lower_bound(in.data().begin(),in.data().end(),*p,less1());
  148. if (found!=in.data().end() &&
  149. (**found).get_object_id() == (**p).get_object_id())
  150. {
  151. using namespace std;
  152. throw std::runtime_error("object ids not unqiue");
  153. }
  154. ++p;
  155. }
  156. }
  157. void concurrent_creation_of_objects()
  158. {
  159. {
  160. boost::xtime_get(&start_time, boost::TIME_UTC_);
  161. boost::thread thread1(callable_ref(test1));
  162. boost::thread thread2(callable_ref(test2));
  163. boost::thread thread3(callable_ref(test3));
  164. thread1.join();
  165. thread2.join();
  166. thread3.join();
  167. }
  168. }
  169. void local_uniqueness()
  170. {
  171. BOOST_TEST(test1.data().size()==test_size);
  172. BOOST_TEST(test2.data().size()==test_size);
  173. BOOST_TEST(test3.data().size()==test_size);
  174. }
  175. void local_ordering_and_uniqueness()
  176. {
  177. // now all objects should have unique ids,
  178. // the ids must be ascending within each vector
  179. // check for ascending ids
  180. check_ascending(test1);
  181. check_ascending(test2);
  182. check_ascending(test3);
  183. }
  184. void global_uniqueness()
  185. {
  186. check_not_contained_in(test1,test3);
  187. check_not_contained_in(test1,test2);
  188. check_not_contained_in(test2,test1);
  189. check_not_contained_in(test2,test3);
  190. check_not_contained_in(test3,test2);
  191. check_not_contained_in(test3,test1);
  192. }
  193. int
  194. main()
  195. {
  196. concurrent_creation_of_objects();
  197. local_ordering_and_uniqueness();
  198. global_uniqueness();
  199. return boost::report_errors();
  200. }
  201. #endif // BOOST_HAS_THREADS