1 //===----------------------------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Copyright (C) 2013 Vicente J. Botet Escriba
12 // Distributed under the Boost Software License, Version 1.0. (See accompanying
13 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15 // <boost/thread/once.hpp>
19 // template<class Callable, class ...Args>
20 // void call_once(once_flag& flag, Callable&& func, Args&&... args);
22 //#define BOOST_THREAD_VERSION 4
23 #define BOOST_THREAD_USES_MOVE
24 #define BOOST_THREAD_PROVIDES_ONCE_CXX11
26 #include <boost/thread/once.hpp>
27 #include <boost/thread/thread.hpp>
28 #include <boost/detail/lightweight_test.hpp>
30 #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
31 #define BOOST_INIT_ONCE_INIT
33 #define BOOST_INIT_ONCE_INIT =BOOST_ONCE_INIT
36 typedef boost::chrono::milliseconds ms
;
38 boost::once_flag flg0 BOOST_INIT_ONCE_INIT
;
44 boost::this_thread::sleep_for(ms(250));
50 boost::call_once(flg0
, init0
);
53 boost::once_flag flg3 BOOST_INIT_ONCE_INIT
;
56 int init3_completed
= 0;
61 boost::this_thread::sleep_for(ms(250));
62 if (init3_called
== 1)
71 boost::call_once(flg3
, init3
);
81 typedef void result_type
;
83 void operator()(int i
) {called
+= i
;}
84 void operator()(int i
) const {called
+= i
;}
87 int init1::called
= 0;
89 boost::once_flag flg1 BOOST_INIT_ONCE_INIT
;
93 boost::call_once(flg1
, init1(), 1);
96 boost::once_flag flg1_member BOOST_INIT_ONCE_INIT
;
101 typedef void result_type
;
106 int init1_member::called
= 0;
112 boost::call_once(flg1_member
, &init1_member::call
, o
, i
);
117 boost::call_once(flg1_member
, &init1_member::call
, o
, 1);
122 typedef void result_type
;
124 void operator()(int i
, int j
) {called
+= i
+ j
;}
125 void operator()(int i
, int j
) const {called
+= i
+ j
;}
128 int init2::called
= 0;
130 boost::once_flag flg2 BOOST_INIT_ONCE_INIT
;
134 boost::call_once(flg2
, init2(), 2, 3);
135 boost::call_once(flg2
, init2(), 4, 5);
138 boost::once_flag flg41 BOOST_INIT_ONCE_INIT
;
139 boost::once_flag flg42 BOOST_INIT_ONCE_INIT
;
141 int init41_called
= 0;
142 int init42_called
= 0;
148 boost::this_thread::sleep_for(ms(250));
154 boost::this_thread::sleep_for(ms(250));
160 boost::call_once(flg41
, init41
);
161 boost::call_once(flg42
, init42
);
166 boost::call_once(flg42
, init42
);
167 boost::call_once(flg41
, init41
);
173 typedef void result_type
;
175 BOOST_THREAD_MOVABLE_ONLY(MoveOnly
)
179 MoveOnly(BOOST_THREAD_RV_REF(MoveOnly
))
182 void operator()(BOOST_THREAD_RV_REF(MoveOnly
))
196 static boost::once_flag flag
;
197 static void do_init(id_string
& )
201 boost::call_once(flag
, &id_string::do_init
, boost::ref(*this));
203 // void operator()(int,int)
205 // // This should fail but works with gcc-4.6.3
206 // //std::bind(&id_string::do_init, *this)();
207 // std::bind(&id_string::do_init, std::ref(*this))();
209 // void operator()(int) const
211 // //std::bind(&id_string::do_init, *this)();
216 boost::once_flag
id_string::flag BOOST_INIT_ONCE_INIT
;
227 // check basic functionality
229 boost::thread
t0(f0
);
230 boost::thread
t1(f0
);
233 BOOST_TEST(init0_called
== 1);
235 // check basic exception safety
237 boost::thread
t0(f3
);
238 boost::thread
t1(f3
);
241 BOOST_TEST(init3_called
== 2);
242 BOOST_TEST(init3_completed
== 1);
244 // check deadlock avoidance
246 boost::thread
t0(f41
);
247 boost::thread
t1(f42
);
250 BOOST_TEST(init41_called
== 1);
251 BOOST_TEST(init42_called
== 1);
253 // check functors with 1 arg
255 boost::thread
t0(f1
);
256 boost::thread
t1(f1
);
259 BOOST_TEST(init1::called
== 1);
261 // check functors with 2 args
263 boost::thread
t0(f2
);
264 boost::thread
t1(f2
);
267 BOOST_TEST(init2::called
== 5);
270 // check member function with 1 arg
272 boost::thread
t0(f1_member_l
);
273 boost::thread
t1(f1_member_r
);
276 BOOST_TEST(init1_member::called
== 1);
278 #if defined BOOST_THREAD_PLATFORM_PTHREAD || (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ > 40600)
280 boost::once_flag f BOOST_INIT_ONCE_INIT
;
281 boost::call_once(f
, MoveOnly());
284 #if defined BOOST_THREAD_PROVIDES_INVOKE
286 boost::once_flag f BOOST_INIT_ONCE_INIT
;
287 boost::call_once(f
, MoveOnly(), 1);
290 boost::once_flag f BOOST_INIT_ONCE_INIT
;
291 boost::call_once(f
, MoveOnly(), MoveOnly());
293 #endif // BOOST_THREAD_PLATFORM_PTHREAD
294 return boost::report_errors();