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 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 throw 1; 52 ++init3_completed; 53 } 54 55 void f3() 56 { 57 try 58 { 59 std::call_once(flg3, init3); 60 } 61 catch (...) 62 { 63 } 64 } 65 66 #ifndef _LIBCPP_HAS_NO_VARIADICS 67 68 struct init1 69 { 70 static int called; 71 72 void operator()(int i) {called += i;} 73 }; 74 75 int init1::called = 0; 76 77 std::once_flag flg1; 78 79 void f1() 80 { 81 std::call_once(flg1, init1(), 1); 82 } 83 84 struct init2 85 { 86 static int called; 87 88 void operator()(int i, int j) const {called += i + j;} 89 }; 90 91 int init2::called = 0; 92 93 std::once_flag flg2; 94 95 void f2() 96 { 97 std::call_once(flg2, init2(), 2, 3); 98 std::call_once(flg2, init2(), 4, 5); 99 } 100 101 #endif // _LIBCPP_HAS_NO_VARIADICS 102 103 std::once_flag flg41; 104 std::once_flag flg42; 105 106 int init41_called = 0; 107 int init42_called = 0; 108 109 void init42(); 110 111 void init41() 112 { 113 std::this_thread::sleep_for(ms(250)); 114 ++init41_called; 115 } 116 117 void init42() 118 { 119 std::this_thread::sleep_for(ms(250)); 120 ++init42_called; 121 } 122 123 void f41() 124 { 125 std::call_once(flg41, init41); 126 std::call_once(flg42, init42); 127 } 128 129 void f42() 130 { 131 std::call_once(flg42, init42); 132 std::call_once(flg41, init41); 133 } 134 135 #ifndef _LIBCPP_HAS_NO_VARIADICS 136 137 class MoveOnly 138 { 139 #if !defined(__clang__) 140 // GCC 4.8 complains about the following being private 141 public: 142 MoveOnly(const MoveOnly&) 143 { 144 } 145 #else 146 MoveOnly(const MoveOnly&); 147 #endif 148 public: 149 MoveOnly() {} 150 MoveOnly(MoveOnly&&) {} 151 152 void operator()(MoveOnly&&) 153 { 154 } 155 }; 156 157 class NonCopyable 158 { 159 #if !defined(__clang__) 160 // GCC 4.8 complains about the following being private 161 public: 162 NonCopyable(const NonCopyable&) 163 { 164 } 165 #else 166 NonCopyable(const NonCopyable&); 167 #endif 168 public: 169 NonCopyable() {} 170 171 void operator()(int&) {} 172 }; 173 174 #if __cplusplus >= 201103L 175 // reference qualifiers on functions are a C++11 extension 176 struct RefQual 177 { 178 int lv_called, rv_called; 179 180 RefQual() : lv_called(0), rv_called(0) {} 181 182 void operator()() & { ++lv_called; } 183 void operator()() && { ++rv_called; } 184 }; 185 #endif 186 #endif 187 188 int main() 189 { 190 // check basic functionality 191 { 192 std::thread t0(f0); 193 std::thread t1(f0); 194 t0.join(); 195 t1.join(); 196 assert(init0_called == 1); 197 } 198 // check basic exception safety 199 { 200 std::thread t0(f3); 201 std::thread t1(f3); 202 t0.join(); 203 t1.join(); 204 assert(init3_called == 2); 205 assert(init3_completed == 1); 206 } 207 // check deadlock avoidance 208 { 209 std::thread t0(f41); 210 std::thread t1(f42); 211 t0.join(); 212 t1.join(); 213 assert(init41_called == 1); 214 assert(init42_called == 1); 215 } 216 #ifndef _LIBCPP_HAS_NO_VARIADICS 217 // check functors with 1 arg 218 { 219 std::thread t0(f1); 220 std::thread t1(f1); 221 t0.join(); 222 t1.join(); 223 assert(init1::called == 1); 224 } 225 // check functors with 2 args 226 { 227 std::thread t0(f2); 228 std::thread t1(f2); 229 t0.join(); 230 t1.join(); 231 assert(init2::called == 5); 232 } 233 { 234 std::once_flag f; 235 std::call_once(f, MoveOnly(), MoveOnly()); 236 } 237 // check LWG2442: call_once() shouldn't DECAY_COPY() 238 { 239 std::once_flag f; 240 int i = 0; 241 std::call_once(f, NonCopyable(), i); 242 } 243 #if __cplusplus >= 201103L 244 // reference qualifiers on functions are a C++11 extension 245 { 246 std::once_flag f1, f2; 247 RefQual rq; 248 std::call_once(f1, rq); 249 assert(rq.lv_called == 1); 250 std::call_once(f2, std::move(rq)); 251 assert(rq.rv_called == 1); 252 } 253 #endif 254 #endif // _LIBCPP_HAS_NO_VARIADICS 255 } 256