Commit 71226651 by Jonathan Wakely Committed by Jonathan Wakely

shared_mutex (__shared_mutex_pthread, [...]): New helper types implementing the…

shared_mutex (__shared_mutex_pthread, [...]): New helper types implementing the shared mutex requirements.

	* 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.

From-SVN: r224158
parent e918809c
2015-06-05 Jonathan Wakely <jwakely@redhat.com>
* 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.
2015-06-05 Ville Voutilainen <ville.voutilainen@gmail.com> 2015-06-05 Ville Voutilainen <ville.voutilainen@gmail.com>
Add __is_nothrow_swappable and take it into use. Add __is_nothrow_swappable and take it into use.
......
...@@ -52,25 +52,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -52,25 +52,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef _GLIBCXX_USE_C99_STDINT_TR1 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
#ifdef _GLIBCXX_HAS_GTHREADS #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 #define __cpp_lib_shared_timed_mutex 201402
class shared_timed_mutex;
/// shared_timed_mutex #if _GLIBCXX_USE_PTHREAD_RWLOCK_T
class shared_timed_mutex /// A shared mutex type implemented using pthread_rwlock_t.
class __shared_mutex_pthread
{ {
#if _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK friend class shared_timed_mutex;
typedef chrono::system_clock __clock_t;
#ifdef PTHREAD_RWLOCK_INITIALIZER #ifdef PTHREAD_RWLOCK_INITIALIZER
pthread_rwlock_t _M_rwlock = PTHREAD_RWLOCK_INITIALIZER; pthread_rwlock_t _M_rwlock = PTHREAD_RWLOCK_INITIALIZER;
public: public:
shared_timed_mutex() = default; __shared_mutex_pthread() = default;
~shared_timed_mutex() = default; ~__shared_mutex_pthread() = default;
#else #else
pthread_rwlock_t _M_rwlock; pthread_rwlock_t _M_rwlock;
public: public:
shared_timed_mutex() __shared_mutex_pthread()
{ {
int __ret = pthread_rwlock_init(&_M_rwlock, NULL); int __ret = pthread_rwlock_init(&_M_rwlock, NULL);
if (__ret == ENOMEM) if (__ret == ENOMEM)
...@@ -83,7 +89,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -83,7 +89,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_DEBUG_ASSERT(__ret == 0); _GLIBCXX_DEBUG_ASSERT(__ret == 0);
} }
~shared_timed_mutex() ~__shared_mutex_pthread()
{ {
int __ret __attribute((__unused__)) = pthread_rwlock_destroy(&_M_rwlock); int __ret __attribute((__unused__)) = pthread_rwlock_destroy(&_M_rwlock);
// Errors not handled: EBUSY, EINVAL // Errors not handled: EBUSY, EINVAL
...@@ -91,10 +97,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -91,10 +97,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} }
#endif #endif
shared_timed_mutex(const shared_timed_mutex&) = delete; __shared_mutex_pthread(const __shared_mutex_pthread&) = delete;
shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; __shared_mutex_pthread& operator=(const __shared_mutex_pthread&) = delete;
// Exclusive ownership
void void
lock() lock()
...@@ -116,48 +120,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -116,48 +120,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return true; return true;
} }
template<typename _Rep, typename _Period>
bool
try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
{
return try_lock_until(__clock_t::now() + __rel_time);
}
template<typename _Duration>
bool
try_lock_until(const chrono::time_point<__clock_t, _Duration>& __atime)
{
auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
__gthread_time_t __ts =
{
static_cast<std::time_t>(__s.time_since_epoch().count()),
static_cast<long>(__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<typename _Clock, typename _Duration>
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 void
unlock() unlock()
{ {
...@@ -198,74 +160,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -198,74 +160,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return true; return true;
} }
template<typename _Rep, typename _Period>
bool
try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
{
return try_lock_shared_until(__clock_t::now() + __rel_time);
}
template<typename _Duration>
bool
try_lock_shared_until(const chrono::time_point<__clock_t,
_Duration>& __atime)
{
auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
__gthread_time_t __ts =
{
static_cast<std::time_t>(__s.time_since_epoch().count()),
static_cast<long>(__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<typename _Clock, typename _Duration>
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 void
unlock_shared() unlock_shared()
{ {
unlock(); 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 #if ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK)
typedef chrono::system_clock __clock_t; /// 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. // Based on Howard Hinnant's reference implementation from N2406.
...@@ -312,15 +221,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -312,15 +221,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
unsigned _M_readers() const { return _M_state & _S_max_readers; } unsigned _M_readers() const { return _M_state & _S_max_readers; }
public: 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 ); _GLIBCXX_DEBUG_ASSERT( _M_state == 0 );
} }
shared_timed_mutex(const shared_timed_mutex&) = delete; __shared_mutex_cv(const __shared_mutex_cv&) = delete;
shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; __shared_mutex_cv& operator=(const __shared_mutex_cv&) = delete;
// Exclusive ownership // Exclusive ownership
...@@ -347,35 +256,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -347,35 +256,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return false; return false;
} }
template<typename _Rep, typename _Period>
bool
try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
{
return try_lock_until(__clock_t::now() + __rel_time);
}
template<typename _Clock, typename _Duration>
bool
try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
{
unique_lock<mutex> __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 void
unlock() unlock()
{ {
...@@ -411,28 +291,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -411,28 +291,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return false; return false;
} }
template<typename _Rep, typename _Period>
bool
try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
{
return try_lock_shared_until(__clock_t::now() + __rel_time);
}
template <typename _Clock, typename _Duration>
bool
try_lock_shared_until(const chrono::time_point<_Clock,
_Duration>& __abs_time)
{
unique_lock<mutex> __lk(_M_mut);
if (!_M_gate1.wait_until(__lk, __abs_time,
[=]{ return _M_state < _S_max_readers; }))
{
return false;
}
++_M_state;
return true;
}
void void
unlock_shared() unlock_shared()
{ {
...@@ -455,6 +313,228 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -455,6 +313,228 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_gate1.notify_one(); _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<typename _Rep, typename _Period>
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<typename _Rep, typename _Period>
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<typename _Duration>
bool
try_lock_until(const chrono::time_point<__clock_t, _Duration>& __atime)
{
auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
__gthread_time_t __ts =
{
static_cast<std::time_t>(__s.time_since_epoch().count()),
static_cast<long>(__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<typename _Clock, typename _Duration>
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<typename _Duration>
bool
try_lock_shared_until(const chrono::time_point<__clock_t,
_Duration>& __atime)
{
auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
__gthread_time_t __ts =
{
static_cast<std::time_t>(__s.time_since_epoch().count()),
static_cast<long>(__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<typename _Clock, typename _Duration>
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<typename _Clock, typename _Duration>
bool
try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
{
unique_lock<mutex> __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 <typename _Clock, typename _Duration>
bool
try_lock_shared_until(const chrono::time_point<_Clock,
_Duration>& __abs_time)
{
unique_lock<mutex> __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_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK
}; };
#endif // _GLIBCXX_HAS_GTHREADS #endif // _GLIBCXX_HAS_GTHREADS
......
// { 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
// <http://www.gnu.org/licenses/>.
#include <shared_mutex>
#include <system_error>
#include <testsuite_hooks.h>
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;
}
// { 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
// <http://www.gnu.org/licenses/>.
#include <shared_mutex>
void test01()
{
// assign
typedef std::shared_mutex mutex_type;
mutex_type m1;
mutex_type m2;
m1 = m2; // { dg-error "deleted" }
}
// { dg-prune-output "include" }
// { 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
// <http://www.gnu.org/licenses/>.
#include <shared_mutex>
void test01()
{
// assign
typedef std::shared_mutex mutex_type;
mutex_type m1;
mutex_type m2(m1); // { dg-error "deleted" }
}
// { dg-prune-output "include" }
// { 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
// <http://www.gnu.org/licenses/>.
#include <shared_mutex>
#include <testsuite_common_types.h>
void test01()
{
__gnu_test::standard_layout test;
test.operator()<std::shared_mutex>();
}
// { 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
// <http://www.gnu.org/licenses/>.
#include <shared_mutex>
#include <system_error>
#include <testsuite_hooks.h>
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;
}
// { 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
// <http://www.gnu.org/licenses/>.
#include <shared_mutex>
#include <thread>
#include <system_error>
#include <testsuite_hooks.h>
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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment