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 "test_macros.h" 23 24 typedef std::chrono::milliseconds ms; 25 26 std::once_flag flg0; 27 28 int init0_called = 0; 29 30 void init0() 31 { 32 std::this_thread::sleep_for(ms(250)); 33 ++init0_called; 34 } 35 36 void f0() 37 { 38 std::call_once(flg0, init0); 39 } 40 41 std::once_flag flg3; 42 43 int init3_called = 0; 44 int init3_completed = 0; 45 46 void init3() 47 { 48 ++init3_called; 49 std::this_thread::sleep_for(ms(250)); 50 if (init3_called == 1) 51 TEST_THROW(1); 52 ++init3_completed; 53 } 54 55 void f3() 56 { 57 #ifndef TEST_HAS_NO_EXCEPTIONS 58 try 59 { 60 std::call_once(flg3, init3); 61 } 62 catch (...) 63 { 64 } 65 #endif 66 } 67 68 #if TEST_STD_VER >= 11 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 // TEST_STD_VER >= 11 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 #if TEST_STD_VER >= 11 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 // reference qualifiers on functions are a C++11 extension 177 struct RefQual 178 { 179 int lv_called, rv_called; 180 181 RefQual() : lv_called(0), rv_called(0) {} 182 183 void operator()() & { ++lv_called; } 184 void operator()() && { ++rv_called; } 185 }; 186 187 #endif // TEST_STD_VER >= 11 188 189 int main(int, char**) 190 { 191 // check basic functionality 192 { 193 std::thread t0(f0); 194 std::thread t1(f0); 195 t0.join(); 196 t1.join(); 197 assert(init0_called == 1); 198 } 199 #ifndef TEST_HAS_NO_EXCEPTIONS 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 #endif 210 // check deadlock avoidance 211 { 212 std::thread t0(f41); 213 std::thread t1(f42); 214 t0.join(); 215 t1.join(); 216 assert(init41_called == 1); 217 assert(init42_called == 1); 218 } 219 #if TEST_STD_VER >= 11 220 // check functors with 1 arg 221 { 222 std::thread t0(f1); 223 std::thread t1(f1); 224 t0.join(); 225 t1.join(); 226 assert(init1::called == 1); 227 } 228 // check functors with 2 args 229 { 230 std::thread t0(f2); 231 std::thread t1(f2); 232 t0.join(); 233 t1.join(); 234 assert(init2::called == 5); 235 } 236 { 237 std::once_flag f; 238 std::call_once(f, MoveOnly(), MoveOnly()); 239 } 240 // check LWG2442: call_once() shouldn't DECAY_COPY() 241 { 242 std::once_flag f; 243 int i = 0; 244 std::call_once(f, NonCopyable(), i); 245 } 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 // TEST_STD_VER >= 11 256 257 return 0; 258 } 259