generic_hook.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2007-2013
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // See http://www.boost.org/libs/intrusive for documentation.
  10. //
  11. /////////////////////////////////////////////////////////////////////////////
  12. #ifndef BOOST_INTRUSIVE_GENERIC_HOOK_HPP
  13. #define BOOST_INTRUSIVE_GENERIC_HOOK_HPP
  14. #ifndef BOOST_CONFIG_HPP
  15. # include <boost/config.hpp>
  16. #endif
  17. #if defined(BOOST_HAS_PRAGMA_ONCE)
  18. # pragma once
  19. #endif
  20. #include <boost/intrusive/pointer_traits.hpp>
  21. #include <boost/intrusive/link_mode.hpp>
  22. #include <boost/intrusive/detail/mpl.hpp>
  23. #include <boost/intrusive/detail/assert.hpp>
  24. #include <boost/intrusive/detail/node_holder.hpp>
  25. #include <boost/intrusive/detail/algo_type.hpp>
  26. namespace boost {
  27. namespace intrusive {
  28. /// @cond
  29. namespace detail {
  30. template <link_mode_type LinkMode>
  31. struct link_dispatch
  32. {};
  33. template<class Hook>
  34. inline void destructor_impl(Hook &hook, detail::link_dispatch<safe_link>)
  35. { //If this assertion raises, you might have destroyed an object
  36. //while it was still inserted in a container that is alive.
  37. //If so, remove the object from the container before destroying it.
  38. (void)hook; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!hook.is_linked());
  39. }
  40. template<class Hook>
  41. inline void destructor_impl(Hook &hook, detail::link_dispatch<auto_unlink>)
  42. { hook.unlink(); }
  43. template<class Hook>
  44. inline void destructor_impl(Hook &, detail::link_dispatch<normal_link>)
  45. {}
  46. } //namespace detail {
  47. enum base_hook_type
  48. { NoBaseHookId
  49. , ListBaseHookId
  50. , SlistBaseHookId
  51. , RbTreeBaseHookId
  52. , HashBaseHookId
  53. , AvlTreeBaseHookId
  54. , BsTreeBaseHookId
  55. , TreapTreeBaseHookId
  56. , AnyBaseHookId
  57. };
  58. template <class HookTags, unsigned int>
  59. struct hook_tags_definer{};
  60. template <class HookTags>
  61. struct hook_tags_definer<HookTags, ListBaseHookId>
  62. { typedef HookTags default_list_hook; };
  63. template <class HookTags>
  64. struct hook_tags_definer<HookTags, SlistBaseHookId>
  65. { typedef HookTags default_slist_hook; };
  66. template <class HookTags>
  67. struct hook_tags_definer<HookTags, RbTreeBaseHookId>
  68. { typedef HookTags default_rbtree_hook; };
  69. template <class HookTags>
  70. struct hook_tags_definer<HookTags, HashBaseHookId>
  71. { typedef HookTags default_hashtable_hook; };
  72. template <class HookTags>
  73. struct hook_tags_definer<HookTags, AvlTreeBaseHookId>
  74. { typedef HookTags default_avltree_hook; };
  75. template <class HookTags>
  76. struct hook_tags_definer<HookTags, BsTreeBaseHookId>
  77. { typedef HookTags default_bstree_hook; };
  78. template <class HookTags>
  79. struct hook_tags_definer<HookTags, AnyBaseHookId>
  80. { typedef HookTags default_any_hook; };
  81. template
  82. < class NodeTraits
  83. , class Tag
  84. , link_mode_type LinkMode
  85. , base_hook_type BaseHookType
  86. >
  87. struct hooktags_impl
  88. {
  89. static const link_mode_type link_mode = LinkMode;
  90. typedef Tag tag;
  91. typedef NodeTraits node_traits;
  92. static const bool is_base_hook = !detail::is_same<Tag, member_tag>::value;
  93. static const bool safemode_or_autounlink = is_safe_autounlink<link_mode>::value;
  94. static const unsigned int type = BaseHookType;
  95. };
  96. /// @endcond
  97. template
  98. < boost::intrusive::algo_types Algo
  99. , class NodeTraits
  100. , class Tag
  101. , link_mode_type LinkMode
  102. , base_hook_type BaseHookType
  103. >
  104. class generic_hook
  105. /// @cond
  106. //If the hook is a base hook, derive generic hook from node_holder
  107. //so that a unique base class is created to convert from the node
  108. //to the type. This mechanism will be used by bhtraits.
  109. //
  110. //If the hook is a member hook, generic hook will directly derive
  111. //from the hook.
  112. : public detail::if_c
  113. < detail::is_same<Tag, member_tag>::value
  114. , typename NodeTraits::node
  115. , node_holder<typename NodeTraits::node, Tag, BaseHookType>
  116. >::type
  117. //If this is the a default-tagged base hook derive from a class that
  118. //will define an special internal typedef. Containers will be able to detect this
  119. //special typedef and obtain generic_hook's internal types in order to deduce
  120. //value_traits for this hook.
  121. , public hook_tags_definer
  122. < generic_hook<Algo, NodeTraits, Tag, LinkMode, BaseHookType>
  123. , detail::is_same<Tag, dft_tag>::value ? BaseHookType : NoBaseHookId>
  124. /// @endcond
  125. {
  126. /// @cond
  127. typedef typename get_algo<Algo, NodeTraits>::type node_algorithms;
  128. typedef typename node_algorithms::node node;
  129. typedef typename node_algorithms::node_ptr node_ptr;
  130. typedef typename node_algorithms::const_node_ptr const_node_ptr;
  131. public:
  132. typedef hooktags_impl
  133. < NodeTraits
  134. , Tag, LinkMode, BaseHookType> hooktags;
  135. inline node_ptr this_ptr() BOOST_NOEXCEPT
  136. { return pointer_traits<node_ptr>::pointer_to(static_cast<node&>(*this)); }
  137. inline const_node_ptr this_ptr() const BOOST_NOEXCEPT
  138. { return pointer_traits<const_node_ptr>::pointer_to(static_cast<const node&>(*this)); }
  139. public:
  140. /// @endcond
  141. inline generic_hook() BOOST_NOEXCEPT
  142. {
  143. if(hooktags::safemode_or_autounlink){
  144. node_algorithms::init(this->this_ptr());
  145. }
  146. }
  147. inline generic_hook(const generic_hook& ) BOOST_NOEXCEPT
  148. {
  149. if(hooktags::safemode_or_autounlink){
  150. node_algorithms::init(this->this_ptr());
  151. }
  152. }
  153. inline generic_hook& operator=(const generic_hook& ) BOOST_NOEXCEPT
  154. { return *this; }
  155. inline ~generic_hook()
  156. {
  157. destructor_impl
  158. (*this, detail::link_dispatch<hooktags::link_mode>());
  159. }
  160. inline void swap_nodes(generic_hook &other) BOOST_NOEXCEPT
  161. {
  162. node_algorithms::swap_nodes
  163. (this->this_ptr(), other.this_ptr());
  164. }
  165. inline bool is_linked() const BOOST_NOEXCEPT
  166. {
  167. //is_linked() can be only used in safe-mode or auto-unlink
  168. BOOST_INTRUSIVE_STATIC_ASSERT(( hooktags::safemode_or_autounlink ));
  169. return !node_algorithms::unique(this->this_ptr());
  170. }
  171. inline void unlink() BOOST_NOEXCEPT
  172. {
  173. BOOST_INTRUSIVE_STATIC_ASSERT(( (int)hooktags::link_mode == (int)auto_unlink ));
  174. node_ptr n(this->this_ptr());
  175. if(!node_algorithms::inited(n)){
  176. node_algorithms::unlink(n);
  177. node_algorithms::init(n);
  178. }
  179. }
  180. };
  181. } //namespace intrusive
  182. } //namespace boost
  183. #endif //BOOST_INTRUSIVE_GENERIC_HOOK_HPP