1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // XFAIL: libcpp-no-exceptions 11 // UNSUPPORTED: libcpp-has-no-threads 12 13 // <mutex> 14 15 // struct once_flag; 16 17 // template<class Callable, class ...Args> 18 // void call_once(once_flag& flag, Callable&& func, Args&&... args); 19 20 #include <mutex> 21 #include <thread> 22 #include <cassert> 23 24 #include "test_macros.h" 25 26 typedef std::chrono::milliseconds ms; 27 28 std::once_flag flg0; 29 30 int init0_called = 0; 31 32 void init0() 33 { 34 std::this_thread::sleep_for(ms(250)); 35 ++init0_called; 36 } 37 38 void f0() 39 { 40 std::call_once(flg0, init0); 41 } 42 43 std::once_flag flg3; 44 45 int init3_called = 0; 46 int init3_completed = 0; 47 48 void init3() 49 { 50 ++init3_called; 51 std::this_thread::sleep_for(ms(250)); 52 if (init3_called == 1) 53 throw 1; 54 ++init3_completed; 55 } 56 57 void f3() 58 { 59 try 60 { 61 std::call_once(flg3, init3); 62 } 63 catch (...) 64 { 65 } 66 } 67 68 #ifndef _LIBCPP_HAS_NO_VARIADICS 69 70 struct init1 71 { 72 static int called; 73 74 void operator()(int i) {called += i;} 75 }; 76 77 int init1::called = 0; 78 79 std::once_flag flg1; 80 81 void f1() 82 { 83 std::call_once(flg1, init1(), 1); 84 } 85 86 struct init2 87 { 88 static int called; 89 90 void operator()(int i, int j) const {called += i + j;} 91 }; 92 93 int init2::called = 0; 94 95 std::once_flag flg2; 96 97 void f2() 98 { 99 std::call_once(flg2, init2(), 2, 3); 100 std::call_once(flg2, init2(), 4, 5); 101 } 102 103 #endif // _LIBCPP_HAS_NO_VARIADICS 104 105 std::once_flag flg41; 106 std::once_flag flg42; 107 108 int init41_called = 0; 109 int init42_called = 0; 110 111 void init42(); 112 113 void init41() 114 { 115 std::this_thread::sleep_for(ms(250)); 116 ++init41_called; 117 } 118 119 void init42() 120 { 121 std::this_thread::sleep_for(ms(250)); 122 ++init42_called; 123 } 124 125 void f41() 126 { 127 std::call_once(flg41, init41); 128 std::call_once(flg42, init42); 129 } 130 131 void f42() 132 { 133 std::call_once(flg42, init42); 134 std::call_once(flg41, init41); 135 } 136 137 #ifndef _LIBCPP_HAS_NO_VARIADICS 138 139 class MoveOnly 140 { 141 #if !defined(__clang__) 142 // GCC 4.8 complains about the following being private 143 public: 144 MoveOnly(const MoveOnly&) 145 { 146 } 147 #else 148 MoveOnly(const MoveOnly&); 149 #endif 150 public: 151 MoveOnly() {} 152 MoveOnly(MoveOnly&&) {} 153 154 void operator()(MoveOnly&&) 155 { 156 } 157 }; 158 159 class NonCopyable 160 { 161 #if !defined(__clang__) 162 // GCC 4.8 complains about the following being private 163 public: 164 NonCopyable(const NonCopyable&) 165 { 166 } 167 #else 168 NonCopyable(const NonCopyable&); 169 #endif 170 public: 171 NonCopyable() {} 172 173 void operator()(int&) {} 174 }; 175 176 #if TEST_STD_VER >= 11 177 // reference qualifiers on functions are a C++11 extension 178 struct RefQual 179 { 180 int lv_called, rv_called; 181 182 RefQual() : lv_called(0), rv_called(0) {} 183 184 void operator()() & { ++lv_called; } 185 void operator()() && { ++rv_called; } 186 }; 187 #endif 188 #endif 189 190 int main() 191 { 192 // check basic functionality 193 { 194 std::thread t0(f0); 195 std::thread t1(f0); 196 t0.join(); 197 t1.join(); 198 assert(init0_called == 1); 199 } 200 // check basic exception safety 201 { 202 std::thread t0(f3); 203 std::thread t1(f3); 204 t0.join(); 205 t1.join(); 206 assert(init3_called == 2); 207 assert(init3_completed == 1); 208 } 209 // check deadlock avoidance 210 { 211 std::thread t0(f41); 212 std::thread t1(f42); 213 t0.join(); 214 t1.join(); 215 assert(init41_called == 1); 216 assert(init42_called == 1); 217 } 218 #ifndef _LIBCPP_HAS_NO_VARIADICS 219 // check functors with 1 arg 220 { 221 std::thread t0(f1); 222 std::thread t1(f1); 223 t0.join(); 224 t1.join(); 225 assert(init1::called == 1); 226 } 227 // check functors with 2 args 228 { 229 std::thread t0(f2); 230 std::thread t1(f2); 231 t0.join(); 232 t1.join(); 233 assert(init2::called == 5); 234 } 235 { 236 std::once_flag f; 237 std::call_once(f, MoveOnly(), MoveOnly()); 238 } 239 // check LWG2442: call_once() shouldn't DECAY_COPY() 240 { 241 std::once_flag f; 242 int i = 0; 243 std::call_once(f, NonCopyable(), i); 244 } 245 #if TEST_STD_VER >= 11 246 // reference qualifiers on functions are a C++11 extension 247 { 248 std::once_flag f1, f2; 249 RefQual rq; 250 std::call_once(f1, rq); 251 assert(rq.lv_called == 1); 252 std::call_once(f2, std::move(rq)); 253 assert(rq.rv_called == 1); 254 } 255 #endif 256 #endif // _LIBCPP_HAS_NO_VARIADICS 257 } 258