1 // Copyright (C) 2020-2021 Free Software Foundation, Inc. 2 // 3 // This file is part of the GNU ISO C++ Library. This library is free 4 // software; you can redistribute it and/or modify it under the 5 // terms of the GNU General Public License as published by the 6 // Free Software Foundation; either version 3, or (at your option) 7 // any later version. 8 9 // This library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 14 // You should have received a copy of the GNU General Public License along 15 // with this library; see the file COPYING3. If not see 16 // <http://www.gnu.org/licenses/>. 17 18 // { dg-options "-std=gnu++2a -pthread" } 19 // { dg-do run { target c++2a } } 20 // { dg-require-effective-target pthread } 21 // { dg-require-gthreads "" } 22 // { dg-add-options libatomic } 23 24 #include <semaphore> 25 #ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE 26 #include <chrono> 27 #include <thread> 28 #include <atomic> 29 #include <testsuite_hooks.h> 30 test01()31void test01() 32 { 33 using namespace std::chrono_literals; 34 std::__platform_semaphore s(2); 35 s._M_acquire(); 36 37 auto const dur = 250ms; 38 { 39 auto const t0 = std::chrono::steady_clock::now(); 40 VERIFY( s._M_try_acquire_for(dur) ); 41 auto const diff = std::chrono::steady_clock::now() - t0; 42 VERIFY( diff < dur ); 43 } 44 45 { 46 auto const t0 = std::chrono::steady_clock::now(); 47 VERIFY( !s._M_try_acquire_for(dur) ); 48 auto const diff = std::chrono::steady_clock::now() - t0; 49 VERIFY( diff >= dur ); 50 } 51 } 52 test02()53void test02() 54 { 55 using namespace std::chrono_literals; 56 std::__platform_semaphore s(1); 57 std::atomic<int> a(0), b(0); 58 std::thread t([&] { 59 a.wait(0); 60 auto const dur = 250ms; 61 VERIFY( !s._M_try_acquire_for(dur) ); 62 b++; 63 b.notify_one(); 64 65 a.wait(1); 66 VERIFY( s._M_try_acquire_for(dur) ); 67 b++; 68 b.notify_one(); 69 }); 70 t.detach(); 71 72 s._M_acquire(); 73 a++; 74 a.notify_one(); 75 b.wait(0); 76 s._M_release(1); 77 a++; 78 a.notify_one(); 79 80 b.wait(1); 81 } 82 test03()83void test03() 84 { 85 using namespace std::chrono_literals; 86 std::__platform_semaphore s(2); 87 s._M_acquire(); 88 89 auto const dur = 250ms; 90 { 91 auto const at = std::chrono::system_clock::now() + dur; 92 auto const t0 = std::chrono::steady_clock::now(); 93 VERIFY( s._M_try_acquire_until(at) ); 94 auto const diff = std::chrono::steady_clock::now() - t0; 95 VERIFY( diff < dur ); 96 } 97 98 { 99 auto const at = std::chrono::system_clock::now() + dur; 100 auto const t0 = std::chrono::steady_clock::now(); 101 VERIFY( !s._M_try_acquire_until(at) ); 102 auto const diff = std::chrono::steady_clock::now() - t0; 103 VERIFY( diff >= dur ); 104 } 105 } 106 test04()107void test04() 108 { 109 using namespace std::chrono_literals; 110 std::__platform_semaphore s(1); 111 std::atomic<int> a(0), b(0); 112 std::thread t([&] { 113 a.wait(0); 114 auto const dur = 250ms; 115 { 116 auto const at = std::chrono::system_clock::now() + dur; 117 VERIFY( !s._M_try_acquire_until(at) ); 118 119 b++; 120 b.notify_one(); 121 } 122 123 a.wait(1); 124 { 125 auto const at = std::chrono::system_clock::now() + dur; 126 VERIFY( s._M_try_acquire_until(at) ); 127 } 128 b++; 129 b.notify_one(); 130 }); 131 t.detach(); 132 133 s._M_acquire(); 134 a++; 135 a.notify_one(); 136 b.wait(0); 137 s._M_release(1); 138 a++; 139 a.notify_one(); 140 141 b.wait(1); 142 } 143 #endif 144 main()145int main() 146 { 147 #ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE 148 test01(); 149 test02(); 150 test03(); 151 test04(); 152 #endif 153 return 0; 154 } 155