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