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 typedef std::chrono::milliseconds ms; 24 25 std::once_flag flg0; 26 27 int init0_called = 0; 28 29 void init0() 30 { 31 std::this_thread::sleep_for(ms(250)); 32 ++init0_called; 33 } 34 35 void f0() 36 { 37 std::call_once(flg0, init0); 38 } 39 40 std::once_flag flg3; 41 42 int init3_called = 0; 43 int init3_completed = 0; 44 45 void init3() 46 { 47 ++init3_called; 48 std::this_thread::sleep_for(ms(250)); 49 if (init3_called == 1) 50 throw 1; 51 ++init3_completed; 52 } 53 54 void f3() 55 { 56 try 57 { 58 std::call_once(flg3, init3); 59 } 60 catch (...) 61 { 62 } 63 } 64 65 #ifndef _LIBCPP_HAS_NO_VARIADICS 66 67 struct init1 68 { 69 static int called; 70 71 void operator()(int i) {called += i;} 72 }; 73 74 int init1::called = 0; 75 76 std::once_flag flg1; 77 78 void f1() 79 { 80 std::call_once(flg1, init1(), 1); 81 } 82 83 struct init2 84 { 85 static int called; 86 87 void operator()(int i, int j) const {called += i + j;} 88 }; 89 90 int init2::called = 0; 91 92 std::once_flag flg2; 93 94 void f2() 95 { 96 std::call_once(flg2, init2(), 2, 3); 97 std::call_once(flg2, init2(), 4, 5); 98 } 99 100 #endif // _LIBCPP_HAS_NO_VARIADICS 101 102 std::once_flag flg41; 103 std::once_flag flg42; 104 105 int init41_called = 0; 106 int init42_called = 0; 107 108 void init42(); 109 110 void init41() 111 { 112 std::this_thread::sleep_for(ms(250)); 113 ++init41_called; 114 } 115 116 void init42() 117 { 118 std::this_thread::sleep_for(ms(250)); 119 ++init42_called; 120 } 121 122 void f41() 123 { 124 std::call_once(flg41, init41); 125 std::call_once(flg42, init42); 126 } 127 128 void f42() 129 { 130 std::call_once(flg42, init42); 131 std::call_once(flg41, init41); 132 } 133 134 #ifndef _LIBCPP_HAS_NO_VARIADICS 135 136 class MoveOnly 137 { 138 #if !defined(__clang__) 139 // GCC 4.8 complains about the following being private 140 public: 141 MoveOnly(const MoveOnly&) 142 { 143 } 144 #else 145 MoveOnly(const MoveOnly&); 146 #endif 147 public: 148 MoveOnly() {} 149 MoveOnly(MoveOnly&&) {} 150 151 void operator()(MoveOnly&&) 152 { 153 } 154 }; 155 156 #endif 157 158 int main() 159 { 160 // check basic functionality 161 { 162 std::thread t0(f0); 163 std::thread t1(f0); 164 t0.join(); 165 t1.join(); 166 assert(init0_called == 1); 167 } 168 // check basic exception safety 169 { 170 std::thread t0(f3); 171 std::thread t1(f3); 172 t0.join(); 173 t1.join(); 174 assert(init3_called == 2); 175 assert(init3_completed == 1); 176 } 177 // check deadlock avoidance 178 { 179 std::thread t0(f41); 180 std::thread t1(f42); 181 t0.join(); 182 t1.join(); 183 assert(init41_called == 1); 184 assert(init42_called == 1); 185 } 186 #ifndef _LIBCPP_HAS_NO_VARIADICS 187 // check functors with 1 arg 188 { 189 std::thread t0(f1); 190 std::thread t1(f1); 191 t0.join(); 192 t1.join(); 193 assert(init1::called == 1); 194 } 195 // check functors with 2 args 196 { 197 std::thread t0(f2); 198 std::thread t1(f2); 199 t0.join(); 200 t1.join(); 201 assert(init2::called == 5); 202 } 203 { 204 std::once_flag f; 205 std::call_once(f, MoveOnly(), MoveOnly()); 206 } 207 #endif // _LIBCPP_HAS_NO_VARIADICS 208 } 209