aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/std/shared_mutex
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2018-11-17 23:35:44 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2018-11-17 23:35:44 +0000
commitc5be64810cd037b134e2f388b9345a5ebf0ce387 (patch)
treefb731c4af3dad3470490f611f5941ab972bfa6f9 /libstdc++-v3/include/std/shared_mutex
parentb579523b7bcd02739e6f06fe21a7ac6eb24dd6ec (diff)
downloadgcc-c5be64810cd037b134e2f388b9345a5ebf0ce387.zip
gcc-c5be64810cd037b134e2f388b9345a5ebf0ce387.tar.gz
gcc-c5be64810cd037b134e2f388b9345a5ebf0ce387.tar.bz2
Implement std::pmr::synchronized_pool_resource
Define the thread-safe pool resource, using a shared_mutex to allow multiple threads to concurrently allocate from thread-specific pools. Define new weak symbols for the pthread_rwlock_t functions, to avoid making libstdc++.so depend on libpthread.so When the necessary Gthread support is absent only define the feature-test macro to 1, rather than 201603. This is intended to imply incomplete support, because everything except synchronized_pool_resource works. Implement std::pmr::synchronized_pool_resource * config/abi/pre/gnu.ver: Add new symbols. * include/std/memory_resource [_GLIBCXX_HAS_GTHREADS] (__cpp_lib_memory_resource): Define to expected value, 201603. (synchronized_pool_resource): New class. [!_GLIBCXX_HAS_GTHREADS] (__cpp_lib_memory_resource): Define to 1. * include/std/shared_mutex (__glibcxx_rwlock_rdlock) (__glibcxx_rwlock_tryrdlock, __glibcxx_rwlock_wrlock) (__glibcxx_rwlock_trywrlock, __glibcxx_rwlock_unlock) (__glibcxx_rwlock_destroy, __glibcxx_rwlock_init) (__glibcxx_rwlock_timedrdlock, __glibcxx_rwlock_timedwrlock): Define weak symbols for POSIX rwlock functions. (__shared_mutex_pthread): Use weak symbols. * include/std/version (__cpp_lib_memory_resource): Define. * src/c++17/memory_resource.cc [_GLIBCXX_HAS_GTHREADS] (synchronized_pool_resource::_TPools): New class. (destroy_TPools): New function for pthread_key_create destructor. (synchronized_pool_resource::synchronized_pool_resource) (synchronized_pool_resource::~synchronized_pool_resource) (synchronized_pool_resource::release) (synchronized_pool_resource::do_allocate) (synchronized_pool_resource::do_deallocate): Define public members. (synchronized_pool_resource::_M_thread_specific_pools) (synchronized_pool_resource::_M_alloc_tpools) (synchronized_pool_resource::_M_alloc_shared_tpools): Define private members. * testsuite/20_util/synchronized_pool_resource/allocate.cc: New test. * testsuite/20_util/synchronized_pool_resource/cons.cc: New test. * testsuite/20_util/synchronized_pool_resource/is_equal.cc: New test. * testsuite/20_util/synchronized_pool_resource/multithreaded.cc: New test. * testsuite/20_util/synchronized_pool_resource/release.cc: New test. * testsuite/performance/20_util/memory_resource/pools.cc: Add multithreaded tests using pmr::synchronized_pool_resource. From-SVN: r266242
Diffstat (limited to 'libstdc++-v3/include/std/shared_mutex')
-rw-r--r--libstdc++-v3/include/std/shared_mutex102
1 files changed, 93 insertions, 9 deletions
diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex
index dce97f4..8aa6e9f 100644
--- a/libstdc++-v3/include/std/shared_mutex
+++ b/libstdc++-v3/include/std/shared_mutex
@@ -57,6 +57,90 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class shared_timed_mutex;
#if _GLIBCXX_USE_PTHREAD_RWLOCK_T
+#ifdef __gthrw
+#define _GLIBCXX_GTHRW(name) \
+ __gthrw(pthread_ ## name); \
+ static inline int \
+ __glibcxx_ ## name (pthread_rwlock_t *__rwlock) \
+ { \
+ if (__gthread_active_p ()) \
+ return __gthrw_(pthread_ ## name) (__rwlock); \
+ else \
+ return 0; \
+ }
+ _GLIBCXX_GTHRW(rwlock_rdlock)
+ _GLIBCXX_GTHRW(rwlock_tryrdlock)
+ _GLIBCXX_GTHRW(rwlock_wrlock)
+ _GLIBCXX_GTHRW(rwlock_trywrlock)
+ _GLIBCXX_GTHRW(rwlock_unlock)
+# ifndef PTHREAD_RWLOCK_INITIALIZER
+ _GLIBCXX_GTHRW(rwlock_destroy)
+ __gthrw(pthread_rwlock_init);
+ static inline int
+ __glibcxx_rwlock_init (pthread_rwlock_t *__rwlock)
+ {
+ if (__gthread_active_p ())
+ return __gthrw_(pthread_rwlock_init) (__rwlock, NULL);
+ else
+ return 0;
+ }
+# endif
+# if _GTHREAD_USE_MUTEX_TIMEDLOCK
+ __gthrw(pthread_rwlock_timedrdlock);
+ static inline int
+ __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock,
+ const timespec *__ts)
+ {
+ if (__gthread_active_p ())
+ return __gthrw_(pthread_rwlock_timedrdlock) (__rwlock, __ts);
+ else
+ return 0;
+ }
+ __gthrw(pthread_rwlock_timedwrlock);
+ static inline int
+ __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock,
+ const timespec *__ts)
+ {
+ if (__gthread_active_p ())
+ return __gthrw_(pthread_rwlock_timedwrlock) (__rwlock, __ts);
+ else
+ return 0;
+ }
+# endif
+#else
+ static inline int
+ __glibcxx_rwlock_rdlock (pthread_rwlock_t *__rwlock)
+ { return pthread_rwlock_rdlock (__rwlock); }
+ static inline int
+ __glibcxx_rwlock_tryrdlock (pthread_rwlock_t *__rwlock)
+ { return pthread_rwlock_tryrdlock (__rwlock); }
+ static inline int
+ __glibcxx_rwlock_wrlock (pthread_rwlock_t *__rwlock)
+ { return pthread_rwlock_wrlock (__rwlock); }
+ static inline int
+ __glibcxx_rwlock_trywrlock (pthread_rwlock_t *__rwlock)
+ { return pthread_rwlock_trywrlock (__rwlock); }
+ static inline int
+ __glibcxx_rwlock_unlock (pthread_rwlock_t *__rwlock)
+ { return pthread_rwlock_unlock (__rwlock); }
+ static inline int
+ __glibcxx_rwlock_destroy(pthread_rwlock_t *__rwlock)
+ { return pthread_rwlock_destroy (__rwlock); }
+ static inline int
+ __glibcxx_rwlock_init(pthread_rwlock_t *__rwlock)
+ { return pthread_rwlock_init (__rwlock, NULL); }
+# if _GTHREAD_USE_MUTEX_TIMEDLOCK
+ static inline int
+ __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock,
+ const timespec *__ts)
+ { return pthread_rwlock_timedrdlock (__rwlock, __ts); }
+ static inline int
+ __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock,
+ const timespec *__ts)
+ { return pthread_rwlock_timedwrlock (__rwlock, __ts); }
+# endif
+#endif
+
/// A shared mutex type implemented using pthread_rwlock_t.
class __shared_mutex_pthread
{
@@ -74,7 +158,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public:
__shared_mutex_pthread()
{
- int __ret = pthread_rwlock_init(&_M_rwlock, NULL);
+ int __ret = __glibcxx_rwlock_init(&_M_rwlock, NULL);
if (__ret == ENOMEM)
__throw_bad_alloc();
else if (__ret == EAGAIN)
@@ -87,7 +171,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~__shared_mutex_pthread()
{
- int __ret __attribute((__unused__)) = pthread_rwlock_destroy(&_M_rwlock);
+ int __ret __attribute((__unused__)) = __glibcxx_rwlock_destroy(&_M_rwlock);
// Errors not handled: EBUSY, EINVAL
__glibcxx_assert(__ret == 0);
}
@@ -99,7 +183,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
lock()
{
- int __ret = pthread_rwlock_wrlock(&_M_rwlock);
+ int __ret = __glibcxx_rwlock_wrlock(&_M_rwlock);
if (__ret == EDEADLK)
__throw_system_error(int(errc::resource_deadlock_would_occur));
// Errors not handled: EINVAL
@@ -109,7 +193,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool
try_lock()
{
- int __ret = pthread_rwlock_trywrlock(&_M_rwlock);
+ int __ret = __glibcxx_rwlock_trywrlock(&_M_rwlock);
if (__ret == EBUSY) return false;
// Errors not handled: EINVAL
__glibcxx_assert(__ret == 0);
@@ -119,7 +203,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
unlock()
{
- int __ret __attribute((__unused__)) = pthread_rwlock_unlock(&_M_rwlock);
+ int __ret __attribute((__unused__)) = __glibcxx_rwlock_unlock(&_M_rwlock);
// Errors not handled: EPERM, EBUSY, EINVAL
__glibcxx_assert(__ret == 0);
}
@@ -135,7 +219,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// is okay based on the current specification of forward progress
// guarantees by the standard.
do
- __ret = pthread_rwlock_rdlock(&_M_rwlock);
+ __ret = __glibcxx_rwlock_rdlock(&_M_rwlock);
while (__ret == EAGAIN);
if (__ret == EDEADLK)
__throw_system_error(int(errc::resource_deadlock_would_occur));
@@ -146,7 +230,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool
try_lock_shared()
{
- int __ret = pthread_rwlock_tryrdlock(&_M_rwlock);
+ int __ret = __glibcxx_rwlock_tryrdlock(&_M_rwlock);
// If the maximum number of read locks has been exceeded, we just fail
// to acquire the lock. Unlike for lock(), we are not allowed to throw
// an exception.
@@ -413,7 +497,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_cast<long>(__ns.count())
};
- int __ret = pthread_rwlock_timedwrlock(&_M_rwlock, &__ts);
+ int __ret = __glibcxx_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)
@@ -466,7 +550,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// mistaken for a spurious failure, which might help users realise
// there is a deadlock.
do
- __ret = pthread_rwlock_timedrdlock(&_M_rwlock, &__ts);
+ __ret = __glibcxx_rwlock_timedrdlock(&_M_rwlock, &__ts);
while (__ret == EAGAIN || __ret == EDEADLK);
if (__ret == ETIMEDOUT)
return false;