aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/src
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2014-11-12 23:55:11 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2014-11-12 23:55:11 +0000
commitbe8de8946ed904c92c09dadb158e76c9c5044d11 (patch)
tree7ee9e4d194e27f91eae668a26c02507636c07454 /libstdc++-v3/src
parentabb502071166f1eee1869cd5304d30d6763979f9 (diff)
downloadgcc-be8de8946ed904c92c09dadb158e76c9c5044d11.zip
gcc-be8de8946ed904c92c09dadb158e76c9c5044d11.tar.gz
gcc-be8de8946ed904c92c09dadb158e76c9c5044d11.tar.bz2
std::shared_ptr atomic operations
PR libstdc++/57250 * config/abi/pre/gnu.ver: Export new symbols. * include/Makefile.am: Add new header. * include/Makefile.in: Regenerate. * include/bits/shared_ptr_atomic.h: Define atomic access functions. * include/std/memory: Include new header. * src/c++11/shared_ptr.cc (_Sp_locker): Define and use mutex pool. * testsuite/20_util/shared_ptr/atomic/1.cc: New. * testsuite/20_util/shared_ptr/atomic/2.cc: New. * testsuite/20_util/shared_ptr/atomic/3.cc: New. From-SVN: r217452
Diffstat (limited to 'libstdc++-v3/src')
-rw-r--r--libstdc++-v3/src/c++11/shared_ptr.cc58
1 files changed, 58 insertions, 0 deletions
diff --git a/libstdc++-v3/src/c++11/shared_ptr.cc b/libstdc++-v3/src/c++11/shared_ptr.cc
index 53b3452..9247532 100644
--- a/libstdc++-v3/src/c++11/shared_ptr.cc
+++ b/libstdc++-v3/src/c++11/shared_ptr.cc
@@ -34,5 +34,63 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bad_weak_ptr::what() const noexcept
{ return "bad_weak_ptr"; }
+#ifdef __GTHREADS
+ namespace
+ {
+ const unsigned char mask = 0xf;
+ const unsigned char invalid = mask + 1;
+
+ inline unsigned char key(const void* addr)
+ { return _Hash_impl::hash(addr) & mask; }
+
+ /* Returns different instances of __mutex depending on the passed address
+ * in order to limit contention.
+ */
+ __gnu_cxx::__mutex&
+ get_mutex(unsigned char i)
+ {
+ static __gnu_cxx::__mutex m[mask + 1];
+ return m[i];
+ }
+ }
+
+ _Sp_locker::_Sp_locker(const void* p)
+ {
+ if (__gthread_active_p())
+ {
+ _M_key1 = _M_key2 = key(p);
+ get_mutex(_M_key1).lock();
+ }
+ else
+ _M_key1 = _M_key2 = invalid;
+ }
+
+ _Sp_locker::_Sp_locker(const void* p1, const void* p2)
+ {
+ if (__gthread_active_p())
+ {
+ _M_key1 = key(p1);
+ _M_key2 = key(p2);
+ if (_M_key2 < _M_key1)
+ get_mutex(_M_key2).lock();
+ get_mutex(_M_key1).lock();
+ if (_M_key2 > _M_key1)
+ get_mutex(_M_key2).lock();
+ }
+ else
+ _M_key1 = _M_key2 = invalid;
+ }
+
+ _Sp_locker::~_Sp_locker()
+ {
+ if (_M_key1 != invalid)
+ {
+ get_mutex(_M_key1).unlock();
+ if (_M_key2 != _M_key1)
+ get_mutex(_M_key2).unlock();
+ }
+ }
+#endif
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace