generic_hook.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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/static_assert.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. 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. void destructor_impl(Hook &hook, detail::link_dispatch<auto_unlink>)
  42. { hook.unlink(); }
  43. template<class Hook>
  44. 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. < class NodeAlgorithms
  99. , class Tag
  100. , link_mode_type LinkMode
  101. , base_hook_type BaseHookType
  102. >
  103. class generic_hook
  104. /// @cond
  105. //If the hook is a base hook, derive generic hook from node_holder
  106. //so that a unique base class is created to convert from the node
  107. //to the type. This mechanism will be used by bhtraits.
  108. //
  109. //If the hook is a member hook, generic hook will directly derive
  110. //from the hook.
  111. : public detail::if_c
  112. < detail::is_same<Tag, member_tag>::value
  113. , typename NodeAlgorithms::node
  114. , node_holder<typename NodeAlgorithms::node, Tag, BaseHookType>
  115. >::type
  116. //If this is the a default-tagged base hook derive from a class that
  117. //will define an special internal typedef. Containers will be able to detect this
  118. //special typedef and obtain generic_hook's internal types in order to deduce
  119. //value_traits for this hook.
  120. , public hook_tags_definer
  121. < generic_hook<NodeAlgorithms, Tag, LinkMode, BaseHookType>
  122. , detail::is_same<Tag, dft_tag>::value*BaseHookType>
  123. /// @endcond
  124. {
  125. /// @cond
  126. typedef NodeAlgorithms node_algorithms;
  127. typedef typename node_algorithms::node node;
  128. typedef typename node_algorithms::node_ptr node_ptr;
  129. typedef typename node_algorithms::const_node_ptr const_node_ptr;
  130. public:
  131. typedef hooktags_impl
  132. < typename NodeAlgorithms::node_traits
  133. , Tag, LinkMode, BaseHookType> hooktags;
  134. node_ptr this_ptr()
  135. { return pointer_traits<node_ptr>::pointer_to(static_cast<node&>(*this)); }
  136. const_node_ptr this_ptr() const
  137. { return pointer_traits<const_node_ptr>::pointer_to(static_cast<const node&>(*this)); }
  138. public:
  139. /// @endcond
  140. generic_hook()
  141. {
  142. if(hooktags::safemode_or_autounlink){
  143. node_algorithms::init(this->this_ptr());
  144. }
  145. }
  146. generic_hook(const generic_hook& )
  147. {
  148. if(hooktags::safemode_or_autounlink){
  149. node_algorithms::init(this->this_ptr());
  150. }
  151. }
  152. generic_hook& operator=(const generic_hook& )
  153. { return *this; }
  154. ~generic_hook()
  155. {
  156. destructor_impl
  157. (*this, detail::link_dispatch<hooktags::link_mode>());
  158. }
  159. void swap_nodes(generic_hook &other)
  160. {
  161. node_algorithms::swap_nodes
  162. (this->this_ptr(), other.this_ptr());
  163. }
  164. bool is_linked() const
  165. {
  166. //is_linked() can be only used in safe-mode or auto-unlink
  167. BOOST_STATIC_ASSERT(( hooktags::safemode_or_autounlink ));
  168. return !node_algorithms::unique(this->this_ptr());
  169. }
  170. void unlink()
  171. {
  172. BOOST_STATIC_ASSERT(( (int)hooktags::link_mode == (int)auto_unlink ));
  173. node_ptr n(this->this_ptr());
  174. if(!node_algorithms::inited(n)){
  175. node_algorithms::unlink(n);
  176. node_algorithms::init(n);
  177. }
  178. }
  179. };
  180. } //namespace intrusive
  181. } //namespace boost
  182. #endif //BOOST_INTRUSIVE_GENERIC_HOOK_HPP