1 // Support for pointer abstractions -*- C++ -*-
2 
3 // Copyright (C) 2011-2018 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&
35   get_mutex(unsigned char i)
36   {
37     static __gnu_cxx::__mutex m[mask + 1];
38     return m[i];
39   }
40 }
41 
42 namespace std _GLIBCXX_VISIBILITY(default)
43 {
44 _GLIBCXX_BEGIN_NAMESPACE_VERSION
45 
46   bad_weak_ptr::~bad_weak_ptr() noexcept = default;
47 
48   char const*
49   bad_weak_ptr::what() const noexcept
50   { return "bad_weak_ptr"; }
51 
52 #ifdef __GTHREADS
53   namespace
54   {
55     inline unsigned char key(const void* addr)
56     { return _Hash_impl::hash(addr) & __gnu_internal::mask; }
57   }
58 
59   _Sp_locker::_Sp_locker(const void* p) noexcept
60   {
61     if (__gthread_active_p())
62       {
63 	_M_key1 = _M_key2 = key(p);
64         __gnu_internal::get_mutex(_M_key1).lock();
65       }
66     else
67       _M_key1 = _M_key2 = __gnu_internal::invalid;
68   }
69 
70   _Sp_locker::_Sp_locker(const void* p1, const void* p2) noexcept
71   {
72     if (__gthread_active_p())
73       {
74 	_M_key1 = key(p1);
75 	_M_key2 = key(p2);
76 	if (_M_key2 < _M_key1)
77 	  __gnu_internal::get_mutex(_M_key2).lock();
78 	__gnu_internal::get_mutex(_M_key1).lock();
79 	if (_M_key2 > _M_key1)
80 	  __gnu_internal::get_mutex(_M_key2).lock();
81       }
82     else
83       _M_key1 = _M_key2 = __gnu_internal::invalid;
84   }
85 
86   _Sp_locker::~_Sp_locker()
87   {
88     if (_M_key1 != __gnu_internal::invalid)
89       {
90 	__gnu_internal::get_mutex(_M_key1).unlock();
91 	if (_M_key2 != _M_key1)
92 	  __gnu_internal::get_mutex(_M_key2).unlock();
93       }
94   }
95 #endif
96 
97 _GLIBCXX_END_NAMESPACE_VERSION
98 } // namespace
99