diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2014-11-12 23:55:11 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2014-11-12 23:55:11 +0000 |
commit | be8de8946ed904c92c09dadb158e76c9c5044d11 (patch) | |
tree | 7ee9e4d194e27f91eae668a26c02507636c07454 /libstdc++-v3/src | |
parent | abb502071166f1eee1869cd5304d30d6763979f9 (diff) | |
download | gcc-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.cc | 58 |
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 |