Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/spirit/test/grammar_mt_tests.cpp @ 33

Last change on this file since 33 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 7.4 KB
Line 
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#include <iostream>
10#include <boost/config.hpp>
11#include <boost/detail/lightweight_test.hpp>
12
13#if defined(DONT_HAVE_BOOST) || !defined(BOOST_HAS_THREADS) || defined(BOOST_DISABLE_THREADS)
14// we end here if we can't do multithreading
15static void skipped()
16{
17    std::cout << "skipped\n";
18}
19
20int
21main()
22{
23    skipped();
24    return 0;
25}
26
27#else
28// the real MT stuff
29
30#undef BOOST_SPIRIT_THREADSAFE
31#define BOOST_SPIRIT_THREADSAFE
32
33#include <boost/thread/thread.hpp>
34#include <boost/spirit/core/non_terminal/grammar.hpp>
35#include <boost/spirit/core/non_terminal/rule.hpp>
36#include <boost/spirit/core/composite/epsilon.hpp>
37#include <boost/thread/xtime.hpp>
38#include <boost/ref.hpp>
39
40static boost::mutex simple_mutex;
41static int simple_definition_count = 0;
42
43struct simple : public boost::spirit::grammar<simple>
44{
45    template <typename ScannerT>
46    struct definition
47    {
48        definition(simple const& /*self*/)
49        {
50            top = boost::spirit::epsilon_p;
51            boost::mutex::scoped_lock lock(simple_mutex);
52            simple_definition_count++;
53        }
54
55        boost::spirit::rule<ScannerT> top;
56        boost::spirit::rule<ScannerT> const &start() const { return top; }
57    };
58};
59
60struct count_guard
61{
62    count_guard(int &c) : counter(c) {}
63    ~count_guard() { counter = 0; }
64private:
65    int &counter;
66};
67
68static void
69milli_sleep(unsigned long milliseconds)
70{
71    static long const nanoseconds_per_second = 1000L*1000L*1000L;
72    boost::xtime xt;
73    boost::xtime_get(&xt, boost::TIME_UTC);
74    xt.nsec+=1000*1000*milliseconds;
75    while (xt.nsec > nanoseconds_per_second)
76    {
77        xt.nsec -= nanoseconds_per_second;
78        xt.sec++;
79    }
80       
81    boost::thread::sleep(xt);
82}
83
84static void
85nap()
86{
87    // this function is called by various threads to ensure
88    // that thread lifetime actually overlap
89    milli_sleep(300);
90}
91
92template <typename GrammarT>
93static void
94make_definition(GrammarT &g)
95{
96    char const *text="blah";
97    boost::spirit::scanner<> s(text, text+4);
98
99    g.parse(s);
100}
101
102template <typename GrammarT>
103static void
104make_definition3(GrammarT &g)
105{
106    char const *text="blah";
107    boost::spirit::scanner<> s(text, text+4);
108
109    g.parse(s);
110    nap();
111    g.parse(s);
112    g.parse(s);
113}
114////////////////////////////////////////////////////////////////////////////////
115#define exactly_one_instance_created simple_definition_count == 1
116#define exactly_two_instances_created simple_definition_count == 2
117#define exactly_four_instances_created simple_definition_count == 4
118#define exactly_eight_instances_created simple_definition_count == 8
119
120////////////////////////////////////////////////////////////////////////////////
121static void
122multiple_attempts_to_instantiate_a_definition_from_a_single_thread()
123{
124    // checks wether exactly one definition per grammar
125    // object is created
126
127    count_guard guard(simple_definition_count);
128
129    simple simple1_p;
130    simple simple2_p;
131
132    make_definition(simple1_p);
133    make_definition(simple1_p);
134    make_definition(simple1_p);
135
136    BOOST_TEST(exactly_one_instance_created);
137
138    make_definition(simple2_p);
139    make_definition(simple2_p);
140    make_definition(simple2_p);
141
142    BOOST_TEST(exactly_two_instances_created);
143}
144
145////////////////////////////////////////////////////////////////////////////////
146struct single_grammar_object_task
147{
148    void operator()() const
149    {
150        make_definition3(simple1_p);
151    };
152
153    simple simple1_p;
154};
155
156static void
157single_local_grammar_object_multiple_threads()
158{
159    // check wether independent definition objects are
160    // created
161    count_guard guard(simple_definition_count);
162    single_grammar_object_task task1, task2, task3, task4;
163
164    boost::thread t1(boost::ref(task1));
165    boost::thread t2(boost::ref(task2));
166    boost::thread t3(boost::ref(task3));
167    boost::thread t4(boost::ref(task4));
168
169    t1.join();
170    t2.join();
171    t3.join();
172    t4.join();
173
174    BOOST_TEST(exactly_four_instances_created);
175}
176
177////////////////////////////////////////////////////////////////////////////////
178struct two_grammar_objects_task
179{
180    void operator()() const
181    {
182        make_definition3(simple1_p);
183        make_definition3(simple2_p);
184    };
185
186    simple simple1_p;
187    simple simple2_p;
188};
189
190static void
191multiple_local_grammar_objects_multiple_threads()
192{
193    // check wether exactly one definition per thread
194    // and per grammar object is created
195    count_guard guard(simple_definition_count);
196    two_grammar_objects_task task1, task2, task3, task4;
197
198    boost::thread t1(boost::ref(task1));
199    boost::thread t2(boost::ref(task2));
200    boost::thread t3(boost::ref(task3));
201    boost::thread t4(boost::ref(task4));
202
203    t1.join();
204    t2.join();
205    t3.join();
206    t4.join();
207
208    BOOST_TEST(exactly_eight_instances_created);
209}
210
211////////////////////////////////////////////////////////////////////////////////
212static simple global_simple1_p;
213
214struct single_global_grammar_object_task
215{
216    void operator()() const
217    {
218        make_definition3(global_simple1_p);
219    };
220};
221
222static void
223single_global_grammar_object_multiple_threads()
224{
225    // check wether exactly one definition per thread is
226    // created
227    count_guard guard(simple_definition_count);
228    single_global_grammar_object_task task1, task2, task3, task4;
229
230    boost::thread t1(boost::ref(task1));
231    boost::thread t2(boost::ref(task2));
232    boost::thread t3(boost::ref(task3));
233    boost::thread t4(boost::ref(task4));
234
235    t1.join();
236    t2.join();
237    t3.join();
238    t4.join();
239
240    BOOST_TEST(exactly_four_instances_created);
241}
242
243////////////////////////////////////////////////////////////////////////////////
244static simple global_simple2_p;
245static simple global_simple3_p;
246
247struct multiple_global_grammar_objects_task
248{
249    void operator()() const
250    {
251        make_definition3(global_simple2_p);
252        make_definition3(global_simple3_p);
253    };
254};
255
256static void
257multiple_global_grammar_objects_multiple_threads()
258{
259    // check wether exactly one definition per thread
260    // and per grammar object is created
261    count_guard guard(simple_definition_count);
262    multiple_global_grammar_objects_task task1, task2, task3, task4;
263
264    boost::thread t1(boost::ref(task1));
265    boost::thread t2(boost::ref(task2));
266    boost::thread t3(boost::ref(task3));
267    boost::thread t4(boost::ref(task4));
268
269    t1.join();
270    t2.join();
271    t3.join();
272    t4.join();
273
274    BOOST_TEST(exactly_eight_instances_created);
275}
276////////////////////////////////////////////////////////////////////////////////
277int
278main()
279{
280    multiple_attempts_to_instantiate_a_definition_from_a_single_thread();
281    single_local_grammar_object_multiple_threads();
282    multiple_local_grammar_objects_multiple_threads();
283    single_global_grammar_object_multiple_threads();
284    multiple_global_grammar_objects_multiple_threads();
285
286    return boost::report_errors();
287}
288
289////////////////////////////////////////////////////////////////////////////////
290
291static boost::spirit::parse_info<char const *> pi;
292
293////////////////////////////////////////////////
294// These macros are used with BOOST_TEST
295
296
297
298#endif // MT mode
Note: See TracBrowser for help on using the repository browser.