libcxx

libcxx mirror with random patches
git clone https://git.neptards.moe/neptards/libcxx.git
Log | Files | Refs

call_once.pass.cpp (4564B)


      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 #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()
    191 {
    192     // check basic functionality
    193     {
    194         std::thread t0(f0);
    195         std::thread t1(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(f3);
    204         std::thread t1(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(f41);
    214         std::thread t1(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(f1);
    224         std::thread t1(f1);
    225         t0.join();
    226         t1.join();
    227         assert(init1::called == 1);
    228     }
    229     // check functors with 2 args
    230     {
    231         std::thread t0(f2);
    232         std::thread t1(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 }