diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2018-11-17 23:35:44 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2018-11-17 23:35:44 +0000 |
commit | c5be64810cd037b134e2f388b9345a5ebf0ce387 (patch) | |
tree | fb731c4af3dad3470490f611f5941ab972bfa6f9 /libstdc++-v3/include/std/shared_mutex | |
parent | b579523b7bcd02739e6f06fe21a7ac6eb24dd6ec (diff) | |
download | gcc-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_mutex | 102 |
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; |