commit 35e47469169a724f6eb0dfc0a4b79aba1c81f213 Author: Jonathan Wakely Date: Fri Jun 5 17:05:04 2015 +0100 * include/std/shared_mutex (__shared_mutex_pthread, __shared_mutex_cv): New helper types implementing the shared mutex requirements. (shared_mutex): New type for C++17. (shared_timed_mutex): Derive from one of the new helper types. * testsuite/30_threads/shared_mutex/cons/1.cc: New. * testsuite/30_threads/shared_mutex/cons/assign_neg.cc: New. * testsuite/30_threads/shared_mutex/cons/copy_neg.cc: New. * testsuite/30_threads/shared_mutex/requirements/standard_layout.cc: New. * testsuite/30_threads/shared_mutex/try_lock/1.cc: New. * testsuite/30_threads/shared_mutex/try_lock/2.cc: New. diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex index b72a822..0a893ee 100644 --- a/libstdc++-v3/include/std/shared_mutex +++ b/libstdc++-v3/include/std/shared_mutex @@ -52,25 +52,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef _GLIBCXX_USE_C99_STDINT_TR1 #ifdef _GLIBCXX_HAS_GTHREADS +#if __cplusplus > 201402L +// TODO: #define __cpp_lib_shared_mutex 201505 + class shared_mutex; +#endif + #define __cpp_lib_shared_timed_mutex 201402 + class shared_timed_mutex; - /// shared_timed_mutex - class shared_timed_mutex +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T + /// A shared mutex type implemented using pthread_rwlock_t. + class __shared_mutex_pthread { -#if _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK - typedef chrono::system_clock __clock_t; + friend class shared_timed_mutex; #ifdef PTHREAD_RWLOCK_INITIALIZER pthread_rwlock_t _M_rwlock = PTHREAD_RWLOCK_INITIALIZER; public: - shared_timed_mutex() = default; - ~shared_timed_mutex() = default; + __shared_mutex_pthread() = default; + ~__shared_mutex_pthread() = default; #else pthread_rwlock_t _M_rwlock; public: - shared_timed_mutex() + __shared_mutex_pthread() { int __ret = pthread_rwlock_init(&_M_rwlock, NULL); if (__ret == ENOMEM) @@ -83,7 +89,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_DEBUG_ASSERT(__ret == 0); } - ~shared_timed_mutex() + ~__shared_mutex_pthread() { int __ret __attribute((__unused__)) = pthread_rwlock_destroy(&_M_rwlock); // Errors not handled: EBUSY, EINVAL @@ -91,10 +97,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif - shared_timed_mutex(const shared_timed_mutex&) = delete; - shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; - - // Exclusive ownership + __shared_mutex_pthread(const __shared_mutex_pthread&) = delete; + __shared_mutex_pthread& operator=(const __shared_mutex_pthread&) = delete; void lock() @@ -116,48 +120,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return true; } - template - bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) - { - return try_lock_until(__clock_t::now() + __rel_time); - } - - template - bool - try_lock_until(const chrono::time_point<__clock_t, _Duration>& __atime) - { - auto __s = chrono::time_point_cast(__atime); - auto __ns = chrono::duration_cast(__atime - __s); - - __gthread_time_t __ts = - { - static_cast(__s.time_since_epoch().count()), - static_cast(__ns.count()) - }; - - int __ret = pthread_rwlock_timedwrlock(&_M_rwlock, &__ts); - // On self-deadlock, we just fail to acquire the lock. Technically, - // the program violated the precondition. - if (__ret == ETIMEDOUT || __ret == EDEADLK) - return false; - // Errors not handled: EINVAL - _GLIBCXX_DEBUG_ASSERT(__ret == 0); - return true; - } - - template - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) - { - // DR 887 - Sync unknown clock to known clock. - const typename _Clock::time_point __c_entry = _Clock::now(); - const __clock_t::time_point __s_entry = __clock_t::now(); - const auto __delta = __abs_time - __c_entry; - const auto __s_atime = __s_entry + __delta; - return try_lock_until(__s_atime); - } - void unlock() { @@ -198,74 +160,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return true; } - template - bool - try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) - { - return try_lock_shared_until(__clock_t::now() + __rel_time); - } - - template - bool - try_lock_shared_until(const chrono::time_point<__clock_t, - _Duration>& __atime) - { - auto __s = chrono::time_point_cast(__atime); - auto __ns = chrono::duration_cast(__atime - __s); - - __gthread_time_t __ts = - { - static_cast(__s.time_since_epoch().count()), - static_cast(__ns.count()) - }; - - int __ret; - // Unlike for lock(), we are not allowed to throw an exception so if - // the maximum number of read locks has been exceeded, or we would - // deadlock, we just try to acquire the lock again (and will time out - // eventually). - // In cases where we would exceed the maximum number of read locks - // throughout the whole time until the timeout, we will fail to - // acquire the lock even if it would be logically free; however, this - // is allowed by the standard, and we made a "strong effort" - // (see C++14 30.4.1.4p26). - // For cases where the implementation detects a deadlock we - // intentionally block and timeout so that an early return isn't - // mistaken for a spurious failure, which might help users realise - // there is a deadlock. - do - __ret = pthread_rwlock_timedrdlock(&_M_rwlock, &__ts); - while (__ret == EAGAIN || __ret == EDEADLK); - if (__ret == ETIMEDOUT) - return false; - // Errors not handled: EINVAL - _GLIBCXX_DEBUG_ASSERT(__ret == 0); - return true; - } - - template - bool - try_lock_shared_until(const chrono::time_point<_Clock, - _Duration>& __abs_time) - { - // DR 887 - Sync unknown clock to known clock. - const typename _Clock::time_point __c_entry = _Clock::now(); - const __clock_t::time_point __s_entry = __clock_t::now(); - const auto __delta = __abs_time - __c_entry; - const auto __s_atime = __s_entry + __delta; - return try_lock_shared_until(__s_atime); - } - void unlock_shared() { unlock(); } -#else // ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK) + void* native_handle() { return &_M_rwlock; } + }; +#endif - // Must use the same clock as condition_variable - typedef chrono::system_clock __clock_t; +#if ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK) + /// A shared mutex type implemented using std::condition_variable. + class __shared_mutex_cv + { + friend class shared_timed_mutex; // Based on Howard Hinnant's reference implementation from N2406. @@ -312,15 +221,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION unsigned _M_readers() const { return _M_state & _S_max_readers; } public: - shared_timed_mutex() : _M_state(0) {} + __shared_mutex_cv() : _M_state(0) {} - ~shared_timed_mutex() + ~__shared_mutex_cv() { _GLIBCXX_DEBUG_ASSERT( _M_state == 0 ); } - shared_timed_mutex(const shared_timed_mutex&) = delete; - shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; + __shared_mutex_cv(const __shared_mutex_cv&) = delete; + __shared_mutex_cv& operator=(const __shared_mutex_cv&) = delete; // Exclusive ownership @@ -347,35 +256,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return false; } - template - bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) - { - return try_lock_until(__clock_t::now() + __rel_time); - } - - template - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) - { - unique_lock __lk(_M_mut); - if (!_M_gate1.wait_until(__lk, __abs_time, - [=]{ return !_M_write_entered(); })) - { - return false; - } - _M_state |= _S_write_entered; - if (!_M_gate2.wait_until(__lk, __abs_time, - [=]{ return _M_readers() == 0; })) - { - _M_state ^= _S_write_entered; - // Wake all threads blocked while the write-entered flag was set. - _M_gate1.notify_all(); - return false; - } - return true; - } - void unlock() { @@ -411,28 +291,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return false; } - template - bool - try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) - { - return try_lock_shared_until(__clock_t::now() + __rel_time); - } - - template - bool - try_lock_shared_until(const chrono::time_point<_Clock, - _Duration>& __abs_time) - { - unique_lock __lk(_M_mut); - if (!_M_gate1.wait_until(__lk, __abs_time, - [=]{ return _M_state < _S_max_readers; })) - { - return false; - } - ++_M_state; - return true; - } - void unlock_shared() { @@ -455,6 +313,228 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_gate1.notify_one(); } } + }; +#endif + +#if __cplusplus > 201402L + /// The standard shared mutex type. + class shared_mutex + { + public: + shared_mutex() = default; + ~shared_mutex() = default; + + shared_mutex(const shared_mutex&) = delete; + shared_mutex& operator=(const shared_mutex&) = delete; + + // Exclusive ownership + + void lock() { _M_impl.lock(); } + bool try_lock() { return _M_impl.try_lock(); } + void unlock() { _M_impl.try_lock(); } + + // Shared ownership + + void lock_shared() { _M_impl.lock_shared(); } + bool try_lock_shared() { return _M_impl.try_lock_shared(); } + void unlock_shared() { _M_impl.unlock_shared(); } + +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T + typedef void* native_handle_type; + native_handle_type native_handle() { return _M_impl.native_handle(); } + + private: + __shared_mutex_pthread _M_impl; +#else + private: + __shared_mutex_cv _M_impl; +#endif + }; +#endif // C++17 + +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK + using __shared_timed_mutex_base = __shared_mutex_pthread; +#else + using __shared_timed_mutex_base = __shared_mutex_cv; +#endif + + /// The standard shared timed mutex type. + class shared_timed_mutex + : private __shared_timed_mutex_base + { + using _Base = __shared_timed_mutex_base; + + // Must use the same clock as condition_variable for __shared_mutex_cv. + typedef chrono::system_clock __clock_t; + + public: + shared_timed_mutex() = default; + ~shared_timed_mutex() = default; + + shared_timed_mutex(const shared_timed_mutex&) = delete; + shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; + + // Exclusive ownership + + void lock() { _Base::lock(); } + bool try_lock() { return _Base::try_lock(); } + void unlock() { _Base::unlock(); } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) + { + return try_lock_until(__clock_t::now() + __rel_time); + } + + // Shared ownership + + void lock_shared() { _Base::lock_shared(); } + bool try_lock_shared() { return _Base::try_lock_shared(); } + void unlock_shared() { _Base::unlock_shared(); } + + template + bool + try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) + { + return try_lock_shared_until(__clock_t::now() + __rel_time); + } + +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK + + // Exclusive ownership + + template + bool + try_lock_until(const chrono::time_point<__clock_t, _Duration>& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = + { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + int __ret = pthread_rwlock_timedwrlock(&_M_rwlock, &__ts); + // On self-deadlock, we just fail to acquire the lock. Technically, + // the program violated the precondition. + if (__ret == ETIMEDOUT || __ret == EDEADLK) + return false; + // Errors not handled: EINVAL + _GLIBCXX_DEBUG_ASSERT(__ret == 0); + return true; + } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) + { + // DR 887 - Sync unknown clock to known clock. + const typename _Clock::time_point __c_entry = _Clock::now(); + const __clock_t::time_point __s_entry = __clock_t::now(); + const auto __delta = __abs_time - __c_entry; + const auto __s_atime = __s_entry + __delta; + return try_lock_until(__s_atime); + } + + // Shared ownership + + template + bool + try_lock_shared_until(const chrono::time_point<__clock_t, + _Duration>& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = + { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + int __ret; + // Unlike for lock(), we are not allowed to throw an exception so if + // the maximum number of read locks has been exceeded, or we would + // deadlock, we just try to acquire the lock again (and will time out + // eventually). + // In cases where we would exceed the maximum number of read locks + // throughout the whole time until the timeout, we will fail to + // acquire the lock even if it would be logically free; however, this + // is allowed by the standard, and we made a "strong effort" + // (see C++14 30.4.1.4p26). + // For cases where the implementation detects a deadlock we + // intentionally block and timeout so that an early return isn't + // mistaken for a spurious failure, which might help users realise + // there is a deadlock. + do + __ret = pthread_rwlock_timedrdlock(&_M_rwlock, &__ts); + while (__ret == EAGAIN || __ret == EDEADLK); + if (__ret == ETIMEDOUT) + return false; + // Errors not handled: EINVAL + _GLIBCXX_DEBUG_ASSERT(__ret == 0); + return true; + } + + template + bool + try_lock_shared_until(const chrono::time_point<_Clock, + _Duration>& __abs_time) + { + // DR 887 - Sync unknown clock to known clock. + const typename _Clock::time_point __c_entry = _Clock::now(); + const __clock_t::time_point __s_entry = __clock_t::now(); + const auto __delta = __abs_time - __c_entry; + const auto __s_atime = __s_entry + __delta; + return try_lock_shared_until(__s_atime); + } + +#else // ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK) + + // Exclusive ownership + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) + { + unique_lock __lk(_M_mut); + if (!_M_gate1.wait_until(__lk, __abs_time, + [=]{ return !_M_write_entered(); })) + { + return false; + } + _M_state |= _S_write_entered; + if (!_M_gate2.wait_until(__lk, __abs_time, + [=]{ return _M_readers() == 0; })) + { + _M_state ^= _S_write_entered; + // Wake all threads blocked while the write-entered flag was set. + _M_gate1.notify_all(); + return false; + } + return true; + } + + // Shared ownership + + template + bool + try_lock_shared_until(const chrono::time_point<_Clock, + _Duration>& __abs_time) + { + unique_lock __lk(_M_mut); + if (!_M_gate1.wait_until(__lk, __abs_time, + [=]{ return _M_state < _S_max_readers; })) + { + return false; + } + ++_M_state; + return true; + } + #endif // _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK }; #endif // _GLIBCXX_HAS_GTHREADS diff --git a/libstdc++-v3/testsuite/30_threads/shared_mutex/cons/1.cc b/libstdc++-v3/testsuite/30_threads/shared_mutex/cons/1.cc new file mode 100644 index 0000000..f54406d --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/shared_mutex/cons/1.cc @@ -0,0 +1,49 @@ +// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } } +// { dg-options " -std=gnu++17 -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } } +// { dg-options " -std=gnu++17 -pthreads" { target *-*-solaris* } } +// { dg-options " -std=gnu++17 " { target *-*-cygwin *-*-darwin* } } +// { dg-require-cstdint "" } +// { dg-require-gthreads "" } + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + + +#include +#include +#include + +int main() +{ + bool test __attribute__((unused)) = true; + typedef std::shared_mutex mutex_type; + + try + { + mutex_type m1; + } + catch (const std::system_error& e) + { + VERIFY( false ); + } + catch (...) + { + VERIFY( false ); + } + + return 0; +} diff --git a/libstdc++-v3/testsuite/30_threads/shared_mutex/cons/assign_neg.cc b/libstdc++-v3/testsuite/30_threads/shared_mutex/cons/assign_neg.cc new file mode 100644 index 0000000..7571323 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/shared_mutex/cons/assign_neg.cc @@ -0,0 +1,35 @@ +// { dg-do compile } +// { dg-options "-std=gnu++17" } +// { dg-require-cstdint "" } +// { dg-require-gthreads "" } + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + + +#include + +void test01() +{ + // assign + typedef std::shared_mutex mutex_type; + mutex_type m1; + mutex_type m2; + m1 = m2; // { dg-error "deleted" } +} + +// { dg-prune-output "include" } diff --git a/libstdc++-v3/testsuite/30_threads/shared_mutex/cons/copy_neg.cc b/libstdc++-v3/testsuite/30_threads/shared_mutex/cons/copy_neg.cc new file mode 100644 index 0000000..42ede2d --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/shared_mutex/cons/copy_neg.cc @@ -0,0 +1,34 @@ +// { dg-do compile } +// { dg-options "-std=gnu++17" } +// { dg-require-cstdint "" } +// { dg-require-gthreads "" } + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + + +#include + +void test01() +{ + // assign + typedef std::shared_mutex mutex_type; + mutex_type m1; + mutex_type m2(m1); // { dg-error "deleted" } +} + +// { dg-prune-output "include" } diff --git a/libstdc++-v3/testsuite/30_threads/shared_mutex/requirements/standard_layout.cc b/libstdc++-v3/testsuite/30_threads/shared_mutex/requirements/standard_layout.cc new file mode 100644 index 0000000..8a92c7d --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/shared_mutex/requirements/standard_layout.cc @@ -0,0 +1,31 @@ +// { dg-do compile } +// { dg-options "-std=gnu++17" } +// { dg-require-cstdint "" } +// { dg-require-gthreads "" } + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + + +#include +#include + +void test01() +{ + __gnu_test::standard_layout test; + test.operator()(); +} diff --git a/libstdc++-v3/testsuite/30_threads/shared_mutex/try_lock/1.cc b/libstdc++-v3/testsuite/30_threads/shared_mutex/try_lock/1.cc new file mode 100644 index 0000000..d5ab962 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/shared_mutex/try_lock/1.cc @@ -0,0 +1,52 @@ +// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } } +// { dg-options " -std=gnu++17 -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } } +// { dg-options " -std=gnu++17 -pthreads" { target *-*-solaris* } } +// { dg-options " -std=gnu++17 " { target *-*-cygwin *-*-darwin* } } +// { dg-require-cstdint "" } +// { dg-require-gthreads "" } + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + + +#include +#include +#include + +int main() +{ + bool test __attribute__((unused)) = true; + typedef std::shared_mutex mutex_type; + + try + { + mutex_type m; + bool b = m.try_lock(); + VERIFY( b ); + m.unlock(); + } + catch (const std::system_error& e) + { + VERIFY( false ); + } + catch (...) + { + VERIFY( false ); + } + + return 0; +} diff --git a/libstdc++-v3/testsuite/30_threads/shared_mutex/try_lock/2.cc b/libstdc++-v3/testsuite/30_threads/shared_mutex/try_lock/2.cc new file mode 100644 index 0000000..be9e3ae --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/shared_mutex/try_lock/2.cc @@ -0,0 +1,67 @@ +// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } } +// { dg-options " -std=gnu++17 -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } } +// { dg-options " -std=gnu++17 -pthreads" { target *-*-solaris* } } +// { dg-options " -std=gnu++17 " { target *-*-cygwin *-*-darwin* } } +// { dg-require-cstdint "" } +// { dg-require-gthreads "" } + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + + +#include +#include +#include +#include + +int main() +{ + bool test __attribute__((unused)) = true; + typedef std::shared_mutex mutex_type; + + try + { + mutex_type m; + m.lock(); + bool b; + + std::thread t([&] { + try + { + b = m.try_lock(); + } + catch (const std::system_error& e) + { + VERIFY( false ); + } + }); + t.join(); + VERIFY( !b ); + + m.unlock(); + } + catch (const std::system_error& e) + { + VERIFY( false ); + } + catch (...) + { + VERIFY( false ); + } + + return 0; +}