xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/profile/unordered_base.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj // Profiling unordered containers implementation details -*- C++ -*-
2*38fd1498Szrj 
3*38fd1498Szrj // Copyright (C) 2013-2018 Free Software Foundation, Inc.
4*38fd1498Szrj //
5*38fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
6*38fd1498Szrj // software; you can redistribute it and/or modify it under the
7*38fd1498Szrj // terms of the GNU General Public License as published by the
8*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj // any later version.
10*38fd1498Szrj //
11*38fd1498Szrj // This library is distributed in the hope that it will be useful,
12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*38fd1498Szrj // GNU General Public License for more details.
15*38fd1498Szrj 
16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj // 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj 
20*38fd1498Szrj // You should have received a copy of the GNU General Public License along
21*38fd1498Szrj // with this library; see the file COPYING3.  If not see
22*38fd1498Szrj // <http://www.gnu.org/licenses/>.
23*38fd1498Szrj 
24*38fd1498Szrj /** @file profile/unordered_base.h
25*38fd1498Szrj  *  This file is a GNU profile extension to the Standard C++ Library.
26*38fd1498Szrj  */
27*38fd1498Szrj 
28*38fd1498Szrj #ifndef _GLIBCXX_PROFILE_UNORDERED
29*38fd1498Szrj #define _GLIBCXX_PROFILE_UNORDERED 1
30*38fd1498Szrj 
_GLIBCXX_VISIBILITY(default)31*38fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
32*38fd1498Szrj {
33*38fd1498Szrj namespace __profile
34*38fd1498Szrj {
35*38fd1498Szrj   template<typename _UnorderedCont,
36*38fd1498Szrj 	   typename _Value, bool _Cache_hash_code>
37*38fd1498Szrj     struct _Bucket_index_helper;
38*38fd1498Szrj 
39*38fd1498Szrj   template<typename _UnorderedCont, typename _Value>
40*38fd1498Szrj     struct _Bucket_index_helper<_UnorderedCont, _Value, true>
41*38fd1498Szrj     {
42*38fd1498Szrj       static std::size_t
43*38fd1498Szrj       bucket(const _UnorderedCont& __uc,
44*38fd1498Szrj 	     const __detail::_Hash_node<_Value, true>* __node)
45*38fd1498Szrj       { return __node->_M_hash_code % __uc.bucket_count(); }
46*38fd1498Szrj     };
47*38fd1498Szrj 
48*38fd1498Szrj   template<typename _UnorderedCont, typename _Value>
49*38fd1498Szrj     struct _Bucket_index_helper<_UnorderedCont, _Value, false>
50*38fd1498Szrj     {
51*38fd1498Szrj       static std::size_t
52*38fd1498Szrj       bucket(const _UnorderedCont& __uc,
53*38fd1498Szrj 	     const __detail::_Hash_node<_Value, false>* __node)
54*38fd1498Szrj       { return __uc.bucket(__node->_M_v()); }
55*38fd1498Szrj     };
56*38fd1498Szrj 
57*38fd1498Szrj   template<typename _UnorderedCont, typename _Key, typename _Mapped>
58*38fd1498Szrj     struct _Bucket_index_helper<_UnorderedCont,
59*38fd1498Szrj 				std::pair<const _Key, _Mapped>, false>
60*38fd1498Szrj     {
61*38fd1498Szrj       typedef std::pair<const _Key, _Mapped> _Value;
62*38fd1498Szrj 
63*38fd1498Szrj       static std::size_t
64*38fd1498Szrj       bucket(const _UnorderedCont& __uc,
65*38fd1498Szrj 	     const __detail::_Hash_node<_Value, false>* __node)
66*38fd1498Szrj       { return __uc.bucket(__node->_M_v().first); }
67*38fd1498Szrj     };
68*38fd1498Szrj 
69*38fd1498Szrj   template<typename _UnorderedCont, typename _Value, bool _Cache_hash_code>
70*38fd1498Szrj     std::size_t
71*38fd1498Szrj     __get_bucket_index(const _UnorderedCont& __uc,
72*38fd1498Szrj 		       const __detail::_Hash_node<_Value, _Cache_hash_code>* __node)
73*38fd1498Szrj     {
74*38fd1498Szrj       using __bucket_index_helper
75*38fd1498Szrj 	= _Bucket_index_helper<_UnorderedCont, _Value, _Cache_hash_code>;
76*38fd1498Szrj       return __bucket_index_helper::bucket(__uc, __node);
77*38fd1498Szrj     }
78*38fd1498Szrj 
79*38fd1498Szrj   template<typename _UnorderedCont,
80*38fd1498Szrj 	   typename _Value, bool _Cache_hash_code>
81*38fd1498Szrj     struct _Equal_helper;
82*38fd1498Szrj 
83*38fd1498Szrj   template<typename _UnorderedCont, typename _Value>
84*38fd1498Szrj     struct _Equal_helper<_UnorderedCont, _Value, true>
85*38fd1498Szrj     {
86*38fd1498Szrj       static std::size_t
87*38fd1498Szrj       are_equal(const _UnorderedCont& __uc,
88*38fd1498Szrj 		const __detail::_Hash_node<_Value, true>* __lhs,
89*38fd1498Szrj 		const __detail::_Hash_node<_Value, true>* __rhs)
90*38fd1498Szrj       {
91*38fd1498Szrj 	return __lhs->_M_hash_code == __rhs->_M_hash_code
92*38fd1498Szrj 	  && __uc.key_eq()(__lhs->_M_v(), __rhs->_M_v());
93*38fd1498Szrj       }
94*38fd1498Szrj     };
95*38fd1498Szrj 
96*38fd1498Szrj   template<typename _UnorderedCont,
97*38fd1498Szrj 	   typename _Value>
98*38fd1498Szrj     struct _Equal_helper<_UnorderedCont, _Value, false>
99*38fd1498Szrj     {
100*38fd1498Szrj       static std::size_t
101*38fd1498Szrj       are_equal(const _UnorderedCont& __uc,
102*38fd1498Szrj 		const __detail::_Hash_node<_Value, false>* __lhs,
103*38fd1498Szrj 		const __detail::_Hash_node<_Value, false>* __rhs)
104*38fd1498Szrj       { return __uc.key_eq()(__lhs->_M_v(), __rhs->_M_v()); }
105*38fd1498Szrj     };
106*38fd1498Szrj 
107*38fd1498Szrj   template<typename _UnorderedCont,
108*38fd1498Szrj 	   typename _Key, typename _Mapped>
109*38fd1498Szrj     struct _Equal_helper<_UnorderedCont, std::pair<const _Key, _Mapped>, true>
110*38fd1498Szrj     {
111*38fd1498Szrj       typedef std::pair<const _Key, _Mapped> _Value;
112*38fd1498Szrj 
113*38fd1498Szrj       static std::size_t
114*38fd1498Szrj       are_equal(const _UnorderedCont& __uc,
115*38fd1498Szrj 		const __detail::_Hash_node<_Value, true>* __lhs,
116*38fd1498Szrj 		const __detail::_Hash_node<_Value, true>* __rhs)
117*38fd1498Szrj       {
118*38fd1498Szrj 	return __lhs->_M_hash_code == __rhs->_M_hash_code
119*38fd1498Szrj 	  && __uc.key_eq()(__lhs->_M_v().first, __rhs->_M_v().first);
120*38fd1498Szrj       }
121*38fd1498Szrj     };
122*38fd1498Szrj 
123*38fd1498Szrj   template<typename _UnorderedCont,
124*38fd1498Szrj 	   typename _Key, typename _Mapped>
125*38fd1498Szrj     struct _Equal_helper<_UnorderedCont, std::pair<const _Key, _Mapped>, false>
126*38fd1498Szrj     {
127*38fd1498Szrj       typedef std::pair<const _Key, _Mapped> _Value;
128*38fd1498Szrj 
129*38fd1498Szrj       static std::size_t
130*38fd1498Szrj       are_equal(const _UnorderedCont& __uc,
131*38fd1498Szrj 		const __detail::_Hash_node<_Value, false>* __lhs,
132*38fd1498Szrj 		const __detail::_Hash_node<_Value, false>* __rhs)
133*38fd1498Szrj       { return __uc.key_eq()(__lhs->_M_v().first, __rhs->_M_v().first); }
134*38fd1498Szrj     };
135*38fd1498Szrj 
136*38fd1498Szrj   template<typename _UnorderedCont, typename _Value, bool _Cache_hash_code>
137*38fd1498Szrj     bool
138*38fd1498Szrj     __are_equal(const _UnorderedCont& __uc,
139*38fd1498Szrj 		const __detail::_Hash_node<_Value, _Cache_hash_code>* __lhs,
140*38fd1498Szrj 		const __detail::_Hash_node<_Value, _Cache_hash_code>* __rhs)
141*38fd1498Szrj   {
142*38fd1498Szrj     using __equal_helper
143*38fd1498Szrj       = _Equal_helper<_UnorderedCont, _Value, _Cache_hash_code>;
144*38fd1498Szrj     return __equal_helper::are_equal(__uc, __lhs, __rhs);
145*38fd1498Szrj   }
146*38fd1498Szrj 
147*38fd1498Szrj   template<typename _UnorderedCont, bool _Unique_keys>
148*38fd1498Szrj     class _Unordered_profile
149*38fd1498Szrj     {
150*38fd1498Szrj       _UnorderedCont&
151*38fd1498Szrj       _M_conjure()
152*38fd1498Szrj       { return *(static_cast<_UnorderedCont*>(this)); }
153*38fd1498Szrj 
154*38fd1498Szrj       using __unique_keys = std::integral_constant<bool, _Unique_keys>;
155*38fd1498Szrj 
156*38fd1498Szrj     protected:
157*38fd1498Szrj       _Unordered_profile() noexcept
158*38fd1498Szrj       { _M_profile_construct(); }
159*38fd1498Szrj 
160*38fd1498Szrj       _Unordered_profile(const _Unordered_profile&) noexcept
161*38fd1498Szrj 	: _Unordered_profile() { }
162*38fd1498Szrj 
163*38fd1498Szrj       _Unordered_profile(_Unordered_profile&& __other) noexcept
164*38fd1498Szrj 	: _Unordered_profile()
165*38fd1498Szrj       { _M_swap(__other); }
166*38fd1498Szrj 
167*38fd1498Szrj       ~_Unordered_profile()
168*38fd1498Szrj       { _M_profile_destruct(); }
169*38fd1498Szrj 
170*38fd1498Szrj       _Unordered_profile&
171*38fd1498Szrj       operator=(const _Unordered_profile&) noexcept
172*38fd1498Szrj       {
173*38fd1498Szrj 	// Assignment just reset profiling.
174*38fd1498Szrj 	_M_profile_destruct();
175*38fd1498Szrj 	_M_profile_construct();
176*38fd1498Szrj       }
177*38fd1498Szrj 
178*38fd1498Szrj       _Unordered_profile&
179*38fd1498Szrj       operator=(_Unordered_profile&& __other) noexcept
180*38fd1498Szrj       {
181*38fd1498Szrj 	// Take profiling of the moved instance...
182*38fd1498Szrj 	_M_swap(__other);
183*38fd1498Szrj 
184*38fd1498Szrj 	// ...and then reset other instance profiling.
185*38fd1498Szrj 	__other._M_profile_destruct();
186*38fd1498Szrj 	__other._M_profile_construct();
187*38fd1498Szrj       }
188*38fd1498Szrj 
189*38fd1498Szrj       void
190*38fd1498Szrj       _M_profile_construct() noexcept
191*38fd1498Szrj       {
192*38fd1498Szrj 	auto& __uc = _M_conjure();
193*38fd1498Szrj 	_M_size_info = __profcxx_hashtable_size_construct(__uc.bucket_count());
194*38fd1498Szrj 	_M_hashfunc_info = __profcxx_hash_func_construct();
195*38fd1498Szrj       }
196*38fd1498Szrj 
197*38fd1498Szrj       void
198*38fd1498Szrj       _M_profile_destruct() noexcept
199*38fd1498Szrj       {
200*38fd1498Szrj 	auto& __uc = _M_conjure();
201*38fd1498Szrj 	__profcxx_hashtable_size_destruct(_M_size_info,
202*38fd1498Szrj 					  __uc.bucket_count(), __uc.size());
203*38fd1498Szrj 	_M_size_info = 0;
204*38fd1498Szrj 
205*38fd1498Szrj 	if (!_M_hashfunc_info)
206*38fd1498Szrj 	  return;
207*38fd1498Szrj 
208*38fd1498Szrj 	_M_profile_destruct(__unique_keys());
209*38fd1498Szrj 	_M_hashfunc_info = 0;
210*38fd1498Szrj       }
211*38fd1498Szrj 
212*38fd1498Szrj       void
213*38fd1498Szrj       _M_swap(_Unordered_profile& __other) noexcept
214*38fd1498Szrj       {
215*38fd1498Szrj 	std::swap(_M_size_info, __other._M_size_info);
216*38fd1498Szrj 	std::swap(_M_hashfunc_info, __other._M_hashfunc_info);
217*38fd1498Szrj       }
218*38fd1498Szrj 
219*38fd1498Szrj       void
220*38fd1498Szrj       _M_profile_resize(std::size_t __old_size)
221*38fd1498Szrj       {
222*38fd1498Szrj 	auto __new_size = _M_conjure().bucket_count();
223*38fd1498Szrj 	if (__old_size != __new_size)
224*38fd1498Szrj 	  __profcxx_hashtable_size_resize(_M_size_info, __old_size, __new_size);
225*38fd1498Szrj       }
226*38fd1498Szrj 
227*38fd1498Szrj       __gnu_profile::__container_size_info* _M_size_info;
228*38fd1498Szrj       __gnu_profile::__hashfunc_info* _M_hashfunc_info;
229*38fd1498Szrj 
230*38fd1498Szrj     private:
231*38fd1498Szrj       void
232*38fd1498Szrj       _M_profile_destruct(std::true_type);
233*38fd1498Szrj 
234*38fd1498Szrj       void
235*38fd1498Szrj       _M_profile_destruct(std::false_type);
236*38fd1498Szrj     };
237*38fd1498Szrj 
238*38fd1498Szrj   template<typename _UnorderedCont, bool _Unique_keys>
239*38fd1498Szrj     void
240*38fd1498Szrj     _Unordered_profile<_UnorderedCont, _Unique_keys>::
241*38fd1498Szrj     _M_profile_destruct(std::true_type)
242*38fd1498Szrj     {
243*38fd1498Szrj       auto& __uc = _M_conjure();
244*38fd1498Szrj       std::size_t __hops = 0, __lc = 0, __chain = 0;
245*38fd1498Szrj       auto __it = __uc.begin();
246*38fd1498Szrj       while (__it != __uc.end())
247*38fd1498Szrj 	{
248*38fd1498Szrj 	  auto __bkt = __get_bucket_index(__uc, __it._M_cur);
249*38fd1498Szrj 	  auto __lit = __uc.begin(__bkt);
250*38fd1498Szrj 	  auto __lend = __uc.end(__bkt);
251*38fd1498Szrj 	  for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit)
252*38fd1498Szrj 	    ++__chain;
253*38fd1498Szrj 
254*38fd1498Szrj 	  if (__chain)
255*38fd1498Szrj 	    {
256*38fd1498Szrj 	      ++__chain;
257*38fd1498Szrj 	      __lc = __lc > __chain ? __lc : __chain;
258*38fd1498Szrj 	      __hops += __chain * (__chain - 1) / 2;
259*38fd1498Szrj 	      __chain = 0;
260*38fd1498Szrj 	    }
261*38fd1498Szrj 	}
262*38fd1498Szrj 
263*38fd1498Szrj       __profcxx_hash_func_destruct(_M_hashfunc_info,
264*38fd1498Szrj 				   __lc, __uc.size(), __hops);
265*38fd1498Szrj     }
266*38fd1498Szrj 
267*38fd1498Szrj   template<typename _UnorderedCont, bool _Unique_keys>
268*38fd1498Szrj     void
269*38fd1498Szrj     _Unordered_profile<_UnorderedCont, _Unique_keys>::
270*38fd1498Szrj     _M_profile_destruct(std::false_type)
271*38fd1498Szrj     {
272*38fd1498Szrj       auto& __uc = _M_conjure();
273*38fd1498Szrj       std::size_t __hops = 0, __lc = 0, __chain = 0, __unique_size = 0;
274*38fd1498Szrj       auto __it = __uc.begin();
275*38fd1498Szrj       while (__it != __uc.end())
276*38fd1498Szrj 	{
277*38fd1498Szrj 	  auto __bkt = __get_bucket_index(__uc, __it._M_cur);
278*38fd1498Szrj 	  auto __lit = __uc.begin(__bkt);
279*38fd1498Szrj 	  auto __lend = __uc.end(__bkt);
280*38fd1498Szrj 	  auto __pit = __it;
281*38fd1498Szrj 	  ++__unique_size;
282*38fd1498Szrj 	  for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit)
283*38fd1498Szrj 	    {
284*38fd1498Szrj 	      if (!__are_equal(__uc, __pit._M_cur, __it._M_cur))
285*38fd1498Szrj 		{
286*38fd1498Szrj 		  ++__chain;
287*38fd1498Szrj 		  ++__unique_size;
288*38fd1498Szrj 		  __pit = __it;
289*38fd1498Szrj 		}
290*38fd1498Szrj 	    }
291*38fd1498Szrj 
292*38fd1498Szrj 	  if (__chain)
293*38fd1498Szrj 	    {
294*38fd1498Szrj 	      ++__chain;
295*38fd1498Szrj 	      __lc = __lc > __chain ? __lc : __chain;
296*38fd1498Szrj 	      __hops += __chain * (__chain - 1) / 2;
297*38fd1498Szrj 	      __chain = 0;
298*38fd1498Szrj 	    }
299*38fd1498Szrj 	}
300*38fd1498Szrj 
301*38fd1498Szrj       __profcxx_hash_func_destruct(_M_hashfunc_info,
302*38fd1498Szrj 				   __lc, __unique_size, __hops);
303*38fd1498Szrj     }
304*38fd1498Szrj 
305*38fd1498Szrj } // namespace __profile
306*38fd1498Szrj } // namespace std
307*38fd1498Szrj 
308*38fd1498Szrj #endif
309