Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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