You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
203 lines
5.4 KiB
203 lines
5.4 KiB
///////////////////////////////////////////////////////////////////////////// |
|
// |
|
// (C) Copyright Ion Gaztanaga 2007-2009 |
|
// |
|
// 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 |
|
|
|
#include <boost/intrusive/detail/config_begin.hpp> |
|
#include <boost/intrusive/intrusive_fwd.hpp> |
|
#include <boost/intrusive/detail/pointer_to_other.hpp> |
|
#include <boost/intrusive/link_mode.hpp> |
|
#include <boost/intrusive/detail/utilities.hpp> |
|
#include <boost/intrusive/detail/mpl.hpp> |
|
#include <boost/static_assert.hpp> |
|
|
|
namespace boost { |
|
namespace intrusive { |
|
namespace detail { |
|
|
|
/// @cond |
|
|
|
enum |
|
{ NoBaseHook |
|
, ListBaseHook |
|
, SlistBaseHook |
|
, SetBaseHook |
|
, UsetBaseHook |
|
, SplaySetBaseHook |
|
, AvlSetBaseHook |
|
, BsSetBaseHook |
|
, AnyBaseHook |
|
}; |
|
|
|
struct no_default_definer{}; |
|
|
|
template <class Hook, unsigned int> |
|
struct default_definer; |
|
|
|
template <class Hook> |
|
struct default_definer<Hook, ListBaseHook> |
|
{ typedef Hook default_list_hook; }; |
|
|
|
template <class Hook> |
|
struct default_definer<Hook, SlistBaseHook> |
|
{ typedef Hook default_slist_hook; }; |
|
|
|
template <class Hook> |
|
struct default_definer<Hook, SetBaseHook> |
|
{ typedef Hook default_set_hook; }; |
|
|
|
template <class Hook> |
|
struct default_definer<Hook, UsetBaseHook> |
|
{ typedef Hook default_uset_hook; }; |
|
|
|
template <class Hook> |
|
struct default_definer<Hook, SplaySetBaseHook> |
|
{ typedef Hook default_splay_set_hook; }; |
|
|
|
template <class Hook> |
|
struct default_definer<Hook, AvlSetBaseHook> |
|
{ typedef Hook default_avl_set_hook; }; |
|
|
|
template <class Hook> |
|
struct default_definer<Hook, BsSetBaseHook> |
|
{ typedef Hook default_bs_set_hook; }; |
|
|
|
template <class Hook> |
|
struct default_definer<Hook, AnyBaseHook> |
|
{ typedef Hook default_any_hook; }; |
|
|
|
template <class Hook, unsigned int BaseHookType> |
|
struct make_default_definer |
|
{ |
|
typedef typename detail::if_c |
|
< BaseHookType != 0 |
|
, default_definer<Hook, BaseHookType> |
|
, no_default_definer>::type type; |
|
}; |
|
|
|
template |
|
< class GetNodeAlgorithms |
|
, class Tag |
|
, link_mode_type LinkMode |
|
, int HookType |
|
> |
|
struct make_node_holder |
|
{ |
|
typedef typename detail::if_c |
|
<!detail::is_same<Tag, member_tag>::value |
|
, detail::node_holder |
|
< typename GetNodeAlgorithms::type::node |
|
, Tag |
|
, LinkMode |
|
, HookType> |
|
, typename GetNodeAlgorithms::type::node |
|
>::type type; |
|
}; |
|
|
|
/// @endcond |
|
|
|
template |
|
< class GetNodeAlgorithms |
|
, class Tag |
|
, link_mode_type LinkMode |
|
, int HookType |
|
> |
|
class generic_hook |
|
/// @cond |
|
|
|
//If the hook is a base hook, derive generic hook from detail::node_holder |
|
//so that a unique base class is created to convert from the node |
|
//to the type. This mechanism will be used by base_hook_traits. |
|
// |
|
//If the hook is a member hook, generic hook will directly derive |
|
//from the hook. |
|
: public make_default_definer |
|
< generic_hook<GetNodeAlgorithms, Tag, LinkMode, HookType> |
|
, detail::is_same<Tag, default_tag>::value*HookType |
|
>::type |
|
, public make_node_holder<GetNodeAlgorithms, Tag, LinkMode, HookType>::type |
|
/// @endcond |
|
{ |
|
/// @cond |
|
typedef typename GetNodeAlgorithms::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: |
|
struct boost_intrusive_tags |
|
{ |
|
static const int hook_type = HookType; |
|
static const link_mode_type link_mode = LinkMode; |
|
typedef Tag tag; |
|
typedef typename GetNodeAlgorithms::type::node_traits node_traits; |
|
static const bool is_base_hook = !detail::is_same<Tag, member_tag>::value; |
|
static const bool safemode_or_autounlink = |
|
(int)link_mode == (int)auto_unlink || (int)link_mode == (int)safe_link; |
|
}; |
|
|
|
public: |
|
/// @endcond |
|
|
|
generic_hook() |
|
{ |
|
if(boost_intrusive_tags::safemode_or_autounlink){ |
|
node_algorithms::init(static_cast<node*>(this)); |
|
} |
|
} |
|
|
|
generic_hook(const generic_hook& ) |
|
{ |
|
if(boost_intrusive_tags::safemode_or_autounlink){ |
|
node_algorithms::init(static_cast<node*>(this)); |
|
} |
|
} |
|
|
|
generic_hook& operator=(const generic_hook& ) |
|
{ return *this; } |
|
|
|
~generic_hook() |
|
{ |
|
destructor_impl |
|
(*this, detail::link_dispatch<boost_intrusive_tags::link_mode>()); |
|
} |
|
|
|
void swap_nodes(generic_hook &other) |
|
{ |
|
node_algorithms::swap_nodes |
|
( static_cast<node*>(this), static_cast<node*>(&other)); |
|
} |
|
|
|
bool is_linked() const |
|
{ |
|
//is_linked() can be only used in safe-mode or auto-unlink |
|
BOOST_STATIC_ASSERT(( boost_intrusive_tags::safemode_or_autounlink )); |
|
return !node_algorithms::unique |
|
(static_cast<const node*>(this)); |
|
} |
|
|
|
void unlink() |
|
{ |
|
BOOST_STATIC_ASSERT(( (int)boost_intrusive_tags::link_mode == (int)auto_unlink )); |
|
node_algorithms::unlink(static_cast<node*>(this)); |
|
node_algorithms::init(static_cast<node*>(this)); |
|
} |
|
}; |
|
|
|
} //namespace detail |
|
} //namespace intrusive |
|
} //namespace boost |
|
|
|
#include <boost/intrusive/detail/config_end.hpp> |
|
|
|
#endif //BOOST_INTRUSIVE_GENERIC_HOOK_HPP
|
|
|