xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/src/c++11/shared_ptr.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 // Support for pointer abstractions -*- C++ -*-
2 
3 // Copyright (C) 2011-2022 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 #include <memory>
26 
27 #include "mutex_pool.h"
28 
29 namespace __gnu_internal _GLIBCXX_VISIBILITY(hidden)
30 {
31   /* Returns different instances of __mutex depending on the passed index
32    * in order to limit contention.
33    */
34   __gnu_cxx::__mutex&
get_mutex(unsigned char i)35   get_mutex(unsigned char i)
36   {
37     // increase alignment to put each lock on a separate cache line
38     struct alignas(64) M : __gnu_cxx::__mutex { };
39     static M m[mask + 1];
40     return m[i];
41   }
42 }
43 
44 namespace std _GLIBCXX_VISIBILITY(default)
45 {
46 _GLIBCXX_BEGIN_NAMESPACE_VERSION
47 
48   bad_weak_ptr::~bad_weak_ptr() noexcept = default;
49 
50   char const*
what() const51   bad_weak_ptr::what() const noexcept
52   { return "bad_weak_ptr"; }
53 
54 #ifdef __GTHREADS
55   namespace
56   {
key(const void * addr)57     inline unsigned char key(const void* addr)
58     { return _Hash_impl::hash(addr) & __gnu_internal::mask; }
59   }
60 
_Sp_locker(const void * p)61   _Sp_locker::_Sp_locker(const void* p) noexcept
62   {
63     if (__gthread_active_p())
64       {
65 	_M_key1 = _M_key2 = key(p);
66         __gnu_internal::get_mutex(_M_key1).lock();
67       }
68     else
69       _M_key1 = _M_key2 = __gnu_internal::invalid;
70   }
71 
_Sp_locker(const void * p1,const void * p2)72   _Sp_locker::_Sp_locker(const void* p1, const void* p2) noexcept
73   {
74     if (__gthread_active_p())
75       {
76 	_M_key1 = key(p1);
77 	_M_key2 = key(p2);
78 	if (_M_key2 < _M_key1)
79 	  __gnu_internal::get_mutex(_M_key2).lock();
80 	__gnu_internal::get_mutex(_M_key1).lock();
81 	if (_M_key2 > _M_key1)
82 	  __gnu_internal::get_mutex(_M_key2).lock();
83       }
84     else
85       _M_key1 = _M_key2 = __gnu_internal::invalid;
86   }
87 
~_Sp_locker()88   _Sp_locker::~_Sp_locker()
89   {
90     if (_M_key1 != __gnu_internal::invalid)
91       {
92 	__gnu_internal::get_mutex(_M_key1).unlock();
93 	if (_M_key2 != _M_key1)
94 	  __gnu_internal::get_mutex(_M_key2).unlock();
95       }
96   }
97 #endif
98 
99   bool
_S_eq(const type_info & ti)100   _Sp_make_shared_tag::_S_eq(const type_info& ti [[gnu::unused]]) noexcept
101   {
102 #if __cpp_rtti
103     return ti == typeid(_Sp_make_shared_tag);
104 #else
105     // If libstdc++ itself is built with -fno-rtti then just assume that
106     // make_shared and allocate_shared will never be used with -frtti.
107     return false;
108 #endif
109   }
110 
111 _GLIBCXX_END_NAMESPACE_VERSION
112 } // namespace
113