1 // (C) Copyright 2006-7 Anthony Williams
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
6 #define BOOST_THREAD_VERSION 2
7 #define BOOST_THREAD_PROVIDES_INTERRUPTIONS
8 #define BOOST_TEST_MODULE Boost.Threads: once test suite
10 #include <boost/test/unit_test.hpp>
11 #include <boost/thread/thread.hpp>
12 #include <boost/thread/mutex.hpp>
13 #include <boost/thread/once.hpp>
16 #include <boost/thread/detail/log.hpp>
18 boost::once_flag flag
=BOOST_ONCE_INIT
;
22 void initialize_variable()
24 // ensure that if multiple threads get in here, they are serialized, so we can see the effect
25 boost::unique_lock
<boost::mutex
> lock(m
);
30 void call_once_thread()
32 unsigned const loop_count
=100;
34 for(unsigned i
=0;i
<loop_count
;++i
)
36 boost::call_once(flag
, initialize_variable
);
37 my_once_value
=var_to_init
;
43 boost::unique_lock
<boost::mutex
> lock(m
);
44 BOOST_CHECK_EQUAL(my_once_value
, 1);
47 BOOST_AUTO_TEST_CASE(test_call_once
)
49 BOOST_DETAIL_THREAD_LOG
;
51 unsigned const num_threads
=20;
52 boost::thread_group group
;
56 for(unsigned i
=0;i
<num_threads
;++i
)
58 group
.create_thread(&call_once_thread
);
64 group
.interrupt_all();
69 BOOST_CHECK_EQUAL(var_to_init
,1);
72 int var_to_init_with_functor
=0;
74 struct increment_value
77 explicit increment_value(int* value_
):
81 void operator()() const
83 boost::unique_lock
<boost::mutex
> lock(m
);
88 void call_once_with_functor()
90 unsigned const loop_count
=100;
92 static boost::once_flag functor_flag
=BOOST_ONCE_INIT
;
93 for(unsigned i
=0;i
<loop_count
;++i
)
95 boost::call_once(functor_flag
, increment_value(&var_to_init_with_functor
));
96 my_once_value
=var_to_init_with_functor
;
102 boost::unique_lock
<boost::mutex
> lock(m
);
103 BOOST_CHECK_EQUAL(my_once_value
, 1);
106 BOOST_AUTO_TEST_CASE(test_call_once_arbitrary_functor
)
108 BOOST_DETAIL_THREAD_LOG
;
110 unsigned const num_threads
=20;
111 boost::thread_group group
;
115 for(unsigned i
=0;i
<num_threads
;++i
)
117 group
.create_thread(&call_once_with_functor
);
123 group
.interrupt_all();
128 BOOST_CHECK_EQUAL(var_to_init_with_functor
,1);
132 struct throw_before_third_pass
137 static unsigned pass_counter
;
139 void operator()() const
141 boost::unique_lock
<boost::mutex
> lock(m
);
145 throw my_exception();
150 unsigned throw_before_third_pass::pass_counter
=0;
151 unsigned exception_counter
=0;
153 void call_once_with_exception()
155 static boost::once_flag functor_flag
=BOOST_ONCE_INIT
;
158 boost::call_once(functor_flag
, throw_before_third_pass());
160 catch(throw_before_third_pass::my_exception
)
162 boost::unique_lock
<boost::mutex
> lock(m
);
167 BOOST_AUTO_TEST_CASE(test_call_once_retried_on_exception
)
169 BOOST_DETAIL_THREAD_LOG
;
170 unsigned const num_threads
=20;
171 boost::thread_group group
;
175 for(unsigned i
=0;i
<num_threads
;++i
)
177 group
.create_thread(&call_once_with_exception
);
183 group
.interrupt_all();
188 BOOST_CHECK_EQUAL(throw_before_third_pass::pass_counter
,3u);
189 BOOST_CHECK_EQUAL(exception_counter
,2u);