1 /*============================================================================= 2 Copyright (c) 2003 Martin Wille 3 http://spirit.sourceforge.net/ 4 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 =============================================================================*/ 9 10 // see http://article.gmane.org/gmane.comp.parsers.spirit.general/4575 11 // or https://sf.net/mailarchive/forum.php?thread_id=2692308&forum_id=1595 12 // for a description of the bug being tested for by this program 13 // 14 // the problem should be solved with version 1.3 of phoenix/closures.hpp> 15 16 #if defined(BOOST_SPIRIT_DEBUG) && defined(__GNUC__) && defined(__WIN32__) 17 // It seems that MinGW has some problems with threads and iostream ? 18 // This code crashes MinGW when BOOST_SPIRIT_DEBUG is defined. The reason 19 // is beyond me. Disable BOOST_SPIRIT_DEBUG for now. 20 #undef BOOST_SPIRIT_DEBUG 21 #endif 22 23 #include <iostream> 24 #include <boost/config.hpp> 25 #include <boost/detail/lightweight_test.hpp> 26 27 #if defined(DONT_HAVE_BOOST) || !defined(BOOST_HAS_THREADS) || defined(BOOST_DISABLE_THREADS) 28 // we end here if we can't do multithreading skipped()29static void skipped() 30 { 31 std::cout << "skipped\n"; 32 } 33 34 int main()35main() 36 { 37 skipped(); 38 return boost::report_errors(); 39 } 40 41 #else 42 // the real MT stuff 43 44 #undef BOOST_SPIRIT_THREADSAFE 45 #define BOOST_SPIRIT_THREADSAFE 46 #undef PHOENIX_THREADSAFE 47 #define PHOENIX_THREADSAFE 48 49 #include <boost/spirit/include/classic_core.hpp> 50 #include <boost/spirit/include/classic_closure.hpp> 51 #include <boost/thread.hpp> 52 53 static const int number_of_calls_to_parse_per_thread=20000; 54 55 struct test_closure 56 : BOOST_SPIRIT_CLASSIC_NS::closure<test_closure, char const*> 57 { 58 member1 b; 59 }; 60 61 struct test_grammar 62 : BOOST_SPIRIT_CLASSIC_NS::grammar<test_grammar, test_closure::context_t> 63 { test_grammartest_grammar64 test_grammar() {} 65 66 template <typename ScannerT> 67 struct definition 68 { definitiontest_grammar::definition69 definition(test_grammar const &self) 70 { 71 using namespace phoenix; 72 rule = BOOST_SPIRIT_CLASSIC_NS::epsilon_p[self.b = arg1]; 73 } 74 starttest_grammar::definition75 BOOST_SPIRIT_CLASSIC_NS::rule<ScannerT> const &start() const { return rule; } 76 77 BOOST_SPIRIT_CLASSIC_NS::rule<ScannerT> rule; 78 }; 79 }; 80 81 test_grammar const g; 82 83 void in_thread(void)84in_thread(void) 85 { 86 char const text[]="foo"; 87 for(int i=0; i<number_of_calls_to_parse_per_thread; ++i) 88 { 89 BOOST_SPIRIT_CLASSIC_NS::parse(&text[0], text+sizeof(text), g); 90 } 91 } 92 93 void bug_000008()94bug_000008() 95 { 96 boost::thread t1(in_thread); 97 boost::thread t2(in_thread); 98 boost::thread t3(in_thread); 99 boost::thread t4(in_thread); 100 101 t1.join(); 102 t2.join(); 103 t3.join(); 104 t4.join(); 105 } 106 107 int main()108main() 109 { 110 bug_000008(); 111 return boost::report_errors(); 112 } 113 114 #endif 115 116