1 /*=============================================================================
2     Copyright (c) 2003 Martin Wille
3     Copyright (c) 2001-2007 Joel de Guzman
4     Copyright (c) 2015 John Fletcher
5 
6     Distributed under the Boost Software License, Version 1.0. (See accompanying
7     file LICENSE_1_0.txt or copy at 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   // This code is borrowed from Spirit's bug_000008.cpp test for multithreads.
15   // Now modified to point to the Phoenix headers
16   // instead of the ones in Spirit.
17 #include <iostream>
18 #include <boost/config.hpp>
19 #include <boost/assert.hpp>
20 #include <boost/detail/lightweight_test.hpp>
21  // Testing problems in thread/future
22 //#include <boost/move/move.hpp>
23 //#include <boost/move/detail/type_traits.hpp>
24 //using boost::move_detail::is_copy_constructible;
25 #include <boost/phoenix/scope/dynamic.hpp>
26 
27 #if defined(DONT_HAVE_BOOST)                        \
28     || !defined(BOOST_HAS_THREADS)                  \
29     || defined(BOOST_DISABLE_THREADS)               \
30     || (defined(__GNUC__) && defined(__WIN32__))    // MinGW
31 #define SKIP_TEST
32 #endif
33 
34 
35 #if defined(SKIP_TEST)
36 // we end here if we can't do multithreading
skipped()37 static void skipped()
38 {
39     std::cout << "skipped\n";
40 }
41 
42 int
main()43 main()
44 {
45     skipped();
46     return boost::report_errors();
47 }
48 
49 #else
50 // the real MT stuff
51 
52 #include <boost/phoenix/operator.hpp>
53 #include <boost/phoenix/scope.hpp>
54 #include <boost/thread.hpp>
55 
56 static const int number_of_calls_per_thread=20000;
57 
58 struct test_dynamic : boost::phoenix::dynamic<int>
59 {
60   //    test_dynamic() : b(*this) {}
test_dynamictest_dynamic61   test_dynamic() : b(init<0>(this)) {}
62     member1 b;
63 };
64 
65 void
in_thread(void)66 in_thread(void)
67 {
68     test_dynamic s; // should now be a local
69 
70     for (int i = 0; i < number_of_calls_per_thread; ++i)
71     {
72         boost::phoenix::dynamic_frame<test_dynamic::self_type> frame(s);
73         (s.b = 123)();
74         {
75             boost::phoenix::dynamic_frame<test_dynamic::self_type> frame(s);
76             (s.b = 456)();
77             BOOST_ASSERT((s.b == 456)());
78         }
79         BOOST_ASSERT((s.b == 123)());
80     }
81 }
82 
83 void
bug_000008()84 bug_000008()
85 {
86     boost::thread t1(in_thread);
87     boost::thread t2(in_thread);
88     boost::thread t3(in_thread);
89     boost::thread t4(in_thread);
90 
91     t1.join();
92     t2.join();
93     t3.join();
94     t4.join();
95 }
96 
97 int
main()98 main()
99 {
100     bug_000008();
101     return boost::report_errors();
102 }
103 
104 #endif
105 
106