123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- /////////////////////////////////////////////////////////////////////////////
- //
- // (C) Copyright Ion Gaztanaga 2007-2013
- //
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //
- // See http://www.boost.org/libs/intrusive for documentation.
- //
- /////////////////////////////////////////////////////////////////////////////
- #ifndef BOOST_INTRUSIVE_GENERIC_HOOK_HPP
- #define BOOST_INTRUSIVE_GENERIC_HOOK_HPP
- #ifndef BOOST_CONFIG_HPP
- # include <boost/config.hpp>
- #endif
- #if defined(BOOST_HAS_PRAGMA_ONCE)
- # pragma once
- #endif
- #include <boost/intrusive/pointer_traits.hpp>
- #include <boost/intrusive/link_mode.hpp>
- #include <boost/intrusive/detail/mpl.hpp>
- #include <boost/intrusive/detail/assert.hpp>
- #include <boost/intrusive/detail/node_holder.hpp>
- #include <boost/intrusive/detail/algo_type.hpp>
- #include <boost/static_assert.hpp>
- namespace boost {
- namespace intrusive {
- /// @cond
- namespace detail {
- template <link_mode_type LinkMode>
- struct link_dispatch
- {};
- template<class Hook>
- void destructor_impl(Hook &hook, detail::link_dispatch<safe_link>)
- { //If this assertion raises, you might have destroyed an object
- //while it was still inserted in a container that is alive.
- //If so, remove the object from the container before destroying it.
- (void)hook; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!hook.is_linked());
- }
- template<class Hook>
- void destructor_impl(Hook &hook, detail::link_dispatch<auto_unlink>)
- { hook.unlink(); }
- template<class Hook>
- void destructor_impl(Hook &, detail::link_dispatch<normal_link>)
- {}
- } //namespace detail {
- enum base_hook_type
- { NoBaseHookId
- , ListBaseHookId
- , SlistBaseHookId
- , RbTreeBaseHookId
- , HashBaseHookId
- , AvlTreeBaseHookId
- , BsTreeBaseHookId
- , TreapTreeBaseHookId
- , AnyBaseHookId
- };
- template <class HookTags, unsigned int>
- struct hook_tags_definer{};
- template <class HookTags>
- struct hook_tags_definer<HookTags, ListBaseHookId>
- { typedef HookTags default_list_hook; };
- template <class HookTags>
- struct hook_tags_definer<HookTags, SlistBaseHookId>
- { typedef HookTags default_slist_hook; };
- template <class HookTags>
- struct hook_tags_definer<HookTags, RbTreeBaseHookId>
- { typedef HookTags default_rbtree_hook; };
- template <class HookTags>
- struct hook_tags_definer<HookTags, HashBaseHookId>
- { typedef HookTags default_hashtable_hook; };
- template <class HookTags>
- struct hook_tags_definer<HookTags, AvlTreeBaseHookId>
- { typedef HookTags default_avltree_hook; };
- template <class HookTags>
- struct hook_tags_definer<HookTags, BsTreeBaseHookId>
- { typedef HookTags default_bstree_hook; };
- template <class HookTags>
- struct hook_tags_definer<HookTags, AnyBaseHookId>
- { typedef HookTags default_any_hook; };
- template
- < class NodeTraits
- , class Tag
- , link_mode_type LinkMode
- , base_hook_type BaseHookType
- >
- struct hooktags_impl
- {
- static const link_mode_type link_mode = LinkMode;
- typedef Tag tag;
- typedef NodeTraits node_traits;
- static const bool is_base_hook = !detail::is_same<Tag, member_tag>::value;
- static const bool safemode_or_autounlink = is_safe_autounlink<link_mode>::value;
- static const unsigned int type = BaseHookType;
- };
- /// @endcond
- template
- < boost::intrusive::algo_types Algo
- , class NodeTraits
- , class Tag
- , link_mode_type LinkMode
- , base_hook_type BaseHookType
- >
- class generic_hook
- /// @cond
- //If the hook is a base hook, derive generic hook from node_holder
- //so that a unique base class is created to convert from the node
- //to the type. This mechanism will be used by bhtraits.
- //
- //If the hook is a member hook, generic hook will directly derive
- //from the hook.
- : public detail::if_c
- < detail::is_same<Tag, member_tag>::value
- , typename NodeTraits::node
- , node_holder<typename NodeTraits::node, Tag, BaseHookType>
- >::type
- //If this is the a default-tagged base hook derive from a class that
- //will define an special internal typedef. Containers will be able to detect this
- //special typedef and obtain generic_hook's internal types in order to deduce
- //value_traits for this hook.
- , public hook_tags_definer
- < generic_hook<Algo, NodeTraits, Tag, LinkMode, BaseHookType>
- , detail::is_same<Tag, dft_tag>::value ? BaseHookType : NoBaseHookId>
- /// @endcond
- {
- /// @cond
- typedef typename get_algo<Algo, NodeTraits>::type node_algorithms;
- typedef typename node_algorithms::node node;
- typedef typename node_algorithms::node_ptr node_ptr;
- typedef typename node_algorithms::const_node_ptr const_node_ptr;
- public:
- typedef hooktags_impl
- < NodeTraits
- , Tag, LinkMode, BaseHookType> hooktags;
- BOOST_INTRUSIVE_FORCEINLINE node_ptr this_ptr()
- { return pointer_traits<node_ptr>::pointer_to(static_cast<node&>(*this)); }
- BOOST_INTRUSIVE_FORCEINLINE const_node_ptr this_ptr() const
- { return pointer_traits<const_node_ptr>::pointer_to(static_cast<const node&>(*this)); }
- public:
- /// @endcond
- BOOST_INTRUSIVE_FORCEINLINE generic_hook()
- {
- if(hooktags::safemode_or_autounlink){
- node_algorithms::init(this->this_ptr());
- }
- }
- BOOST_INTRUSIVE_FORCEINLINE generic_hook(const generic_hook& )
- {
- if(hooktags::safemode_or_autounlink){
- node_algorithms::init(this->this_ptr());
- }
- }
- BOOST_INTRUSIVE_FORCEINLINE generic_hook& operator=(const generic_hook& )
- { return *this; }
- BOOST_INTRUSIVE_FORCEINLINE ~generic_hook()
- {
- destructor_impl
- (*this, detail::link_dispatch<hooktags::link_mode>());
- }
- BOOST_INTRUSIVE_FORCEINLINE void swap_nodes(generic_hook &other)
- {
- node_algorithms::swap_nodes
- (this->this_ptr(), other.this_ptr());
- }
- BOOST_INTRUSIVE_FORCEINLINE bool is_linked() const
- {
- //is_linked() can be only used in safe-mode or auto-unlink
- BOOST_STATIC_ASSERT(( hooktags::safemode_or_autounlink ));
- return !node_algorithms::unique(this->this_ptr());
- }
- BOOST_INTRUSIVE_FORCEINLINE void unlink()
- {
- BOOST_STATIC_ASSERT(( (int)hooktags::link_mode == (int)auto_unlink ));
- node_ptr n(this->this_ptr());
- if(!node_algorithms::inited(n)){
- node_algorithms::unlink(n);
- node_algorithms::init(n);
- }
- }
- };
- } //namespace intrusive
- } //namespace boost
- #endif //BOOST_INTRUSIVE_GENERIC_HOOK_HPP
|