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;
108
//#if defined BOOST_THREAD_PLATFORM_PTHREAD
112
//#if defined BOOST_THREAD_PROVIDES_ONCE_CXX11
113
boost::call_once(flg1_member, &init1_member::call, o, 1);
115
// boost::call_once(flg1_member, boost::bind(&init1_member::call, boost::ref(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);
273
boost::thread t1(f1_member);
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();