xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/src/c++11/shared_ptr.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
148fb7bfaSmrg // Support for pointer abstractions -*- C++ -*-
248fb7bfaSmrg 
3*b1e83836Smrg // Copyright (C) 2011-2022 Free Software Foundation, Inc.
448fb7bfaSmrg //
548fb7bfaSmrg // This file is part of the GNU ISO C++ Library.  This library is free
648fb7bfaSmrg // software; you can redistribute it and/or modify it under the
748fb7bfaSmrg // terms of the GNU General Public License as published by the
848fb7bfaSmrg // Free Software Foundation; either version 3, or (at your option)
948fb7bfaSmrg // any later version.
1048fb7bfaSmrg 
1148fb7bfaSmrg // This library is distributed in the hope that it will be useful,
1248fb7bfaSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
1348fb7bfaSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1448fb7bfaSmrg // GNU General Public License for more details.
1548fb7bfaSmrg 
1648fb7bfaSmrg // Under Section 7 of GPL version 3, you are granted additional
1748fb7bfaSmrg // permissions described in the GCC Runtime Library Exception, version
1848fb7bfaSmrg // 3.1, as published by the Free Software Foundation.
1948fb7bfaSmrg 
2048fb7bfaSmrg // You should have received a copy of the GNU General Public License and
2148fb7bfaSmrg // a copy of the GCC Runtime Library Exception along with this program;
2248fb7bfaSmrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2348fb7bfaSmrg // <http://www.gnu.org/licenses/>.
2448fb7bfaSmrg 
2548fb7bfaSmrg #include <memory>
2648fb7bfaSmrg 
27b17d1066Smrg #include "mutex_pool.h"
28b17d1066Smrg 
29b17d1066Smrg namespace __gnu_internal _GLIBCXX_VISIBILITY(hidden)
30b17d1066Smrg {
31b17d1066Smrg   /* Returns different instances of __mutex depending on the passed index
32b17d1066Smrg    * in order to limit contention.
33b17d1066Smrg    */
34b17d1066Smrg   __gnu_cxx::__mutex&
get_mutex(unsigned char i)35b17d1066Smrg   get_mutex(unsigned char i)
36b17d1066Smrg   {
37fb8a8121Smrg     // increase alignment to put each lock on a separate cache line
38fb8a8121Smrg     struct alignas(64) M : __gnu_cxx::__mutex { };
39fb8a8121Smrg     static M m[mask + 1];
40b17d1066Smrg     return m[i];
41b17d1066Smrg   }
42b17d1066Smrg }
43b17d1066Smrg 
4448fb7bfaSmrg namespace std _GLIBCXX_VISIBILITY(default)
4548fb7bfaSmrg {
4648fb7bfaSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
4748fb7bfaSmrg 
4848fb7bfaSmrg   bad_weak_ptr::~bad_weak_ptr() noexcept = default;
4948fb7bfaSmrg 
5048fb7bfaSmrg   char const*
what() const5148fb7bfaSmrg   bad_weak_ptr::what() const noexcept
5248fb7bfaSmrg   { return "bad_weak_ptr"; }
5348fb7bfaSmrg 
544d5abbe8Smrg #ifdef __GTHREADS
554d5abbe8Smrg   namespace
564d5abbe8Smrg   {
key(const void * addr)574d5abbe8Smrg     inline unsigned char key(const void* addr)
58b17d1066Smrg     { return _Hash_impl::hash(addr) & __gnu_internal::mask; }
594d5abbe8Smrg   }
604d5abbe8Smrg 
_Sp_locker(const void * p)613f4ceed9Smrg   _Sp_locker::_Sp_locker(const void* p) noexcept
624d5abbe8Smrg   {
634d5abbe8Smrg     if (__gthread_active_p())
644d5abbe8Smrg       {
654d5abbe8Smrg 	_M_key1 = _M_key2 = key(p);
66b17d1066Smrg         __gnu_internal::get_mutex(_M_key1).lock();
674d5abbe8Smrg       }
684d5abbe8Smrg     else
69b17d1066Smrg       _M_key1 = _M_key2 = __gnu_internal::invalid;
704d5abbe8Smrg   }
714d5abbe8Smrg 
_Sp_locker(const void * p1,const void * p2)723f4ceed9Smrg   _Sp_locker::_Sp_locker(const void* p1, const void* p2) noexcept
734d5abbe8Smrg   {
744d5abbe8Smrg     if (__gthread_active_p())
754d5abbe8Smrg       {
764d5abbe8Smrg 	_M_key1 = key(p1);
774d5abbe8Smrg 	_M_key2 = key(p2);
784d5abbe8Smrg 	if (_M_key2 < _M_key1)
79b17d1066Smrg 	  __gnu_internal::get_mutex(_M_key2).lock();
80b17d1066Smrg 	__gnu_internal::get_mutex(_M_key1).lock();
814d5abbe8Smrg 	if (_M_key2 > _M_key1)
82b17d1066Smrg 	  __gnu_internal::get_mutex(_M_key2).lock();
834d5abbe8Smrg       }
844d5abbe8Smrg     else
85b17d1066Smrg       _M_key1 = _M_key2 = __gnu_internal::invalid;
864d5abbe8Smrg   }
874d5abbe8Smrg 
~_Sp_locker()884d5abbe8Smrg   _Sp_locker::~_Sp_locker()
894d5abbe8Smrg   {
90b17d1066Smrg     if (_M_key1 != __gnu_internal::invalid)
914d5abbe8Smrg       {
92b17d1066Smrg 	__gnu_internal::get_mutex(_M_key1).unlock();
934d5abbe8Smrg 	if (_M_key2 != _M_key1)
94b17d1066Smrg 	  __gnu_internal::get_mutex(_M_key2).unlock();
954d5abbe8Smrg       }
964d5abbe8Smrg   }
974d5abbe8Smrg #endif
984d5abbe8Smrg 
99181254a7Smrg   bool
_S_eq(const type_info & ti)100*b1e83836Smrg   _Sp_make_shared_tag::_S_eq(const type_info& ti [[gnu::unused]]) noexcept
101181254a7Smrg   {
102181254a7Smrg #if __cpp_rtti
103181254a7Smrg     return ti == typeid(_Sp_make_shared_tag);
104181254a7Smrg #else
105181254a7Smrg     // If libstdc++ itself is built with -fno-rtti then just assume that
106181254a7Smrg     // make_shared and allocate_shared will never be used with -frtti.
107181254a7Smrg     return false;
108181254a7Smrg #endif
109181254a7Smrg   }
110181254a7Smrg 
11148fb7bfaSmrg _GLIBCXX_END_NAMESPACE_VERSION
11248fb7bfaSmrg } // namespace
113