• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()29 static void skipped()
30 {
31     std::cout << "skipped\n";
32 }
33 
34 int
main()35 main()
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)84 in_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()94 bug_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()108 main()
109 {
110     bug_000008();
111     return boost::report_errors();
112 }
113 
114 #endif
115 
116