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 // UNSUPPORTED: libcpp-has-no-threads 11 12 // <mutex> 13 14 // struct once_flag; 15 16 // template<class Callable, class ...Args> 17 // void call_once(once_flag& flag, Callable&& func, Args&&... args); 18 19 #include <mutex> 20 #include <thread> 21 #include <cassert> 22 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 #ifndef _LIBCPP_HAS_NO_VARIADICS 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 // _LIBCPP_HAS_NO_VARIADICS 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 #ifndef _LIBCPP_HAS_NO_VARIADICS 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 #if TEST_STD_VER >= 11 178 // reference qualifiers on functions are a C++11 extension 179 struct RefQual 180 { 181 int lv_called, rv_called; 182 183 RefQual() : lv_called(0), rv_called(0) {} 184 185 void operator()() & { ++lv_called; } 186 void operator()() && { ++rv_called; } 187 }; 188 #endif 189 #endif 190 191 int main() 192 { 193 // check basic functionality 194 { 195 std::thread t0(f0); 196 std::thread t1(f0); 197 t0.join(); 198 t1.join(); 199 assert(init0_called == 1); 200 } 201 #ifndef TEST_HAS_NO_EXCEPTIONS 202 // check basic exception safety 203 { 204 std::thread t0(f3); 205 std::thread t1(f3); 206 t0.join(); 207 t1.join(); 208 assert(init3_called == 2); 209 assert(init3_completed == 1); 210 } 211 #endif 212 // check deadlock avoidance 213 { 214 std::thread t0(f41); 215 std::thread t1(f42); 216 t0.join(); 217 t1.join(); 218 assert(init41_called == 1); 219 assert(init42_called == 1); 220 } 221 #ifndef _LIBCPP_HAS_NO_VARIADICS 222 // check functors with 1 arg 223 { 224 std::thread t0(f1); 225 std::thread t1(f1); 226 t0.join(); 227 t1.join(); 228 assert(init1::called == 1); 229 } 230 // check functors with 2 args 231 { 232 std::thread t0(f2); 233 std::thread t1(f2); 234 t0.join(); 235 t1.join(); 236 assert(init2::called == 5); 237 } 238 { 239 std::once_flag f; 240 std::call_once(f, MoveOnly(), MoveOnly()); 241 } 242 // check LWG2442: call_once() shouldn't DECAY_COPY() 243 { 244 std::once_flag f; 245 int i = 0; 246 std::call_once(f, NonCopyable(), i); 247 } 248 #if TEST_STD_VER >= 11 249 // reference qualifiers on functions are a C++11 extension 250 { 251 std::once_flag f1, f2; 252 RefQual rq; 253 std::call_once(f1, rq); 254 assert(rq.lv_called == 1); 255 std::call_once(f2, std::move(rq)); 256 assert(rq.rv_called == 1); 257 } 258 #endif 259 #endif // _LIBCPP_HAS_NO_VARIADICS 260 } 261