mirror of
https://github.com/boostorg/intrusive.git
synced 2025-05-09 23:03:56 +00:00
First inclusion
[SVN r37592]
This commit is contained in:
commit
fe23901b24
96
.gitattributes
vendored
Normal file
96
.gitattributes
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
* text=auto !eol svneol=native#text/plain
|
||||
*.gitattributes text svneol=native#text/plain
|
||||
|
||||
# Scriptish formats
|
||||
*.bat text svneol=native#text/plain
|
||||
*.bsh text svneol=native#text/x-beanshell
|
||||
*.cgi text svneol=native#text/plain
|
||||
*.cmd text svneol=native#text/plain
|
||||
*.js text svneol=native#text/javascript
|
||||
*.php text svneol=native#text/x-php
|
||||
*.pl text svneol=native#text/x-perl
|
||||
*.pm text svneol=native#text/x-perl
|
||||
*.py text svneol=native#text/x-python
|
||||
*.sh eol=lf svneol=LF#text/x-sh
|
||||
configure eol=lf svneol=LF#text/x-sh
|
||||
|
||||
# Image formats
|
||||
*.bmp binary svneol=unset#image/bmp
|
||||
*.gif binary svneol=unset#image/gif
|
||||
*.ico binary svneol=unset#image/ico
|
||||
*.jpeg binary svneol=unset#image/jpeg
|
||||
*.jpg binary svneol=unset#image/jpeg
|
||||
*.png binary svneol=unset#image/png
|
||||
*.tif binary svneol=unset#image/tiff
|
||||
*.tiff binary svneol=unset#image/tiff
|
||||
*.svg text svneol=native#image/svg%2Bxml
|
||||
|
||||
# Data formats
|
||||
*.pdf binary svneol=unset#application/pdf
|
||||
*.avi binary svneol=unset#video/avi
|
||||
*.doc binary svneol=unset#application/msword
|
||||
*.dsp text svneol=crlf#text/plain
|
||||
*.dsw text svneol=crlf#text/plain
|
||||
*.eps binary svneol=unset#application/postscript
|
||||
*.gz binary svneol=unset#application/gzip
|
||||
*.mov binary svneol=unset#video/quicktime
|
||||
*.mp3 binary svneol=unset#audio/mpeg
|
||||
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
|
||||
*.ps binary svneol=unset#application/postscript
|
||||
*.psd binary svneol=unset#application/photoshop
|
||||
*.rdf binary svneol=unset#text/rdf
|
||||
*.rss text svneol=unset#text/xml
|
||||
*.rtf binary svneol=unset#text/rtf
|
||||
*.sln text svneol=native#text/plain
|
||||
*.swf binary svneol=unset#application/x-shockwave-flash
|
||||
*.tgz binary svneol=unset#application/gzip
|
||||
*.vcproj text svneol=native#text/xml
|
||||
*.vcxproj text svneol=native#text/xml
|
||||
*.vsprops text svneol=native#text/xml
|
||||
*.wav binary svneol=unset#audio/wav
|
||||
*.xls binary svneol=unset#application/vnd.ms-excel
|
||||
*.zip binary svneol=unset#application/zip
|
||||
|
||||
# Text formats
|
||||
.htaccess text svneol=native#text/plain
|
||||
*.bbk text svneol=native#text/xml
|
||||
*.cmake text svneol=native#text/plain
|
||||
*.css text svneol=native#text/css
|
||||
*.dtd text svneol=native#text/xml
|
||||
*.htm text svneol=native#text/html
|
||||
*.html text svneol=native#text/html
|
||||
*.ini text svneol=native#text/plain
|
||||
*.log text svneol=native#text/plain
|
||||
*.mak text svneol=native#text/plain
|
||||
*.qbk text svneol=native#text/plain
|
||||
*.rst text svneol=native#text/plain
|
||||
*.sql text svneol=native#text/x-sql
|
||||
*.txt text svneol=native#text/plain
|
||||
*.xhtml text svneol=native#text/xhtml%2Bxml
|
||||
*.xml text svneol=native#text/xml
|
||||
*.xsd text svneol=native#text/xml
|
||||
*.xsl text svneol=native#text/xml
|
||||
*.xslt text svneol=native#text/xml
|
||||
*.xul text svneol=native#text/xul
|
||||
*.yml text svneol=native#text/plain
|
||||
boost-no-inspect text svneol=native#text/plain
|
||||
CHANGES text svneol=native#text/plain
|
||||
COPYING text svneol=native#text/plain
|
||||
INSTALL text svneol=native#text/plain
|
||||
Jamfile text svneol=native#text/plain
|
||||
Jamroot text svneol=native#text/plain
|
||||
Jamfile.v2 text svneol=native#text/plain
|
||||
Jamrules text svneol=native#text/plain
|
||||
Makefile* text svneol=native#text/plain
|
||||
README text svneol=native#text/plain
|
||||
TODO text svneol=native#text/plain
|
||||
|
||||
# Code formats
|
||||
*.c text svneol=native#text/plain
|
||||
*.cpp text svneol=native#text/plain
|
||||
*.h text svneol=native#text/plain
|
||||
*.hpp text svneol=native#text/plain
|
||||
*.ipp text svneol=native#text/plain
|
||||
*.tpp text svneol=native#text/plain
|
||||
*.jam text svneol=native#text/plain
|
||||
*.java text svneol=native#text/plain
|
319
include/boost/intrusive/circular_list_algorithms.hpp
Normal file
319
include/boost/intrusive/circular_list_algorithms.hpp
Normal file
@ -0,0 +1,319 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_CIRCULAR_LIST_ALGORITHMS_HPP
|
||||
#define BOOST_INTRUSIVE_CIRCULAR_LIST_ALGORITHMS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <iterator>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//! circular_list_algorithms provides basic algorithms to manipulate nodes
|
||||
//! forming a circular doubly linked list. An empty circular list is formed by a node
|
||||
//! whose pointers point to itself.
|
||||
//!
|
||||
//! circular_list_algorithms is configured with a NodeTraits class, which encapsulates the
|
||||
//! information about the node to be manipulated. NodeTraits must support the
|
||||
//! following interface:
|
||||
//!
|
||||
//! <b>Typedefs</b>:
|
||||
//!
|
||||
//! <tt>node</tt>: The type of the node that forms the circular list
|
||||
//!
|
||||
//! <tt>node_ptr</tt>: A pointer to a node
|
||||
//!
|
||||
//! <tt>const_node_ptr</tt>: A pointer to a const node
|
||||
//!
|
||||
//! <b>Static functions</b>:
|
||||
//!
|
||||
//! <tt>static node_ptr get_previous(const_node_ptr n);</tt>
|
||||
//!
|
||||
//! <tt>static void set_previous(node_ptr n, node_ptr prev);</tt>
|
||||
//!
|
||||
//! <tt>static node_ptr get_next(const_node_ptr n);</tt>
|
||||
//!
|
||||
//! <tt>static void set_next(node_ptr n, node_ptr next);</tt>
|
||||
template<class NodeTraits>
|
||||
class circular_list_algorithms
|
||||
{
|
||||
public:
|
||||
typedef typename NodeTraits::node_ptr node_ptr;
|
||||
typedef typename NodeTraits::const_node_ptr const_node_ptr;
|
||||
|
||||
//! <b>Effects</b>: Constructs an empty list, making this_node the only
|
||||
//! node of the circular list:
|
||||
//! <tt>NodeTraits::get_next(this_node) == NodeTraits::get_previous(this_node)
|
||||
//! == this_node</tt>.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void init(node_ptr this_node)
|
||||
{
|
||||
NodeTraits::set_next(this_node, this_node);
|
||||
NodeTraits::set_previous(this_node, this_node);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
|
||||
//! <tt>return NodeTraits::get_next(this_node) == this_node</tt>
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static bool unique(const_node_ptr this_node)
|
||||
{ return NodeTraits::get_next(this_node) == this_node; }
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the number of nodes in a circular list. If the circular list
|
||||
//! is empty, returns 1.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static std::size_t count(const_node_ptr this_node)
|
||||
{
|
||||
std::size_t result = 0;
|
||||
const_node_ptr p = this_node;
|
||||
do{
|
||||
p = NodeTraits::get_next(p);
|
||||
++result;
|
||||
}while (p != this_node);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Unlinks the node from the circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static node_ptr unlink(node_ptr this_node)
|
||||
{
|
||||
node_ptr next(NodeTraits::get_next(this_node));
|
||||
node_ptr prev(NodeTraits::get_previous(this_node));
|
||||
NodeTraits::set_next(prev, next);
|
||||
NodeTraits::set_previous(next, prev);
|
||||
return next;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
|
||||
//!
|
||||
//! <b>Effects</b>: Unlinks the node [b, e) from the circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void unlink(node_ptr b, node_ptr e)
|
||||
{
|
||||
if (b != e) {
|
||||
node_ptr prev(NodeTraits::get_previous(b));
|
||||
node_ptr next(NodeTraits::get_next(e));
|
||||
NodeTraits::set_previous(next, prev);
|
||||
NodeTraits::set_next(prev, next);
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: nxt_node must be a node of a circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Links this_node before nxt_node in the circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void link_before(node_ptr nxt_node, node_ptr this_node)
|
||||
{
|
||||
node_ptr prev(NodeTraits::get_previous(nxt_node));
|
||||
NodeTraits::set_previous(this_node, prev);
|
||||
NodeTraits::set_next(prev, this_node);
|
||||
NodeTraits::set_previous(nxt_node, this_node);
|
||||
NodeTraits::set_next(this_node, nxt_node);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: prev_node must be a node of a circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Links this_node after prev_node in the circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void link_after(node_ptr prev_node, node_ptr this_node)
|
||||
{
|
||||
node_ptr next(NodeTraits::get_next(prev_node));
|
||||
NodeTraits::set_previous(this_node, prev_node);
|
||||
NodeTraits::set_next(this_node, next);
|
||||
NodeTraits::set_previous(next, this_node);
|
||||
NodeTraits::set_next(prev_node, this_node);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: this_node and other_node must be nodes inserted
|
||||
//! in circular lists or be empty circular lists.
|
||||
//!
|
||||
//! <b>Effects</b>: Swaps the position of the nodes: this_node is inserted in
|
||||
//! other_nodes position in the second circular list and the other_node is inserted
|
||||
//! in this_node's position in the first circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void swap_nodes(node_ptr this_node, node_ptr other_node)
|
||||
{
|
||||
if (other_node == this_node)
|
||||
return;
|
||||
bool empty1 = unique(this_node);
|
||||
bool empty2 = unique(other_node);
|
||||
|
||||
node_ptr next_this(NodeTraits::get_next(this_node));
|
||||
node_ptr prev_this(NodeTraits::get_previous(this_node));
|
||||
node_ptr next_other(NodeTraits::get_next(other_node));
|
||||
node_ptr prev_other(NodeTraits::get_previous(other_node));
|
||||
|
||||
//Do the swap
|
||||
NodeTraits::set_next(this_node, next_other);
|
||||
NodeTraits::set_next(other_node, next_this);
|
||||
|
||||
NodeTraits::set_previous(this_node, prev_other);
|
||||
NodeTraits::set_previous(other_node, prev_this);
|
||||
|
||||
if (empty2){
|
||||
init(this_node);
|
||||
}
|
||||
else{
|
||||
NodeTraits::set_next(prev_other, this_node);
|
||||
NodeTraits::set_previous(next_other, this_node);
|
||||
}
|
||||
if (empty1){
|
||||
init(other_node);
|
||||
}
|
||||
else{
|
||||
NodeTraits::set_next(prev_this, other_node);
|
||||
NodeTraits::set_previous(next_this, other_node);
|
||||
}
|
||||
}
|
||||
/*
|
||||
//Watanabe version
|
||||
private:
|
||||
static void swap_prev(node_ptr this_node, node_ptr other_node)
|
||||
{
|
||||
node_ptr temp(NodeTraits::get_previous(this_node));
|
||||
NodeTraits::set_previous(this_node, NodeTraits::get_previous(other_node));
|
||||
NodeTraits::set_previous(other_node, temp);
|
||||
}
|
||||
static void swap_next(node_ptr this_node, node_ptr other_node)
|
||||
{
|
||||
node_ptr temp(NodeTraits::get_next(this_node));
|
||||
NodeTraits::set_next(this_node, NodeTraits::get_next(other_node));
|
||||
NodeTraits::set_next(other_node, temp);
|
||||
}
|
||||
|
||||
public:
|
||||
static void swap_nodes(node_ptr this_node, node_ptr other_node)
|
||||
{
|
||||
node_ptr next_this(NodeTraits::get_next(this_node));
|
||||
node_ptr prev_this(NodeTraits::get_previous(this_node));
|
||||
node_ptr next_other(NodeTraits::get_next(other_node));
|
||||
node_ptr prev_other(NodeTraits::get_previous(other_node));
|
||||
//these first two swaps must happen before the other two
|
||||
swap_prev(next_this, next_other);
|
||||
swap_next(prev_this, prev_other);
|
||||
swap_next(this_node, other_node);
|
||||
swap_prev(this_node, other_node);
|
||||
}
|
||||
*/
|
||||
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
|
||||
//! and p must be a node of a different circular list or may not be an iterator in
|
||||
// [b, e).
|
||||
//!
|
||||
//! <b>Effects</b>: Removes the nodes from [b, e) range from their circular list and inserts
|
||||
//! them before p in p's circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void transfer(node_ptr p, node_ptr b, node_ptr e)
|
||||
{
|
||||
if (b != e) {
|
||||
node_ptr prev_p(NodeTraits::get_previous(p));
|
||||
node_ptr prev_e(NodeTraits::get_previous(e));
|
||||
node_ptr prev_b(NodeTraits::get_previous(b));
|
||||
NodeTraits::set_next(prev_e, p);
|
||||
NodeTraits::set_previous(p, prev_e);
|
||||
NodeTraits::set_next(prev_b, e);
|
||||
NodeTraits::set_previous(e, prev_b);
|
||||
NodeTraits::set_next(prev_p, b);
|
||||
NodeTraits::set_previous(b, prev_p);
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: i must a node of a circular list
|
||||
//! and p must be a node of a different circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Removes the node i from its circular list and inserts
|
||||
//! it before p in p's circular list.
|
||||
//! If p == i or p == NodeTraits::get_next(i), this function is a null operation.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void transfer(node_ptr p, node_ptr i)
|
||||
{
|
||||
node_ptr n(NodeTraits::get_next(i));
|
||||
if(n != p && i != p){
|
||||
node_ptr prev_p(NodeTraits::get_previous(p));
|
||||
node_ptr prev_i(NodeTraits::get_previous(i));
|
||||
NodeTraits::set_next(prev_p, i);
|
||||
NodeTraits::set_previous(i, prev_p);
|
||||
NodeTraits::set_next(i, p);
|
||||
NodeTraits::set_previous(p, i);
|
||||
NodeTraits::set_previous(n, prev_i);
|
||||
NodeTraits::set_next(prev_i, n);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Reverses the order of elements in the list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: This function is linear time.
|
||||
static void reverse(node_ptr p)
|
||||
{
|
||||
node_ptr f(NodeTraits::get_next(p));
|
||||
node_ptr i(NodeTraits::get_next(f)), e(p);
|
||||
|
||||
while(i != e) {
|
||||
node_ptr n = i;
|
||||
i = NodeTraits::get_next(i);
|
||||
transfer(f, n, i);
|
||||
f = n;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_CIRCULAR_LIST_ALGORITHMS_HPP
|
291
include/boost/intrusive/circular_slist_algorithms.hpp
Normal file
291
include/boost/intrusive/circular_slist_algorithms.hpp
Normal file
@ -0,0 +1,291 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_CIRCULAR_SLIST_ALGORITHMS_HPP
|
||||
#define BOOST_INTRUSIVE_CIRCULAR_SLIST_ALGORITHMS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <iterator>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//! circular_slist_algorithms provides basic algorithms to manipulate nodes
|
||||
//! forming a circular singly linked list. An empty circular list is formed by a node
|
||||
//! whose pointer to the next node points to itself.
|
||||
//!
|
||||
//! circular_slist_algorithms is configured with a NodeTraits class, which capsulates the
|
||||
//! information about the node to be manipulated. NodeTraits must support the
|
||||
//! following interface:
|
||||
//!
|
||||
//! <b>Typedefs</b>:
|
||||
//!
|
||||
//! <tt>node</tt>: The type of the node that forms the circular list
|
||||
//!
|
||||
//! <tt>node_ptr</tt>: A pointer to a node
|
||||
//!
|
||||
//! <tt>const_node_ptr</tt>: A pointer to a const node
|
||||
//!
|
||||
//! <b>Static functions</b>:
|
||||
//!
|
||||
//! <tt>static node_ptr get_next(const_node_ptr n);</tt>
|
||||
//!
|
||||
//! <tt>static void set_next(node_ptr n, node_ptr next);</tt>
|
||||
template<class NodeTraits>
|
||||
class circular_slist_algorithms
|
||||
{
|
||||
public:
|
||||
typedef typename NodeTraits::node_ptr node_ptr;
|
||||
typedef typename NodeTraits::const_node_ptr const_node_ptr;
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the previous node of this_node in the circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static node_ptr get_previous_node(node_ptr this_node)
|
||||
{ return get_previous_node(this_node, this_node); }
|
||||
|
||||
|
||||
//! <b>Requires</b>: this_node and prev_init_node must be in the same circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the previous node of this_node in the circular list starting.
|
||||
//! the search from prev_init_node. The first node checked for equality
|
||||
//! is NodeTraits::get_next(prev_init_node).
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements between prev_init_node and this_node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node)
|
||||
{
|
||||
node_ptr p = prev_init_node;
|
||||
for( node_ptr p_next
|
||||
; this_node != (p_next = NodeTraits::get_next(p))
|
||||
; p = p_next){
|
||||
//empty
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the previous node of the previous node of this_node in the circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static node_ptr get_previous_previous_node(node_ptr this_node)
|
||||
{ return get_previous_previous_node(this_node, this_node); }
|
||||
|
||||
//! <b>Requires</b>: this_node and prev_prev_init_node must be in the same circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the previous node of the previous node of this_node in the
|
||||
//! circular list starting. the search from prev_init_node. The first node checked
|
||||
//! for equality is NodeTraits::get_next((NodeTraits::get_next(prev_prev_init_node)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static node_ptr get_previous_previous_node(node_ptr prev_prev_init_node, node_ptr this_node)
|
||||
{
|
||||
node_ptr p = prev_prev_init_node;
|
||||
node_ptr p_next = NodeTraits::get_next(p);
|
||||
node_ptr p_next_next = NodeTraits::get_next(p_next);
|
||||
while (this_node != p_next_next){
|
||||
p = p_next;
|
||||
p_next = p_next_next;
|
||||
p_next_next = NodeTraits::get_next(p_next);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Constructs an empty list, making this_node the only
|
||||
//! node of the circular list:
|
||||
//! <tt>NodeTraits::get_next(this_node) == NodeTraits::get_previous(this_node)
|
||||
//! == this_node</tt>.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void init(node_ptr this_node)
|
||||
{ NodeTraits::set_next(this_node, this_node); }
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
|
||||
//! <tt>return NodeTraits::get_next(this_node) == this_node</tt>
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static bool unique(const_node_ptr this_node)
|
||||
{ return NodeTraits::get_next(this_node) == this_node; }
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the number of nodes in a circular list. If the circular list
|
||||
//! is empty, returns 1.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static std::size_t count(const_node_ptr this_node)
|
||||
{
|
||||
std::size_t result = 0;
|
||||
const_node_ptr p = this_node;
|
||||
do{
|
||||
p = NodeTraits::get_next(p);
|
||||
++result;
|
||||
} while (p != this_node);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: prev_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Unlinks the next node of prev_node from the circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void unlink_after(node_ptr prev_node)
|
||||
{
|
||||
node_ptr this_node(NodeTraits::get_next(prev_node));
|
||||
NodeTraits::set_next(prev_node, NodeTraits::get_next(this_node));
|
||||
NodeTraits::set_next(this_node, this_node);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: nxt_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Unlinks the previous node of nxt_node from the circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the elements in the circular list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void unlink_before(node_ptr nxt_node)
|
||||
{
|
||||
node_ptr prev_to_erase(get_previous_previous_node(nxt_node));
|
||||
unlink_after(prev_to_erase);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Unlinks the node from the circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements in the circular list
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void unlink(node_ptr this_node)
|
||||
{ unlink_after(get_previous_node(this_node)); }
|
||||
|
||||
//! <b>Requires</b>: prev_node must be a node of a circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Links this_node after prev_node in the circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void link_after(node_ptr prev_node, node_ptr this_node)
|
||||
{
|
||||
NodeTraits::set_next(this_node, NodeTraits::get_next(prev_node));
|
||||
NodeTraits::set_next(prev_node, this_node);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: nxt_node must be a node of a circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Links this_node before nxt_node in the circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void link_before (node_ptr nxt_node, node_ptr this_node)
|
||||
{ link_after(get_previous_node(nxt_node), this_node); }
|
||||
|
||||
//! <b>Requires</b>: this_node and other_node must be nodes inserted
|
||||
//! in circular lists or be empty circular lists.
|
||||
//!
|
||||
//! <b>Effects</b>: Swaps the position of the nodes: this_node is inserted in
|
||||
//! other_nodes position in the second circular list and the other_node is inserted
|
||||
//! in this_node's position in the first circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to number of elements of both lists
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void swap_nodes(node_ptr this_node, node_ptr other_node)
|
||||
{
|
||||
if (other_node == this_node)
|
||||
return;
|
||||
bool empty1 = unique(this_node);
|
||||
bool empty2 = unique(other_node);
|
||||
node_ptr prev_this (get_previous_node(this_node));
|
||||
node_ptr prev_other(get_previous_node(other_node));
|
||||
|
||||
node_ptr this_next (NodeTraits::get_next(this_node));
|
||||
node_ptr other_next(NodeTraits::get_next(other_node));
|
||||
NodeTraits::set_next(this_node, other_next);
|
||||
NodeTraits::set_next(other_node, this_next);
|
||||
NodeTraits::set_next(empty1 ? other_node : prev_this, other_node);
|
||||
NodeTraits::set_next(empty2 ? this_node : prev_other, this_node);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
|
||||
//! and p must be a node of a different circular list.
|
||||
//!
|
||||
//! <b>Effects</b>: Removes the nodes from [b, e) range from their circular list and inserts
|
||||
//! them after p in p's circular list.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static void transfer_after(node_ptr p, node_ptr b, node_ptr e)
|
||||
{
|
||||
if (p != b && p != e) {
|
||||
node_ptr next_b = NodeTraits::get_next(b);
|
||||
node_ptr next_e = NodeTraits::get_next(e);
|
||||
node_ptr next_p = NodeTraits::get_next(p);
|
||||
NodeTraits::set_next(b, next_e);
|
||||
NodeTraits::set_next(e, next_p);
|
||||
NodeTraits::set_next(p, next_b);
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Reverses the order of elements in the list.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: This function is linear to the contained elements.
|
||||
static void reverse(node_ptr p)
|
||||
{
|
||||
node_ptr i = NodeTraits::get_next(p), e(p);
|
||||
for (;;) {
|
||||
node_ptr nxt(NodeTraits::get_next(i));
|
||||
if (nxt == e)
|
||||
break;
|
||||
transfer_after(e, i, nxt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_CIRCULAR_SLIST_ALGORITHMS_HPP
|
48
include/boost/intrusive/detail/config_begin.hpp
Normal file
48
include/boost/intrusive/detail/config_begin.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning (push)
|
||||
//
|
||||
//'function' : resolved overload was found by argument-dependent lookup
|
||||
//A function found by argument-dependent lookup (Koenig lookup) was eventually
|
||||
//chosen by overload resolution.
|
||||
//
|
||||
//In Visual C++ .NET and earlier compilers, a different function would have
|
||||
//been called. To pick the original function, use an explicitly qualified name.
|
||||
//
|
||||
|
||||
//warning C4275: non dll-interface class 'x' used as base for
|
||||
//dll-interface class 'Y'
|
||||
#pragma warning (disable : 4275)
|
||||
//warning C4251: 'x' : class 'y' needs to have dll-interface to
|
||||
//be used by clients of class 'z'
|
||||
#pragma warning (disable : 4251)
|
||||
#pragma warning (disable : 4675)
|
||||
#pragma warning (disable : 4996)
|
||||
#pragma warning (disable : 4503)
|
||||
#pragma warning (disable : 4284) // odd return type for operator->
|
||||
#pragma warning (disable : 4244) // possible loss of data
|
||||
#pragma warning (disable : 4521) ////Disable "multiple copy constructors specified"
|
||||
#pragma warning (disable : 4522)
|
||||
#pragma warning (disable : 4146)
|
||||
#pragma warning (disable : 4267) //conversion from 'X' to 'Y', possible loss of data
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
# pragma warn -8026 // shut up warning "cannot inline function because ..."
|
||||
# pragma warn -8027 // shut up warning "cannot inline function because ..."
|
||||
#endif
|
22
include/boost/intrusive/detail/config_end.hpp
Normal file
22
include/boost/intrusive/detail/config_end.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if defined _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
# pragma warn .8026
|
||||
# pragma warn .8027
|
||||
#endif
|
71
include/boost/intrusive/detail/ebo_holder.hpp
Normal file
71
include/boost/intrusive/detail/ebo_holder.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Joaquín M López Muñoz 2006-2007
|
||||
//
|
||||
// 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_DETAIL_EBO_HOLDER_HPP
|
||||
#define BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP
|
||||
|
||||
#include <boost/type_traits/is_empty.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
template<typename T, bool IsEmpty = false>
|
||||
class ebo_holder_impl
|
||||
{
|
||||
public:
|
||||
ebo_holder_impl(){}
|
||||
ebo_holder_impl(const T& t):t(t){}
|
||||
|
||||
T& get(){return t;}
|
||||
const T& get()const{return t;}
|
||||
|
||||
private:
|
||||
T t;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ebo_holder_impl<T, true>
|
||||
: private T
|
||||
{
|
||||
public:
|
||||
ebo_holder_impl(){}
|
||||
ebo_holder_impl(const T& t):T(t){}
|
||||
|
||||
T& get(){return *this;}
|
||||
const T& get()const{return *this;}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ebo_holder
|
||||
: public ebo_holder_impl<T,boost::is_empty<T>::value>
|
||||
{
|
||||
private:
|
||||
typedef ebo_holder_impl<T,boost::is_empty<T>::value> super;
|
||||
|
||||
public:
|
||||
ebo_holder(){}
|
||||
ebo_holder(const T& t):super(t){}
|
||||
|
||||
ebo_holder& operator=(const ebo_holder& x)
|
||||
{
|
||||
this->get()=x.get();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} //namespace detail {
|
||||
} //namespace intrusive {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP
|
205
include/boost/intrusive/detail/hashtable_node.hpp
Normal file
205
include/boost/intrusive/detail/hashtable_node.hpp
Normal file
@ -0,0 +1,205 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gazta<74>ga 2007
|
||||
//
|
||||
// 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_HASHTABLE_NODE_HPP
|
||||
#define BOOST_INTRUSIVE_HASHTABLE_NODE_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <iterator>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/circular_list_algorithms.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
template<int Dummy = 0>
|
||||
struct prime_list_holder
|
||||
{
|
||||
static const std::size_t prime_list[];
|
||||
static const std::size_t prime_list_size;
|
||||
};
|
||||
|
||||
template<int Dummy>
|
||||
const std::size_t prime_list_holder<Dummy>::prime_list[] = {
|
||||
53ul, 97ul, 193ul, 389ul, 769ul,
|
||||
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
|
||||
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
|
||||
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
|
||||
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
|
||||
1610612741ul, 3221225473ul, 4294967291ul };
|
||||
|
||||
template<int Dummy>
|
||||
const std::size_t prime_list_holder<Dummy>::prime_list_size
|
||||
= sizeof(prime_list)/sizeof(std::size_t);
|
||||
|
||||
template <class SlistImpl>
|
||||
struct bucket_type_impl
|
||||
: public SlistImpl
|
||||
{
|
||||
bucket_type_impl()
|
||||
{}
|
||||
|
||||
bucket_type_impl(const bucket_type_impl &)
|
||||
{}
|
||||
|
||||
bucket_type_impl &operator=(const bucket_type_impl&)
|
||||
{ SlistImpl::clear(); }
|
||||
|
||||
static typename std::iterator_traits
|
||||
<typename SlistImpl::const_iterator>::difference_type
|
||||
get_bucket_num
|
||||
( typename SlistImpl::const_iterator it
|
||||
, const bucket_type_impl<SlistImpl> &first_bucket
|
||||
, const bucket_type_impl<SlistImpl> &last_bucket)
|
||||
{
|
||||
typename SlistImpl::const_iterator
|
||||
first(first_bucket.cend()), last(last_bucket.cend());
|
||||
|
||||
//The end node is embedded in the singly linked list:
|
||||
//iterate until we reach it.
|
||||
while(!(first.pointed_node() <= it.pointed_node() &&
|
||||
it.pointed_node() <= last.pointed_node())){
|
||||
++it;
|
||||
}
|
||||
//Now get the bucket_type_impl from the iterator
|
||||
const bucket_type_impl &b = static_cast<const bucket_type_impl&>
|
||||
(SlistImpl::container_from_end_iterator(it));
|
||||
|
||||
//Now just calculate the index b has in the bucket array
|
||||
return &b - &first_bucket;
|
||||
}
|
||||
|
||||
static SlistImpl &bucket_to_slist(bucket_type_impl<SlistImpl> &b)
|
||||
{ return static_cast<SlistImpl &>(b); }
|
||||
|
||||
static const SlistImpl &bucket_to_slist(const bucket_type_impl<SlistImpl> &b)
|
||||
{ return static_cast<const SlistImpl &>(b); }
|
||||
};
|
||||
|
||||
template<class SlistImpl>
|
||||
struct bucket_info_impl
|
||||
{
|
||||
typedef typename boost::pointer_to_other
|
||||
< typename SlistImpl::pointer
|
||||
, bucket_type_impl<SlistImpl> >::type bucket_ptr;
|
||||
typedef typename SlistImpl::size_type size_type;
|
||||
bucket_ptr buckets_;
|
||||
size_type buckets_len_;
|
||||
};
|
||||
|
||||
template<class Value, class SlistImpl>
|
||||
class hashtable_iterator
|
||||
: public boost::iterator_facade
|
||||
< hashtable_iterator<Value, SlistImpl>
|
||||
, Value
|
||||
, boost::forward_traversal_tag
|
||||
, Value&
|
||||
, typename std::iterator_traits<typename SlistImpl::iterator>::difference_type
|
||||
>
|
||||
{
|
||||
typedef typename SlistImpl::iterator local_iterator;
|
||||
typedef typename SlistImpl::const_iterator const_local_iterator;
|
||||
typedef typename SlistImpl::value_traits::node_ptr node_ptr;
|
||||
typedef typename SlistImpl::value_traits::const_node_ptr const_node_ptr;
|
||||
|
||||
typedef bucket_type_impl<SlistImpl> bucket_type;
|
||||
typedef typename boost::pointer_to_other
|
||||
< typename SlistImpl::pointer, bucket_type>::type bucket_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
< typename SlistImpl::pointer, const bucket_type>::type const_bucket_ptr;
|
||||
typedef detail::bucket_info_impl<SlistImpl> bucket_info_t;
|
||||
typedef typename boost::pointer_to_other
|
||||
<bucket_ptr, bucket_info_t>::type bucket_info_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<bucket_ptr, const bucket_info_t>::type const_bucket_info_ptr;
|
||||
typedef typename SlistImpl::size_type size_type;
|
||||
struct enabler {};
|
||||
|
||||
public:
|
||||
hashtable_iterator ()
|
||||
{}
|
||||
|
||||
explicit hashtable_iterator(local_iterator ptr, const_bucket_info_ptr bucket_info)
|
||||
: local_it_ (ptr), bucket_info_ (bucket_info)
|
||||
{}
|
||||
|
||||
template <class OtherValue>
|
||||
hashtable_iterator(hashtable_iterator<OtherValue, SlistImpl> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,Value*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: local_it_(other.local_it_), bucket_info_(other.bucket_info_)
|
||||
{}
|
||||
|
||||
const local_iterator &local() const
|
||||
{ return local_it_; }
|
||||
|
||||
const_node_ptr pointed_node() const
|
||||
{ return local_it_.pointed_node(); }
|
||||
|
||||
const const_bucket_info_ptr &bucket_info() const
|
||||
{ return bucket_info_; }
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
template <class, class> friend class hashtable_iterator;
|
||||
|
||||
template <class OtherValue>
|
||||
bool equal(hashtable_iterator<OtherValue, SlistImpl> const& other) const
|
||||
{ return other.local() == local_it_; }
|
||||
|
||||
void increment()
|
||||
{
|
||||
using boost::get_pointer;
|
||||
size_type buckets_len = bucket_info_->buckets_len_;
|
||||
const_bucket_ptr buckets = bucket_info_->buckets_;
|
||||
const_local_iterator first = bucket_type::bucket_to_slist(buckets[0]).cend();
|
||||
const_local_iterator last = bucket_type::bucket_to_slist(buckets[buckets_len]).cend();
|
||||
|
||||
++local_it_;
|
||||
if(first.pointed_node() <= local_it_.pointed_node() &&
|
||||
local_it_.pointed_node() <= last.pointed_node()){
|
||||
size_type n_bucket = (size_type)
|
||||
bucket_type::get_bucket_num(local_it_, buckets[0], buckets[buckets_len]);
|
||||
do{
|
||||
if (++n_bucket == buckets_len){
|
||||
local_it_ = bucket_info_->buckets_->end();
|
||||
break;
|
||||
}
|
||||
local_it_ = bucket_type::bucket_to_slist(bucket_info_->buckets_[n_bucket]).begin();
|
||||
}
|
||||
while (local_it_ == bucket_type::bucket_to_slist(bucket_info_->buckets_[n_bucket]).end());
|
||||
}
|
||||
}
|
||||
|
||||
Value& dereference() const
|
||||
{ return *local_it_; }
|
||||
|
||||
local_iterator local_it_;
|
||||
const_bucket_info_ptr bucket_info_;
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
} //namespace intrusive {
|
||||
} //namespace boost {
|
||||
|
||||
#endif
|
132
include/boost/intrusive/detail/list_node.hpp
Normal file
132
include/boost/intrusive/detail/list_node.hpp
Normal file
@ -0,0 +1,132 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_LIST_NODE_HPP
|
||||
#define BOOST_INTRUSIVE_LIST_NODE_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <iterator>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/circular_list_algorithms.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
// list_node_traits can be used with circular_list_algorithms and supplies
|
||||
// a list_node holding the pointers needed for a double-linked list
|
||||
// it is used by list_derived_node and list_member_node
|
||||
template<class VoidPointer>
|
||||
struct list_node_traits
|
||||
{
|
||||
struct node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
|
||||
struct node
|
||||
{
|
||||
node_ptr prev_, next_;
|
||||
};
|
||||
|
||||
static node_ptr get_previous(const_node_ptr n)
|
||||
{ return n->prev_; }
|
||||
|
||||
static void set_previous(node_ptr n, node_ptr prev)
|
||||
{ n->prev_ = prev; }
|
||||
|
||||
static node_ptr get_next(const_node_ptr n)
|
||||
{ return n->next_; }
|
||||
|
||||
static void set_next(node_ptr n, node_ptr next)
|
||||
{ n->next_ = next; }
|
||||
};
|
||||
|
||||
// list_iterator provides some basic functions for a
|
||||
// node oriented forward iterator:
|
||||
template<class T, class ValueTraits>
|
||||
class list_iterator
|
||||
: public boost::iterator_facade
|
||||
< list_iterator<T, ValueTraits>
|
||||
, T
|
||||
, boost::bidirectional_traversal_tag
|
||||
, T&
|
||||
, typename std::iterator_traits<typename ValueTraits::node_ptr>::difference_type
|
||||
>
|
||||
{
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
struct enabler{};
|
||||
|
||||
public:
|
||||
typedef typename pointer_to_other<typename ValueTraits::node_ptr, T>::type pointer;
|
||||
typedef typename std::iterator_traits<node_ptr>::difference_type difference_type;
|
||||
|
||||
list_iterator ()
|
||||
: node_ (0)
|
||||
{}
|
||||
|
||||
explicit list_iterator(node_ptr node)
|
||||
: node_ (node)
|
||||
{}
|
||||
|
||||
template <class OtherValue>
|
||||
list_iterator(list_iterator<OtherValue, ValueTraits> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,T*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
|
||||
const node_ptr &pointed_node() const
|
||||
{ return node_; }
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
template <class, class> friend class list_iterator;
|
||||
|
||||
template <class OtherValue>
|
||||
bool equal(list_iterator<OtherValue, ValueTraits> const& other) const
|
||||
{ return other.pointed_node() == node_; }
|
||||
|
||||
void increment()
|
||||
{ node_ = node_traits::get_next(node_); }
|
||||
|
||||
void decrement()
|
||||
{ node_ = node_traits::get_previous(node_); }
|
||||
|
||||
T& dereference() const
|
||||
{ return *ValueTraits::to_value_ptr(node_); }
|
||||
|
||||
node_ptr node_;
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_LIST_NODE_HPP
|
46
include/boost/intrusive/detail/parent_from_member.hpp
Normal file
46
include/boost/intrusive/detail/parent_from_member.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2007
|
||||
//
|
||||
// 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_PARENT_FROM_MEMBER_HPP
|
||||
#define BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
template<class Parent, class Member>
|
||||
std::size_t offset_from_pointer_to_member(const Member Parent::* ptr_to_member)
|
||||
{
|
||||
//This works with gcc and msvc
|
||||
return *(const std::size_t*)(const void*)&ptr_to_member;
|
||||
//Other compilers might need other transformation, depending how a
|
||||
//pointer to data member is implemented.
|
||||
}
|
||||
|
||||
template<class Parent, class Member>
|
||||
Parent *parent_from_member(Member *member, const Member Parent::* ptr_to_member)
|
||||
{
|
||||
return (Parent*)((char*)member -
|
||||
offset_from_pointer_to_member(ptr_to_member));
|
||||
}
|
||||
|
||||
template<class Parent, class Member>
|
||||
const Parent *parent_from_member(const Member *member, const Member Parent::* ptr_to_member)
|
||||
{
|
||||
return (const Parent*)((const char*)member -
|
||||
offset_from_pointer_to_member(ptr_to_member));
|
||||
}
|
||||
|
||||
} //namespace detail {
|
||||
} //namespace intrusive {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP
|
65
include/boost/intrusive/detail/pointer_to_other.hpp
Normal file
65
include/boost/intrusive/detail/pointer_to_other.hpp
Normal file
@ -0,0 +1,65 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2006. 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_POINTER_TO_OTHER_HPP
|
||||
#define BOOST_INTRUSIVE_POINTER_TO_OTHER_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#if (BOOST_VERSION < 103400)
|
||||
|
||||
#ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED
|
||||
#define BOOST_POINTER_TO_OTHER_HPP_INCLUDED
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<class T, class U>
|
||||
struct pointer_to_other;
|
||||
|
||||
template<class T, class U, template <class> class Sp>
|
||||
struct pointer_to_other< Sp<T>, U >
|
||||
{
|
||||
typedef Sp<U> type;
|
||||
};
|
||||
|
||||
template<class T, class T2, class U,
|
||||
template <class, class> class Sp>
|
||||
struct pointer_to_other< Sp<T, T2>, U >
|
||||
{
|
||||
typedef Sp<U, T2> type;
|
||||
};
|
||||
|
||||
template<class T, class T2, class T3, class U,
|
||||
template <class, class, class> class Sp>
|
||||
struct pointer_to_other< Sp<T, T2, T3>, U >
|
||||
{
|
||||
typedef Sp<U, T2, T3> type;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct pointer_to_other< T*, U >
|
||||
{
|
||||
typedef U* type;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_POINTER_TO_OTHER_HPP
|
54
include/boost/intrusive/detail/pointer_type.hpp
Normal file
54
include/boost/intrusive/detail/pointer_type.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2006. 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_POINTER_TYPE_HPP
|
||||
#define BOOST_INTRUSIVE_POINTER_TYPE_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
struct two {char _[2];};
|
||||
|
||||
namespace pointer_type_imp
|
||||
{
|
||||
|
||||
template <class U> static two test(...);
|
||||
template <class U> static char test(typename U::pointer* = 0);
|
||||
|
||||
} //namespace pointer_type_imp
|
||||
|
||||
template <class T>
|
||||
struct has_pointer_type
|
||||
{
|
||||
static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1;
|
||||
};
|
||||
|
||||
template <class T, class A, bool = has_pointer_type<A>::value>
|
||||
struct pointer_type
|
||||
{
|
||||
typedef typename A::pointer type;
|
||||
};
|
||||
|
||||
template <class T, class A>
|
||||
struct pointer_type<T, A, false>
|
||||
{
|
||||
typedef T* type;
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
} //namespace intrusive
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_POINTER_TYPE_HPP
|
257
include/boost/intrusive/detail/rbtree_node.hpp
Normal file
257
include/boost/intrusive/detail/rbtree_node.hpp
Normal file
@ -0,0 +1,257 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007.
|
||||
//
|
||||
// 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_RBTREE_NODE_HPP
|
||||
#define BOOST_INTRUSIVE_RBTREE_NODE_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <iterator>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/rbtree_algorithms.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <cstddef>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/intrusive/pointer_plus_bit.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Generic node_traits for any pointer type //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//This is the compact representation: 3 pointers
|
||||
template<class VoidPointer>
|
||||
struct compact_rbtree_node
|
||||
{
|
||||
typedef typename pointer_to_other
|
||||
<VoidPointer
|
||||
,compact_rbtree_node<VoidPointer> >::type node_ptr;
|
||||
enum color { red_t, black_t };
|
||||
node_ptr parent_, left_, right_;
|
||||
};
|
||||
|
||||
//This is the normal representation: 3 pointers + enum
|
||||
template<class VoidPointer>
|
||||
struct rbtree_node
|
||||
{
|
||||
typedef typename pointer_to_other
|
||||
<VoidPointer
|
||||
,rbtree_node<VoidPointer> >::type node_ptr;
|
||||
|
||||
enum color { red_t, black_t };
|
||||
node_ptr parent_, left_, right_;
|
||||
color color_;
|
||||
};
|
||||
|
||||
//This is the default node traits implementation
|
||||
//using a node with 3 generic pointers plus an enum
|
||||
template<class VoidPointer>
|
||||
struct default_rbtree_node_traits_impl
|
||||
{
|
||||
typedef rbtree_node<VoidPointer> node;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
|
||||
typedef typename node::color color;
|
||||
|
||||
static node_ptr get_parent(const_node_ptr n)
|
||||
{ return n->parent_; }
|
||||
|
||||
static void set_parent(node_ptr n, node_ptr p)
|
||||
{ n->parent_ = p; }
|
||||
|
||||
static node_ptr get_left(const_node_ptr n)
|
||||
{ return n->left_; }
|
||||
|
||||
static void set_left(node_ptr n, node_ptr l)
|
||||
{ n->left_ = l; }
|
||||
|
||||
static node_ptr get_right(const_node_ptr n)
|
||||
{ return n->right_; }
|
||||
|
||||
static void set_right(node_ptr n, node_ptr r)
|
||||
{ n->right_ = r; }
|
||||
|
||||
static color get_color(const_node_ptr n)
|
||||
{ return n->color_; }
|
||||
|
||||
static void set_color(node_ptr n, color c)
|
||||
{ n->color_ = c; }
|
||||
|
||||
static color black()
|
||||
{ return node::black_t; }
|
||||
|
||||
static color red()
|
||||
{ return node::red_t; }
|
||||
};
|
||||
|
||||
//This is the compact node traits implementation
|
||||
//using a node with 3 generic pointers
|
||||
template<class VoidPointer>
|
||||
struct compact_rbtree_node_traits_impl
|
||||
{
|
||||
typedef compact_rbtree_node<VoidPointer> node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
|
||||
typedef pointer_plus_bit<node_ptr> ptr_bit;
|
||||
|
||||
typedef typename node::color color;
|
||||
|
||||
static node_ptr get_parent(const_node_ptr n)
|
||||
{ return ptr_bit::get_pointer(n->parent_); }
|
||||
|
||||
static void set_parent(node_ptr n, node_ptr p)
|
||||
{ ptr_bit::set_pointer(n->parent_, p); }
|
||||
|
||||
static node_ptr get_left(const_node_ptr n)
|
||||
{ return n->left_; }
|
||||
|
||||
static void set_left(node_ptr n, node_ptr l)
|
||||
{ n->left_ = l; }
|
||||
|
||||
static node_ptr get_right(const_node_ptr n)
|
||||
{ return n->right_; }
|
||||
|
||||
static void set_right(node_ptr n, node_ptr r)
|
||||
{ n->right_ = r; }
|
||||
|
||||
static color get_color(const_node_ptr n)
|
||||
{ return (color)ptr_bit::get_bit(n->parent_); }
|
||||
|
||||
static void set_color(node_ptr n, color c)
|
||||
{ ptr_bit::set_bit(n->parent_, c != 0); }
|
||||
|
||||
static color black()
|
||||
{ return node::black_t; }
|
||||
|
||||
static color red()
|
||||
{ return node::red_t; }
|
||||
};
|
||||
|
||||
//Dispatches the implementation based on the boolean
|
||||
template<class VoidPointer, bool compact>
|
||||
struct rbtree_node_traits_dispatch
|
||||
: public default_rbtree_node_traits_impl<VoidPointer>
|
||||
{};
|
||||
|
||||
template<class VoidPointer>
|
||||
struct rbtree_node_traits_dispatch<VoidPointer, true>
|
||||
: public compact_rbtree_node_traits_impl<VoidPointer>
|
||||
{};
|
||||
|
||||
//Inherit from the dispatcher depending on the embedding capabilities
|
||||
template<class VoidPointer>
|
||||
struct rbtree_node_traits
|
||||
: public rbtree_node_traits_dispatch
|
||||
<VoidPointer
|
||||
,has_pointer_plus_bit
|
||||
< typename pointer_to_other
|
||||
<VoidPointer
|
||||
, compact_rbtree_node<VoidPointer>
|
||||
>::type
|
||||
>::value
|
||||
>
|
||||
{};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Implementation of the rbtree iterator //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T, class ValueTraits>
|
||||
class rbtree_iterator
|
||||
: public boost::iterator_facade
|
||||
< rbtree_iterator<T, ValueTraits>
|
||||
, T
|
||||
, boost::bidirectional_traversal_tag
|
||||
, T&
|
||||
, typename std::iterator_traits<typename ValueTraits::node_ptr>::difference_type
|
||||
>
|
||||
{
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef rbtree_algorithms<node_traits> node_algorithms;
|
||||
struct enabler{};
|
||||
|
||||
public:
|
||||
typedef typename pointer_to_other<typename ValueTraits::node_ptr, T>::type pointer;
|
||||
typedef typename std::iterator_traits<node_ptr>::difference_type difference_type;
|
||||
|
||||
rbtree_iterator ()
|
||||
: node_ (0)
|
||||
{}
|
||||
|
||||
explicit rbtree_iterator(node_ptr node)
|
||||
: node_ (node)
|
||||
{}
|
||||
|
||||
template <class OtherValue>
|
||||
rbtree_iterator(rbtree_iterator<OtherValue, ValueTraits> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,T*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
|
||||
const node_ptr &pointed_node() const
|
||||
{ return node_; }
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
template <class, class> friend class rbtree_iterator;
|
||||
|
||||
template <class OtherValue>
|
||||
bool equal(rbtree_iterator<OtherValue, ValueTraits> const& other) const
|
||||
{ return other.pointed_node() == node_; }
|
||||
|
||||
void increment()
|
||||
{ node_ = node_algorithms::next_node(node_); }
|
||||
|
||||
void decrement()
|
||||
{ node_ = node_algorithms::prev_node(node_); }
|
||||
|
||||
T& dereference() const
|
||||
{ return *ValueTraits::to_value_ptr(node_); }
|
||||
|
||||
node_ptr node_;
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_RBTREE_NODE_HPP
|
125
include/boost/intrusive/detail/slist_node.hpp
Normal file
125
include/boost/intrusive/detail/slist_node.hpp
Normal file
@ -0,0 +1,125 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_SLIST_NODE_HPP
|
||||
#define BOOST_INTRUSIVE_SLIST_NODE_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <iterator>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/circular_slist_algorithms.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
// slist_node_traits can be used with circular_slist_algorithms and supplies
|
||||
// a slist_node holding the pointers needed for a singly-linked list
|
||||
// it is used by slist_base_hook and slist_member_hook
|
||||
template<class VoidPointer>
|
||||
struct slist_node_traits
|
||||
{
|
||||
struct node;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
|
||||
struct node
|
||||
{
|
||||
node_ptr next_;
|
||||
};
|
||||
|
||||
static node_ptr get_next(const_node_ptr n)
|
||||
{ return n->next_; }
|
||||
|
||||
static void set_next(node_ptr n, node_ptr next)
|
||||
{ n->next_ = next; }
|
||||
};
|
||||
|
||||
|
||||
// slist_iterator provides some basic functions for a
|
||||
// node oriented forward iterator:
|
||||
template<class T, class ValueTraits>
|
||||
class slist_iterator
|
||||
: public boost::iterator_facade
|
||||
< slist_iterator<T, ValueTraits>
|
||||
, T
|
||||
, boost::forward_traversal_tag
|
||||
, T&
|
||||
, typename std::iterator_traits<typename ValueTraits::node_ptr>::difference_type
|
||||
>
|
||||
{
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
struct enabler{};
|
||||
|
||||
public:
|
||||
typedef typename pointer_to_other<typename ValueTraits::node_ptr, T>::type pointer;
|
||||
typedef typename std::iterator_traits<node_ptr>::difference_type difference_type;
|
||||
|
||||
slist_iterator ()
|
||||
: node_ (0)
|
||||
{}
|
||||
|
||||
explicit slist_iterator(node_ptr node)
|
||||
: node_ (node)
|
||||
{}
|
||||
|
||||
template <class OtherValue>
|
||||
slist_iterator(slist_iterator<OtherValue, ValueTraits> const& other
|
||||
,typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,T*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: node_(other.pointed_node())
|
||||
{}
|
||||
|
||||
const node_ptr &pointed_node() const
|
||||
{ return node_; }
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
template <class, class> friend class slist_iterator;
|
||||
|
||||
template <class OtherValue>
|
||||
bool equal(slist_iterator<OtherValue, ValueTraits> const& other) const
|
||||
{ return other.pointed_node() == node_; }
|
||||
|
||||
void increment()
|
||||
{ node_ = node_traits::get_next(node_); }
|
||||
|
||||
T& dereference() const
|
||||
{ return *ValueTraits::to_value_ptr(node_); }
|
||||
|
||||
node_ptr node_;
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_SLIST_NODE_HPP
|
293
include/boost/intrusive/detail/utilities.hpp
Normal file
293
include/boost/intrusive/detail/utilities.hpp
Normal file
@ -0,0 +1,293 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_DETAIL_UTILITIES_HPP
|
||||
#define BOOST_INTRUSIVE_DETAIL_UTILITIES_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/detail/parent_from_member.hpp>
|
||||
#include <boost/intrusive/detail/ebo_holder.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
//This functor compares a stored value
|
||||
//and the one passed as an argument
|
||||
template<class ConstReference>
|
||||
class equal_to_value
|
||||
{
|
||||
ConstReference t_;
|
||||
|
||||
public:
|
||||
equal_to_value(ConstReference t)
|
||||
: t_(t)
|
||||
{}
|
||||
|
||||
bool operator()(ConstReference t)const
|
||||
{ return t_ == t; }
|
||||
};
|
||||
|
||||
class null_destroyer
|
||||
{
|
||||
public:
|
||||
template <class Pointer>
|
||||
void operator()(Pointer)
|
||||
{}
|
||||
};
|
||||
|
||||
template<bool ConstantSize, class SizeType>
|
||||
struct size_holder
|
||||
{
|
||||
enum { constant_time_size = ConstantSize };
|
||||
typedef SizeType size_type;
|
||||
|
||||
SizeType get_size() const
|
||||
{ return size_; }
|
||||
|
||||
void set_size(SizeType size)
|
||||
{ size_ = size; }
|
||||
|
||||
void decrement()
|
||||
{ --size_; }
|
||||
|
||||
void increment()
|
||||
{ ++size_; }
|
||||
|
||||
SizeType size_;
|
||||
};
|
||||
|
||||
template<class SizeType>
|
||||
struct size_holder<false, SizeType>
|
||||
{
|
||||
enum { constant_time_size = false };
|
||||
typedef SizeType size_type;
|
||||
|
||||
size_type get_size() const
|
||||
{ return 0; }
|
||||
|
||||
void set_size(size_type)
|
||||
{}
|
||||
|
||||
void decrement()
|
||||
{}
|
||||
|
||||
void increment()
|
||||
{}
|
||||
};
|
||||
|
||||
template<class T, class DerivationHookType, typename Tag>
|
||||
struct derivation_value_traits
|
||||
{
|
||||
public:
|
||||
typedef typename DerivationHookType::node_traits node_traits;
|
||||
typedef T value_type;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef typename boost::pointer_to_other<node_ptr, T>::type pointer;
|
||||
typedef typename boost::pointer_to_other<node_ptr, const T>::type const_pointer;
|
||||
typedef typename std::iterator_traits<pointer>::reference reference;
|
||||
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
|
||||
enum { linking_policy = DerivationHookType::linking_policy };
|
||||
|
||||
static node_ptr to_node_ptr(reference value)
|
||||
{ return static_cast<DerivationHookType &>(value).to_node_ptr(); }
|
||||
|
||||
static const_node_ptr to_node_ptr(const_reference value)
|
||||
{ return static_cast<const DerivationHookType &>(value).to_node_ptr(); }
|
||||
|
||||
static pointer to_value_ptr(node_ptr n)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return static_cast<T*>(get_pointer(DerivationHookType::to_hook_ptr(n)));
|
||||
}
|
||||
|
||||
static const_pointer to_value_ptr(const_node_ptr n)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return static_cast<const T*>(get_pointer(DerivationHookType::to_hook_ptr(n)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class T, class MemberHookType, MemberHookType T::* P>
|
||||
struct member_value_traits
|
||||
{
|
||||
public:
|
||||
typedef typename MemberHookType::node_traits node_traits;
|
||||
typedef T value_type;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef typename boost::pointer_to_other<node_ptr, T>::type pointer;
|
||||
typedef typename boost::pointer_to_other<node_ptr, const T>::type const_pointer;
|
||||
typedef typename std::iterator_traits<pointer>::reference reference;
|
||||
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
|
||||
enum { linking_policy = MemberHookType::linking_policy };
|
||||
|
||||
public:
|
||||
static node_ptr to_node_ptr(reference value)
|
||||
{
|
||||
MemberHookType* result = &(value.*P);
|
||||
return result->to_node_ptr();
|
||||
}
|
||||
|
||||
static const_node_ptr to_node_ptr(const_reference value)
|
||||
{
|
||||
const MemberHookType* result = &(value.*P);
|
||||
return result->to_node_ptr();
|
||||
}
|
||||
|
||||
//Now let's be nasty. A pointer to member is usually implemented
|
||||
//as an offset from the start of the class.
|
||||
//get the offset in bytes and go
|
||||
//backwards from n to the value subtracting
|
||||
//the needed bytes.
|
||||
static pointer to_value_ptr(node_ptr n)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return pointer(parent_from_member((MemberHookType*)get_pointer(n), P));
|
||||
}
|
||||
|
||||
static const_pointer to_value_ptr(const_node_ptr n)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
const_pointer(parent_from_member<value_type>((const MemberHookType*)get_pointer(n), P));
|
||||
}
|
||||
|
||||
private:
|
||||
//This function converts a pointer to data member into an offset.
|
||||
//This function is not standard and it's compiler-dependent.
|
||||
static std::size_t value_to_node_offset()
|
||||
{
|
||||
const MemberHookType T::* const p = P;
|
||||
return *(const std::size_t*)(const void *)(&p);
|
||||
// using boost::get_pointer;
|
||||
// const typename node_traits::node *np =
|
||||
// get_pointer((((const value_type *)get_pointer(n))->*P).to_node_ptr());
|
||||
// return ((const char*)np - (const char*)(const value_type *)get_pointer(n));
|
||||
}
|
||||
};
|
||||
|
||||
template<class KeyValueCompare, class ValueTraits>
|
||||
struct key_node_ptr_compare
|
||||
: private detail::ebo_holder<KeyValueCompare>
|
||||
{
|
||||
typedef typename ValueTraits::node_ptr node_ptr;
|
||||
typedef detail::ebo_holder<KeyValueCompare> base_t;
|
||||
key_node_ptr_compare(KeyValueCompare kcomp)
|
||||
: base_t(kcomp)
|
||||
{}
|
||||
|
||||
template<class KeyType>
|
||||
bool operator()(node_ptr node, const KeyType &key) const
|
||||
{ return base_t::get()(*ValueTraits::to_value_ptr(node), key); }
|
||||
|
||||
template<class KeyType>
|
||||
bool operator()(const KeyType &key, node_ptr node) const
|
||||
{ return base_t::get()(key, *ValueTraits::to_value_ptr(node)); }
|
||||
|
||||
bool operator()(node_ptr node1, node_ptr node2) const
|
||||
{
|
||||
return base_t::get()
|
||||
(*ValueTraits::to_value_ptr(node1), *ValueTraits::to_value_ptr(node2));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class F, class ValueTraits>
|
||||
struct value_to_node_cloner
|
||||
: private detail::ebo_holder<F>
|
||||
{
|
||||
typedef typename ValueTraits::node_ptr node_ptr;
|
||||
typedef detail::ebo_holder<F> base_t;
|
||||
|
||||
value_to_node_cloner(F f)
|
||||
: base_t(f)
|
||||
{}
|
||||
|
||||
node_ptr operator()(node_ptr p)
|
||||
{ return ValueTraits::to_node_ptr(*base_t::get()(*ValueTraits::to_value_ptr(p))); }
|
||||
};
|
||||
|
||||
template<class F, class ValueTraits>
|
||||
struct value_to_node_destroyer
|
||||
: private detail::ebo_holder<F>
|
||||
{
|
||||
typedef typename ValueTraits::node_ptr node_ptr;
|
||||
typedef detail::ebo_holder<F> base_t;
|
||||
value_to_node_destroyer(F f)
|
||||
: base_t(f)
|
||||
{}
|
||||
|
||||
void operator()(node_ptr p)
|
||||
{ base_t::get()(ValueTraits::to_value_ptr(p)); }
|
||||
};
|
||||
|
||||
template <linking_policy Policy>
|
||||
struct dispatcher
|
||||
{};
|
||||
|
||||
template<class Container>
|
||||
void destructor_impl(Container &cont, dispatcher<safe_link>)
|
||||
{ BOOST_ASSERT(!cont.is_linked()); }
|
||||
|
||||
template<class Container>
|
||||
void destructor_impl(Container &cont, dispatcher<auto_unlink>)
|
||||
{ cont.unlink(); }
|
||||
|
||||
template<class Container>
|
||||
void destructor_impl(Container &cont, dispatcher<normal_link>)
|
||||
{}
|
||||
|
||||
template<class Node, class MaybeClass>
|
||||
struct node_plus_pred
|
||||
: public ebo_holder<MaybeClass>
|
||||
, public Node
|
||||
{
|
||||
node_plus_pred()
|
||||
{}
|
||||
|
||||
node_plus_pred(const Node &x, const MaybeClass &y)
|
||||
: Node(x), ebo_holder<MaybeClass>(y) {}
|
||||
|
||||
node_plus_pred(const MaybeClass &y)
|
||||
: ebo_holder<MaybeClass>(y) {}
|
||||
|
||||
Node &first()
|
||||
{ return *this; }
|
||||
const Node &first() const
|
||||
{ return *this; }
|
||||
MaybeClass &second()
|
||||
{ return ebo_holder<MaybeClass>::get(); }
|
||||
const MaybeClass &second() const
|
||||
{ return ebo_holder<MaybeClass>::get(); }
|
||||
|
||||
static node_plus_pred *this_from_node(Node *n)
|
||||
{ return static_cast<node_plus_pred*>(n); }
|
||||
|
||||
static node_plus_pred *this_from_node(const Node *n)
|
||||
{ return static_cast<const node_plus_pred*>(n); }
|
||||
};
|
||||
|
||||
|
||||
} //namespace detail
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_DETAIL_UTILITIES_HPP
|
852
include/boost/intrusive/hashtable.hpp
Normal file
852
include/boost/intrusive/hashtable.hpp
Normal file
@ -0,0 +1,852 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_HASHTABLE_HPP
|
||||
#define BOOST_INTRUSIVE_HASHTABLE_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
//std C++
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
//boost
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/compressed_pair.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
//General intrusive utilities
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/detail/hashtable_node.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
//Implementation utilities
|
||||
#include <boost/intrusive/unordered_set_hook.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//! The class template hashtable is an intrusive hash table container, that
|
||||
//! is used to construct intrusive unordered_set and unordered_multiset containers. The
|
||||
//! no-throw guarantee holds only, if the Equal object and Hasher don't throw.
|
||||
template< class ValueTraits
|
||||
, class Hash //= boost::hash<typename ValueTraits::value_type>
|
||||
, class Equal //= std::equal_to<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize //= true
|
||||
, class SizeType //= std::size_t
|
||||
>
|
||||
class hashtable
|
||||
: private detail::size_holder<ConstantTimeSize, SizeType>
|
||||
{
|
||||
/// @cond
|
||||
private:
|
||||
typedef slist<ValueTraits, false, SizeType> slist_impl;
|
||||
typedef hashtable<ValueTraits, Hash, Equal
|
||||
,ConstantTimeSize, SizeType> this_type;
|
||||
typedef typename ValueTraits::node_traits node_traits;
|
||||
typedef detail::size_holder<ConstantTimeSize, SizeType> size_traits;
|
||||
|
||||
//noncopyable
|
||||
hashtable (const hashtable&);
|
||||
hashtable operator =(const hashtable&);
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef ValueTraits value_traits;
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ValueTraits::pointer pointer;
|
||||
typedef typename ValueTraits::const_pointer const_pointer;
|
||||
typedef typename std::iterator_traits<pointer>::reference reference;
|
||||
typedef typename std::iterator_traits<const_pointer>::reference const_reference;
|
||||
typedef typename std::iterator_traits<pointer>::difference_type difference_type;
|
||||
typedef SizeType size_type;
|
||||
typedef value_type key_type;
|
||||
typedef Hash hasher;
|
||||
typedef Equal key_equal;
|
||||
typedef detail::bucket_type_impl<slist_impl> bucket_type;
|
||||
typedef typename boost::pointer_to_other
|
||||
<pointer, bucket_type>::type bucket_ptr;
|
||||
typedef typename slist_impl::iterator local_iterator;
|
||||
typedef typename slist_impl::const_iterator const_local_iterator;
|
||||
|
||||
typedef detail::hashtable_iterator<value_type, slist_impl> iterator;
|
||||
typedef detail::hashtable_iterator<value_type, slist_impl> const_iterator;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<pointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<node_ptr, const node>::type const_node_ptr;
|
||||
|
||||
enum { safemode_or_autounlink =
|
||||
(int)ValueTraits::linking_policy == (int)auto_unlink ||
|
||||
(int)ValueTraits::linking_policy == (int)safe_link };
|
||||
|
||||
//Constant-time size is incompatible with auto-unlink hooks!
|
||||
BOOST_STATIC_ASSERT(!(ConstantTimeSize && ((int)ValueTraits::linking_policy == (int)auto_unlink)));
|
||||
|
||||
typedef detail::bucket_info_impl<slist_impl> bucket_info_t;
|
||||
typedef typename boost::pointer_to_other
|
||||
<pointer, bucket_info_t>::type bucket_info_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<pointer, const bucket_info_t>::type const_bucket_info_ptr;
|
||||
|
||||
//User scattered boost::compressed pair to get EBO all compilers
|
||||
boost::compressed_pair
|
||||
<boost::compressed_pair<bucket_info_t, Hash>
|
||||
,Equal> members_;
|
||||
|
||||
const Equal &priv_equal() const
|
||||
{ return members_.second(); }
|
||||
|
||||
Equal &priv_equal()
|
||||
{ return members_.second(); }
|
||||
|
||||
const_bucket_info_ptr priv_bucket_info() const
|
||||
{ return &members_.first().first(); }
|
||||
|
||||
bucket_info_ptr priv_bucket_info()
|
||||
{ return &members_.first().first(); }
|
||||
|
||||
const Hash &priv_hasher() const
|
||||
{ return members_.first().second(); }
|
||||
|
||||
Hash &priv_hasher()
|
||||
{ return members_.first().second(); }
|
||||
|
||||
const bucket_ptr &priv_buckets() const
|
||||
{ return members_.first().first().buckets_; }
|
||||
|
||||
bucket_ptr &priv_buckets()
|
||||
{ return members_.first().first().buckets_; }
|
||||
|
||||
const size_type &priv_buckets_len() const
|
||||
{ return members_.first().first().buckets_len_; }
|
||||
|
||||
size_type &priv_buckets_len()
|
||||
{ return members_.first().first().buckets_len_; }
|
||||
|
||||
static node_ptr uncast(const_node_ptr ptr)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return node_ptr(const_cast<node*>(get_pointer(ptr)));
|
||||
}
|
||||
|
||||
static bucket_info_ptr uncast(const_bucket_info_ptr ptr)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return bucket_info_ptr(const_cast<bucket_info_t*>(get_pointer(ptr)));
|
||||
}
|
||||
|
||||
static slist_impl &bucket_to_slist(bucket_type &b)
|
||||
{ return static_cast<slist_impl &>(b); }
|
||||
|
||||
static const slist_impl &bucket_to_slist(const bucket_type &b)
|
||||
{ return static_cast<const slist_impl &>(b); }
|
||||
|
||||
struct insert_commit_data_impl
|
||||
{
|
||||
size_type hash;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef insert_commit_data_impl insert_commit_data;
|
||||
|
||||
hashtable( bucket_ptr buckets
|
||||
, size_type buckets_len
|
||||
, const Hash & hasher = Hash()
|
||||
, const Equal &equal = Equal())
|
||||
: members_(boost::compressed_pair<bucket_info_t, Hash>(hasher), equal)
|
||||
{
|
||||
|
||||
BOOST_ASSERT(buckets_len != 0);
|
||||
priv_buckets() = buckets;
|
||||
priv_buckets_len() = buckets_len;
|
||||
priv_clear_buckets();
|
||||
size_traits::set_size(size_type(0));
|
||||
}
|
||||
|
||||
~hashtable()
|
||||
{ this->clear(); }
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
size_type bucket_num;
|
||||
local_iterator local_it = priv_begin(bucket_num);
|
||||
return iterator( local_it, this->priv_bucket_info());
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{ return cbegin(); }
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
size_type bucket_num;
|
||||
local_iterator local_it = priv_begin(bucket_num);
|
||||
return const_iterator( local_it, this->priv_bucket_info());
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
using boost::get_pointer;
|
||||
bucket_info_t *info = get_pointer(this->priv_bucket_info());
|
||||
return iterator(invalid_local_it(*info), 0);
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{ return cend(); }
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
using boost::get_pointer;
|
||||
const bucket_info_t *info = get_pointer(this->priv_bucket_info());
|
||||
return const_iterator(invalid_local_it(*info), 0);
|
||||
}
|
||||
|
||||
hasher hash_function() const
|
||||
{ return this->priv_hasher(); }
|
||||
|
||||
key_equal key_eq() const
|
||||
{ return this->priv_equal(); }
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
if(ConstantTimeSize){
|
||||
return !size();
|
||||
}
|
||||
else{
|
||||
using boost::get_pointer;
|
||||
size_type buckets_len = this->priv_buckets_len();
|
||||
const bucket_type *b = get_pointer(this->priv_buckets());
|
||||
for (size_type n = 0; n < buckets_len; ++n, ++b){
|
||||
if(!b->empty()){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
if(ConstantTimeSize)
|
||||
return size_traits::get_size();
|
||||
else{
|
||||
size_type len = 0;
|
||||
using boost::get_pointer;
|
||||
size_type buckets_len = this->priv_buckets_len();
|
||||
const bucket_type *b = get_pointer(this->priv_buckets());
|
||||
for (size_type n = 0; n < buckets_len; ++n, ++b){
|
||||
len += b->size();
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(hashtable& other)
|
||||
{
|
||||
using std::swap;
|
||||
//These can throw
|
||||
swap(this->priv_equal(), other.priv_equal());
|
||||
swap(this->priv_hasher(), other.priv_hasher());
|
||||
//These can't throw
|
||||
swap(this->priv_buckets(), other.priv_buckets());
|
||||
swap(this->priv_buckets_len(), other.priv_buckets_len());
|
||||
if(ConstantTimeSize){
|
||||
size_type backup = size_traits::get_size();
|
||||
size_traits::set_size(other.get_size());
|
||||
other.set_size(backup);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Cloner, class Destroyer>
|
||||
void clone_from(const hashtable &src, Cloner cloner, Destroyer destroyer)
|
||||
{
|
||||
this->clear_and_destroy(destroyer);
|
||||
if(!ConstantTimeSize || !src.empty()){
|
||||
const size_type src_bucket_count = src.bucket_count();
|
||||
const size_type dst_bucket_count = this->bucket_count();
|
||||
|
||||
//If src bucket count is bigger or equal, structural copy is possible
|
||||
if(src_bucket_count >= dst_bucket_count){
|
||||
//First clone the first ones
|
||||
const bucket_ptr src_buckets = src.priv_buckets();
|
||||
const bucket_ptr dst_buckets = this->priv_buckets();
|
||||
size_type constructed;
|
||||
try{
|
||||
for( constructed = 0
|
||||
; constructed < dst_bucket_count
|
||||
; ++constructed){
|
||||
dst_buckets[constructed].clone_from(src_buckets[constructed], cloner, destroyer);
|
||||
}
|
||||
if(src_bucket_count != dst_bucket_count){
|
||||
//Now insert the remaining ones using the modulo trick
|
||||
for(//"constructed" comes from the previous loop
|
||||
; constructed < src_bucket_count
|
||||
; ++constructed){
|
||||
bucket_type &dst_b = dst_buckets[constructed % dst_bucket_count];
|
||||
bucket_type &src_b = src_buckets[constructed];
|
||||
for( local_iterator b(src_b.begin()), e(src_b.end())
|
||||
; b != e
|
||||
; ++b){
|
||||
dst_b.push_front(*cloner(*b));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(...){
|
||||
while(constructed--){
|
||||
dst_buckets[constructed].clear_and_destroy(destroyer);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
size_traits::set_size(src.get_size());
|
||||
}
|
||||
else{
|
||||
//Unlike previous cloning algorithm, this can throw
|
||||
//if cloner, the hasher or comparison functor throw
|
||||
const_iterator b(src.begin()), e(src.end());
|
||||
try{
|
||||
for(; b != e; ++b){
|
||||
this->insert_equal(*cloner(*b));
|
||||
}
|
||||
}
|
||||
catch(...){
|
||||
this->clear_and_destroy(destroyer);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iterator insert_equal(reference value)
|
||||
{
|
||||
size_type bucket_num, hash;
|
||||
local_iterator it = priv_find(value, this->priv_hasher(), this->priv_equal(), bucket_num, hash);
|
||||
bucket_type &b = this->priv_buckets()[bucket_num];
|
||||
if(it == invalid_local_it(*this->priv_bucket_info())){
|
||||
it = b.before_begin();
|
||||
}
|
||||
size_traits::increment();
|
||||
return iterator(b.insert_after(it, value), this->priv_bucket_info());
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
void insert_equal(Iterator b, Iterator e)
|
||||
{
|
||||
for (; b != e; ++b)
|
||||
this->insert_equal(*b);
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert_unique(reference value)
|
||||
{
|
||||
insert_commit_data commit_data;
|
||||
std::pair<iterator, bool> ret = insert_unique_check(value, commit_data);
|
||||
if(!ret.second)
|
||||
return ret;
|
||||
return std::pair<iterator, bool> (insert_unique_commit(value, commit_data), true);
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
void insert_unique(Iterator b, Iterator e)
|
||||
{
|
||||
for (; b != e; ++b)
|
||||
this->insert_unique(*b);
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert_unique_check
|
||||
(const_reference value, insert_commit_data &commit_data)
|
||||
{ return insert_unique_check(value, this->priv_hasher(), this->priv_equal(), commit_data); }
|
||||
|
||||
template<class KeyType, class KeyHasher, class KeyValueEqual>
|
||||
std::pair<iterator, bool> insert_unique_check
|
||||
( const KeyType &key
|
||||
, KeyHasher hasher
|
||||
, KeyValueEqual key_value_eq
|
||||
, insert_commit_data &commit_data)
|
||||
{
|
||||
size_type bucket_num;
|
||||
local_iterator prev_pos =
|
||||
priv_find(key, hasher, key_value_eq, bucket_num, commit_data.hash);
|
||||
bool success = prev_pos == invalid_local_it(*this->priv_bucket_info());
|
||||
if(success){
|
||||
prev_pos = this->priv_buckets()[bucket_num].before_begin();
|
||||
}
|
||||
return std::pair<iterator, bool>
|
||||
(iterator(prev_pos, this->priv_bucket_info())
|
||||
,success);
|
||||
}
|
||||
|
||||
iterator insert_unique_commit(reference value, const insert_commit_data &commit_data)
|
||||
{
|
||||
size_type bucket_num = commit_data.hash % this->priv_buckets_len();
|
||||
bucket_type &b = this->priv_buckets()[bucket_num];
|
||||
size_traits::increment();
|
||||
return iterator( b.insert_after(b.before_begin(), value)
|
||||
, this->priv_bucket_info());
|
||||
}
|
||||
|
||||
void erase(const_iterator i)
|
||||
{ erase_and_destroy(i, detail::null_destroyer()); }
|
||||
|
||||
void erase(const_iterator b, const_iterator e)
|
||||
{ erase_and_destroy(b, e, detail::null_destroyer()); }
|
||||
|
||||
size_type erase(const_reference value)
|
||||
{ return this->erase(value, this->priv_hasher(), this->priv_equal()); }
|
||||
|
||||
template<class KeyType, class KeyHasher, class KeyValueEqual>
|
||||
size_type erase(const KeyType& key, KeyHasher hasher, KeyValueEqual equal)
|
||||
{ return erase_and_destroy(key, hasher, equal, detail::null_destroyer()); }
|
||||
|
||||
template<class Destroyer>
|
||||
void erase_and_destroy(const_iterator i, Destroyer destroyer)
|
||||
{
|
||||
local_iterator to_erase(i.local());
|
||||
bucket_ptr f(priv_buckets()), l(f + priv_buckets_len());
|
||||
bucket_type &b = this->priv_buckets()[bucket_type::get_bucket_num(to_erase, *f, *l)];
|
||||
b.erase_after_and_destroy(b.previous(to_erase), destroyer);
|
||||
size_traits::decrement();
|
||||
}
|
||||
|
||||
template<class Destroyer>
|
||||
void erase_and_destroy(const_iterator b, const_iterator e, Destroyer destroyer)
|
||||
{
|
||||
if(b == e) return;
|
||||
|
||||
//Get the bucket number and local iterator for both iterators
|
||||
bucket_ptr f(priv_buckets()), l(f + priv_buckets_len());
|
||||
size_type first_bucket_num = bucket_type::get_bucket_num(b.local(), *f, *l);
|
||||
|
||||
local_iterator before_first_local_it
|
||||
= priv_buckets()[first_bucket_num].previous(b.local());
|
||||
size_type last_bucket_num;
|
||||
local_iterator last_local_it;
|
||||
|
||||
//For the end iterator, we will assign the end iterator
|
||||
//of the last bucket
|
||||
if(e == end()){
|
||||
last_bucket_num = this->bucket_count() - 1;
|
||||
last_local_it = priv_buckets()[last_bucket_num].end();
|
||||
}
|
||||
else{
|
||||
last_local_it = e.local();
|
||||
last_bucket_num = bucket_type::get_bucket_num(last_local_it, *f, *l);
|
||||
}
|
||||
|
||||
const bucket_ptr buckets = priv_buckets();
|
||||
//First erase the nodes of the first bucket
|
||||
{
|
||||
bucket_type &first_b = buckets[first_bucket_num];
|
||||
local_iterator nxt(before_first_local_it); ++nxt;
|
||||
local_iterator end = first_b.end();
|
||||
while(nxt != end){
|
||||
nxt = first_b.erase_after_and_destroy(before_first_local_it, destroyer);
|
||||
size_traits::decrement();
|
||||
}
|
||||
}
|
||||
|
||||
//Now fully clear the intermediate buckets
|
||||
for(size_type i = first_bucket_num+1; i < last_bucket_num; ++i){
|
||||
bucket_type &b = buckets[i];
|
||||
if(b.empty())
|
||||
continue;
|
||||
local_iterator b_begin(b.before_begin());
|
||||
local_iterator nxt(b_begin); ++nxt;
|
||||
local_iterator end = b.end();
|
||||
while(nxt != end){
|
||||
nxt = b.erase_after_and_destroy(b_begin, destroyer);
|
||||
size_traits::decrement();
|
||||
}
|
||||
}
|
||||
|
||||
//Now erase nodes from the last bucket
|
||||
{
|
||||
bucket_type &last_b = buckets[last_bucket_num];
|
||||
local_iterator b_begin(last_b.before_begin());
|
||||
local_iterator nxt(b_begin); ++nxt;
|
||||
while(nxt != last_local_it){
|
||||
nxt = last_b.erase_after_and_destroy(b_begin, destroyer);
|
||||
size_traits::decrement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Destroyer>
|
||||
size_type erase_and_destroy(const_reference value, Destroyer destroyer)
|
||||
{ return erase_and_destroy(value, priv_hasher(), priv_equal(), destroyer); }
|
||||
|
||||
template<class KeyType, class KeyHasher, class KeyValueEqual, class Destroyer>
|
||||
size_type erase_and_destroy(const KeyType& key, KeyHasher hasher
|
||||
,KeyValueEqual equal, Destroyer destroyer)
|
||||
{
|
||||
size_type count(0);
|
||||
|
||||
if(ConstantTimeSize && this->empty()){
|
||||
return 0;
|
||||
}
|
||||
|
||||
bucket_type &b = this->priv_buckets()[hasher(key) % this->priv_buckets_len()];
|
||||
local_iterator it = b.begin();
|
||||
local_iterator prev = b.before_begin();
|
||||
|
||||
bool found = false;
|
||||
//Find equal value
|
||||
while(it != b.end()){
|
||||
if(equal(key, *it)){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
++prev;
|
||||
++it;
|
||||
}
|
||||
|
||||
if(!found)
|
||||
return 0;
|
||||
|
||||
//If found erase all equal values
|
||||
for(local_iterator end = b.end(); it != end && equal(key, *it); ++count){
|
||||
it = b.erase_after_and_destroy(prev, destroyer);
|
||||
size_traits::decrement();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
if(safemode_or_autounlink){
|
||||
priv_clear_buckets();
|
||||
}
|
||||
size_traits::set_size(size_type(0));
|
||||
}
|
||||
|
||||
template<class Destroyer>
|
||||
void clear_and_destroy(Destroyer destroyer)
|
||||
{
|
||||
if(!ConstantTimeSize || !this->empty()){
|
||||
size_type num_buckets = this->bucket_count();
|
||||
bucket_ptr b = this->priv_buckets();
|
||||
for(; num_buckets--; ++b){
|
||||
b->clear_and_destroy(destroyer);
|
||||
}
|
||||
size_traits::set_size(size_type(0));
|
||||
}
|
||||
}
|
||||
|
||||
size_type count(const_reference value) const
|
||||
{ return this->count(value, this->priv_hasher(), this->priv_equal()); }
|
||||
|
||||
template<class KeyType, class KeyHasher, class KeyValueEqual>
|
||||
size_type count(const KeyType &key, const KeyHasher &hasher, const KeyValueEqual &equal) const
|
||||
{
|
||||
size_type bucket_n1, bucket_n2, count;
|
||||
priv_equal_range(key, hasher, equal, bucket_n1, bucket_n2, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
iterator find(const_reference value)
|
||||
{ return find(value, this->priv_hasher(), this->priv_equal()); }
|
||||
|
||||
template<class KeyType, class KeyHasher, class KeyValueEqual>
|
||||
iterator find(const KeyType &key, KeyHasher hasher, KeyValueEqual equal)
|
||||
{
|
||||
size_type bucket_n, hash;
|
||||
local_iterator local_it = priv_find(key, hasher, equal, bucket_n, hash);
|
||||
return iterator( local_it
|
||||
, this->priv_bucket_info());
|
||||
}
|
||||
|
||||
const_iterator find(const_reference value) const
|
||||
{ return find(value, this->priv_hasher(), this->priv_equal()); }
|
||||
|
||||
template<class KeyType, class KeyHasher, class KeyValueEqual>
|
||||
const_iterator find
|
||||
(const KeyType &key, KeyHasher hasher, KeyValueEqual equal) const
|
||||
{
|
||||
size_type bucket_n, hash;
|
||||
local_iterator local_it = priv_find(key, hasher, equal, bucket_n, hash);
|
||||
return const_iterator( local_it
|
||||
, uncast(this->priv_bucket_info()));
|
||||
}
|
||||
|
||||
std::pair<iterator,iterator> equal_range(const_reference value)
|
||||
{ return this->equal_range(value, this->priv_hasher(), this->priv_equal()); }
|
||||
|
||||
template<class KeyType, class KeyHasher, class KeyValueEqual>
|
||||
std::pair<iterator,iterator> equal_range
|
||||
(const KeyType &key, KeyHasher hasher, KeyValueEqual equal)
|
||||
{
|
||||
size_type bucket_n1, bucket_n2, count;
|
||||
std::pair<local_iterator, local_iterator> ret
|
||||
= priv_equal_range(key, hasher, equal, bucket_n1, bucket_n2, count);
|
||||
return std::pair<iterator, iterator>
|
||||
( iterator( ret.first, this->priv_bucket_info() )
|
||||
, iterator( ret.second, this->priv_bucket_info()) );
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const_reference value) const
|
||||
{ return this->equal_range(value, this->priv_hasher(), this->priv_equal()); }
|
||||
|
||||
template<class KeyType, class KeyHasher, class KeyValueEqual>
|
||||
std::pair<const_iterator,const_iterator> equal_range
|
||||
(const KeyType &key, KeyHasher hasher, KeyValueEqual equal) const
|
||||
{
|
||||
size_type bucket_n1, bucket_n2, count;
|
||||
std::pair<local_iterator, local_iterator> ret
|
||||
= priv_equal_range(key, hasher, equal, bucket_n1, bucket_n2, count);
|
||||
return std::pair<const_iterator, const_iterator>
|
||||
( const_iterator( ret.first, uncast(this->priv_bucket_info()) )
|
||||
, const_iterator( ret.second, uncast(this->priv_bucket_info()) ) );
|
||||
}
|
||||
|
||||
size_type bucket_count() const
|
||||
{ return this->priv_buckets_len(); }
|
||||
|
||||
size_type bucket_size(size_type n) const
|
||||
{ return this->priv_buckets()[n].size(); }
|
||||
|
||||
size_type bucket(const key_type& k) const
|
||||
{ return this->bucket(k, this->priv_hasher()); }
|
||||
|
||||
template<class KeyType, class KeyHasher>
|
||||
size_type bucket(const KeyType& k, const KeyHasher &hasher) const
|
||||
{ return hasher(k) % this->priv_buckets_len(); }
|
||||
|
||||
bucket_ptr bucket_pointer() const
|
||||
{ return this->priv_buckets(); }
|
||||
|
||||
local_iterator begin(size_type n)
|
||||
{ return this->priv_buckets()[n].begin(); }
|
||||
|
||||
const_local_iterator begin(size_type n) const
|
||||
{ return this->cbegin(n); }
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
{ return const_cast<const bucket_type&>(this->priv_buckets()[n]).begin(); }
|
||||
|
||||
local_iterator end(size_type n)
|
||||
{ return this->priv_buckets()[n].end(); }
|
||||
|
||||
const_local_iterator end(size_type n) const
|
||||
{ return this->cend(n); }
|
||||
|
||||
const_local_iterator cend(size_type n) const
|
||||
{ return const_cast<const bucket_type&>(this->priv_buckets()[n]).end(); }
|
||||
|
||||
void rehash(bucket_ptr new_buckets, size_type new_buckets_len)
|
||||
{
|
||||
bucket_ptr old_buckets = this->priv_buckets();
|
||||
size_type old_buckets_len = this->priv_buckets_len();
|
||||
|
||||
try{
|
||||
size_type n = 0;
|
||||
bool same_buffer = old_buckets == new_buckets;
|
||||
//If we are shrinking the bucket array, just rehash the last nodes
|
||||
if(same_buffer && (old_buckets_len > new_buckets_len)){
|
||||
n = new_buckets_len;
|
||||
}
|
||||
|
||||
//Iterate through nodes
|
||||
for(; n < old_buckets_len; ++n){
|
||||
bucket_type &old_bucket = old_buckets[n];
|
||||
local_iterator before_i(old_bucket.before_begin());
|
||||
local_iterator end(old_bucket.end());
|
||||
local_iterator i(old_bucket.begin());
|
||||
for(;i != end; ++i){
|
||||
size_type new_n = this->priv_hasher()(*i) % new_buckets_len;
|
||||
//If this is a buffer expansion don't move if it's not necessary
|
||||
if(same_buffer && new_n == n){
|
||||
++before_i;
|
||||
}
|
||||
else{
|
||||
bucket_type &new_b = new_buckets[new_n];
|
||||
new_b.splice_after(new_b.before_begin(), old_bucket, before_i);
|
||||
i = before_i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->priv_buckets() = new_buckets;
|
||||
this->priv_buckets_len() = new_buckets_len;
|
||||
}
|
||||
catch(...){
|
||||
for(size_type n = 0; n < new_buckets_len; ++n){
|
||||
new_buckets[n].clear();
|
||||
old_buckets[n].clear();
|
||||
}
|
||||
size_traits::set_size(size_type(0));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
iterator iterator_to(reference value)
|
||||
{
|
||||
return iterator( bucket_type::iterator_to(value)
|
||||
, this->priv_bucket_info());
|
||||
}
|
||||
|
||||
const_iterator iterator_to(const_reference value) const
|
||||
{
|
||||
return const_iterator( bucket_type::iterator_to(const_cast<reference>(value))
|
||||
, uncast(this->priv_bucket_info()));
|
||||
}
|
||||
|
||||
static local_iterator local_iterator_to(reference value)
|
||||
{ return bucket_type::iterator_to(value); }
|
||||
|
||||
static const_local_iterator local_iterator_to(const_reference value)
|
||||
{ return bucket_type::iterator_to(value); }
|
||||
|
||||
// no throw
|
||||
static size_type suggested_upper_bucket_count(size_type n)
|
||||
{
|
||||
const std::size_t *primes = &detail::prime_list_holder<0>::prime_list[0];
|
||||
const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size;
|
||||
size_type const* bound =
|
||||
std::lower_bound(primes, primes_end, n);
|
||||
if(bound == primes_end)
|
||||
bound--;
|
||||
return size_type(*bound);
|
||||
}
|
||||
|
||||
// no throw
|
||||
static size_type suggested_lower_bucket_count(size_type n)
|
||||
{
|
||||
const std::size_t *primes = &detail::prime_list_holder<0>::prime_list[0];
|
||||
const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size;
|
||||
size_type const* bound =
|
||||
std::upper_bound(primes, primes_end, n);
|
||||
if(bound != primes_end)
|
||||
bound--;
|
||||
return size_type(*bound);
|
||||
}
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
static local_iterator invalid_local_it(const bucket_info_t &b)
|
||||
{ return b.buckets_->end(); }
|
||||
|
||||
local_iterator priv_begin(size_type &bucket_num) const
|
||||
{
|
||||
size_type buckets_len = this->priv_buckets_len();
|
||||
for (bucket_num = 0; bucket_num < buckets_len; ++bucket_num){
|
||||
bucket_type &b = this->priv_buckets()[bucket_num];
|
||||
if(!b.empty())
|
||||
return b.begin();
|
||||
}
|
||||
return invalid_local_it(*this->priv_bucket_info());
|
||||
}
|
||||
|
||||
void priv_clear_buckets()
|
||||
{ priv_clear_buckets(this->priv_buckets(), this->priv_buckets_len()); }
|
||||
|
||||
static void priv_clear_buckets(bucket_ptr buckets_ptr, size_type buckets_len)
|
||||
{
|
||||
for(; buckets_len--; ++buckets_ptr){
|
||||
buckets_ptr->clear();
|
||||
}
|
||||
}
|
||||
|
||||
template<class KeyType, class KeyHasher, class KeyValueEqual>
|
||||
local_iterator priv_find
|
||||
( const KeyType &key, KeyHasher hasher
|
||||
, KeyValueEqual equal, size_type &bucket_number, size_type &hash) const
|
||||
{
|
||||
size_type b_len(this->priv_buckets_len());
|
||||
hash = hasher(key);
|
||||
bucket_number = hash % b_len;
|
||||
|
||||
if(ConstantTimeSize && this->empty()){
|
||||
return invalid_local_it(*this->priv_bucket_info());
|
||||
}
|
||||
|
||||
bucket_type &b = this->priv_buckets()[bucket_number];
|
||||
local_iterator it = b.begin();
|
||||
|
||||
while(it != b.end()){
|
||||
if(equal(key, *it)){
|
||||
return it;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
return invalid_local_it(*this->priv_bucket_info());
|
||||
}
|
||||
|
||||
template<class KeyType, class KeyHasher, class KeyValueEqual>
|
||||
std::pair<local_iterator, local_iterator> priv_equal_range
|
||||
( const KeyType &key
|
||||
, KeyHasher hasher
|
||||
, KeyValueEqual equal
|
||||
, size_type &bucket_number_first
|
||||
, size_type &bucket_number_second
|
||||
, size_type &count) const
|
||||
{
|
||||
size_type hash;
|
||||
count = 0;
|
||||
//Let's see if the element is present
|
||||
std::pair<local_iterator, local_iterator> to_return
|
||||
( priv_find(key, hasher, equal, bucket_number_first, hash)
|
||||
, invalid_local_it(*this->priv_bucket_info()));
|
||||
if(to_return.first == to_return.second){
|
||||
bucket_number_second = bucket_number_first;
|
||||
return to_return;
|
||||
}
|
||||
++count;
|
||||
//If it's present, find the first that it's not equal in
|
||||
//the same bucket
|
||||
bucket_type &b = this->priv_buckets()[bucket_number_first];
|
||||
local_iterator it = to_return.first;
|
||||
++it;
|
||||
|
||||
while(it != b.end()){
|
||||
if(!equal(key, *it)){
|
||||
to_return.second = it;
|
||||
bucket_number_second = bucket_number_first;
|
||||
return to_return;
|
||||
}
|
||||
++it;
|
||||
++count;
|
||||
}
|
||||
|
||||
//If we reached the end, find the first, non-empty bucket
|
||||
for(bucket_number_second = bucket_number_first+1
|
||||
; bucket_number_second != this->priv_buckets_len()
|
||||
; ++bucket_number_second){
|
||||
bucket_type &b = this->priv_buckets()[bucket_number_second];
|
||||
if(!b.empty()){
|
||||
to_return.second = b.begin();
|
||||
return to_return;
|
||||
}
|
||||
}
|
||||
|
||||
//Otherwise, return the end node
|
||||
to_return.second = invalid_local_it(*this->priv_bucket_info());
|
||||
return to_return;
|
||||
}
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_HASHTABLE_HPP
|
154
include/boost/intrusive/intrusive_fwd.hpp
Normal file
154
include/boost/intrusive/intrusive_fwd.hpp
Normal file
@ -0,0 +1,154 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2007
|
||||
//
|
||||
// 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_FWD_HPP
|
||||
#define BOOST_INTRUSIVE_FWD_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
#include <boost/intrusive/tag.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
|
||||
//std predeclarations
|
||||
namespace std{
|
||||
|
||||
template<class T>
|
||||
struct equal_to;
|
||||
|
||||
template<class T>
|
||||
struct less;
|
||||
|
||||
} //namespace std{
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
////////////////////////////
|
||||
// Node algorithms
|
||||
////////////////////////////
|
||||
|
||||
//Algorithms predeclarations
|
||||
template<class NodeTraits>
|
||||
class circular_list_algorithms;
|
||||
|
||||
template<class NodeTraits>
|
||||
class circular_slist_algorithms;
|
||||
|
||||
template<class NodeTraits>
|
||||
class rbtree_algorithms;
|
||||
|
||||
////////////////////////////
|
||||
// Containers
|
||||
////////////////////////////
|
||||
|
||||
//slist
|
||||
template < class ValueTraits
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t>
|
||||
class slist;
|
||||
|
||||
template< class Tag = tag
|
||||
, linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *
|
||||
>
|
||||
class slist_base_hook;
|
||||
|
||||
template< linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *>
|
||||
class slist_member_hook;
|
||||
|
||||
//list
|
||||
template< class ValueTraits
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t>
|
||||
class list;
|
||||
|
||||
template< class Tag = tag
|
||||
, linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *
|
||||
>
|
||||
class list_base_hook;
|
||||
|
||||
template< linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *>
|
||||
class list_member_hook;
|
||||
|
||||
//hash/unordered
|
||||
template< class ValueTraits
|
||||
, class Hash = boost::hash<typename ValueTraits::value_type>
|
||||
, class Equal = std::equal_to<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t
|
||||
>
|
||||
class hashtable;
|
||||
|
||||
template< class ValueTraits
|
||||
, class Hash = boost::hash<typename ValueTraits::value_type>
|
||||
, class Equal = std::equal_to<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t
|
||||
>
|
||||
class unordered_set;
|
||||
|
||||
template< class ValueTraits
|
||||
, class Hash = boost::hash<typename ValueTraits::value_type>
|
||||
, class Equal = std::equal_to<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t
|
||||
>
|
||||
class unordered_multiset;
|
||||
|
||||
template< class Tag = tag
|
||||
, linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *
|
||||
>
|
||||
class unordered_set_base_hook;
|
||||
|
||||
template< linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *>
|
||||
class unordered_set_member_hook;
|
||||
|
||||
|
||||
//rbtree/set
|
||||
template < class ValueTraits
|
||||
, class Compare = std::less<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t
|
||||
>
|
||||
class rbtree;
|
||||
|
||||
template < class ValueTraits
|
||||
, class Compare = std::less<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t>
|
||||
class set;
|
||||
|
||||
template < class ValueTraits
|
||||
, class Compare = std::less<typename ValueTraits::value_type>
|
||||
, bool ConstantTimeSize = true
|
||||
, class SizeType = std::size_t>
|
||||
class multiset;
|
||||
|
||||
template< class Tag = tag
|
||||
, linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *
|
||||
>
|
||||
class set_base_hook;
|
||||
|
||||
template< linking_policy Policy = safe_link
|
||||
, class VoidPointer = void *>
|
||||
class set_member_hook;
|
||||
|
||||
} //namespace intrusive {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_FWD_HPP
|
46
include/boost/intrusive/linking_policy.hpp
Normal file
46
include/boost/intrusive/linking_policy.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_VALUE_LINKING_POLICY_HPP
|
||||
#define BOOST_INTRUSIVE_VALUE_LINKING_POLICY_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//!This enumeration defines the type of value_traits that can be defined
|
||||
//!for Boost.Intrusive containers
|
||||
enum linking_policy{
|
||||
//!If this linking policy is specified in a value_traits class
|
||||
//!as the linking_policy, containers
|
||||
//!configured with such value_traits won't set the hooks
|
||||
//!of the erased values to a default state. Containers also won't
|
||||
//!check that the hooks of the new values are default initialized.
|
||||
normal_link,
|
||||
|
||||
//!If this linking policy is specified in a value_traits class
|
||||
//!as the linking_policy, containers
|
||||
//!configured with such value_traits will set the hooks
|
||||
//!of the erased values to a default state. Containers also will
|
||||
//!check that the hooks of the new values are default initialized.
|
||||
safe_link,
|
||||
|
||||
//!Same as "safe_link" but the user type is an auto-unlink
|
||||
//!type, so the containers with constant-time size features won't be
|
||||
//!compatible with value_traits configured with this policy.
|
||||
//!Containers also know that the a value can be silently erased from
|
||||
//!the container without using any function provided by the containers.
|
||||
auto_unlink
|
||||
};
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#endif //BOOST_INTRUSIVE_VALUE_LINKING_POLICY_HPP
|
1214
include/boost/intrusive/list.hpp
Normal file
1214
include/boost/intrusive/list.hpp
Normal file
File diff suppressed because it is too large
Load Diff
400
include/boost/intrusive/list_hook.hpp
Normal file
400
include/boost/intrusive/list_hook.hpp
Normal file
@ -0,0 +1,400 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_LIST_HOOK_HPP
|
||||
#define BOOST_INTRUSIVE_LIST_HOOK_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/detail/list_node.hpp>
|
||||
#include <boost/intrusive/circular_list_algorithms.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/tag.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//! Derive a class from list_base_hook in order to store objects in
|
||||
//! in an list. list_base_hook holds the data necessary to maintain the
|
||||
//! list and provides an appropriate value_traits class for list.
|
||||
//!
|
||||
//! The first integer template argument defines a tag to identify the node.
|
||||
//! The same tag value can be used in different classes, but if a class is
|
||||
//! derived from more than one list_base_hook, then each list_base_hook needs its
|
||||
//! unique tag.
|
||||
//!
|
||||
//! The second boolean template parameter will specify the linking mode of the hook.
|
||||
//!
|
||||
//! The third argument is the pointer type that will be used internally in the hook
|
||||
//! and the list configured from this hook.
|
||||
template< class Tag //= tag
|
||||
, linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
class list_base_hook
|
||||
: private detail::list_node_traits<VoidPointer>::node
|
||||
{
|
||||
public:
|
||||
typedef detail::list_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef circular_list_algorithms<node_traits> node_algorithms;
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef list_base_hook
|
||||
<Tag, Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type>::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type>::type const_this_type_ptr;
|
||||
|
||||
private:
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
list_base_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using list_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
list_base_hook(const list_base_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using list_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
list_base_hook& operator=(const list_base_hook& )
|
||||
{ return *this; }
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~list_base_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(list_base_hook &other)
|
||||
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether list::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
|
||||
//! The value_traits class is used as the first template argument for list.
|
||||
//! The template argument T defines the class type stored in list. Objects
|
||||
//! of type T and of types derived from T can be stored. T doesn't need to be
|
||||
//! copy-constructible or assignable.
|
||||
template<class T>
|
||||
struct value_traits
|
||||
: detail::derivation_value_traits<T, this_type, Tag>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return this_type_ptr(static_cast<list_base_hook*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return const_this_type_ptr(static_cast<const list_base_hook*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
};
|
||||
|
||||
//! Put a public data member list_member_hook in order to store objects of this class in
|
||||
//! an list. list_member_hook holds the data necessary for maintaining the list and
|
||||
//! provides an appropriate value_traits class for list.
|
||||
//!
|
||||
//! The first boolean template parameter will specify the linking mode of the hook.
|
||||
//!
|
||||
//! The second argument is the pointer type that will be used internally in the hook
|
||||
//! and the list configured from this hook.
|
||||
template< linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
class list_member_hook
|
||||
: private detail::list_node_traits<VoidPointer>::node
|
||||
{
|
||||
public:
|
||||
typedef detail::list_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef circular_list_algorithms<node_traits> node_algorithms;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef list_member_hook
|
||||
<Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type >::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type >::type const_this_type_ptr;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
list_member_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using list_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
list_member_hook(const list_member_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using list_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
list_member_hook& operator=(const list_member_hook& )
|
||||
{ return *this; }
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~list_member_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(list_member_hook& other)
|
||||
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether list::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
|
||||
//! The value_traits class is used as the first template argument for list.
|
||||
//! The template argument is a pointer to member pointing to the node in
|
||||
//! the class. Objects of type T and of types derived from T can be stored.
|
||||
//! T doesn't need to be copy-constructible or assignable.
|
||||
template<class T, this_type T::* M>
|
||||
struct value_traits
|
||||
: detail::member_value_traits<T, this_type, M>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return this_type_ptr(static_cast<this_type*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return const_this_type_ptr(static_cast<const this_type*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_LIST_HOOK_HPP
|
82
include/boost/intrusive/pointer_plus_bit.hpp
Normal file
82
include/boost/intrusive/pointer_plus_bit.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2007
|
||||
//
|
||||
// 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_POINTER_PLUS_BIT_HPP
|
||||
#define BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP
|
||||
|
||||
#include<boost/type_traits/alignment_of.hpp>
|
||||
#include<boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//!This trait class is used to know if a pointer
|
||||
//!can embed an extra bit of information if
|
||||
//!it's going to be used to point to objects
|
||||
//!with an alignment of "Alignment" bytes.
|
||||
template<class Pointer>
|
||||
struct has_pointer_plus_bit
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
//!This is an specialization for raw pointers.
|
||||
//!Raw pointers can embed an extra bit in the lower bit
|
||||
//!if the alignment is multiple of 2.
|
||||
|
||||
template<class T>
|
||||
struct has_pointer_plus_bit<T*>
|
||||
{
|
||||
enum { value = (boost::alignment_of<T>::value % 2u) == 0 };
|
||||
};
|
||||
|
||||
//!This is class that is supposed to have static methods
|
||||
//!to embed an extra bit of information in a pointer.
|
||||
//!This is a declaration and there is no default implementation,
|
||||
//!because operations to embed the bit change with every pointer type.
|
||||
//!
|
||||
//!An implementation that detects that a pointer type whose
|
||||
//!has_pointer_plus_bit<>::value is non-zero can make use of these
|
||||
//!operations to embed the bit in the pointer.
|
||||
template<class Pointer>
|
||||
struct pointer_plus_bit;
|
||||
|
||||
//!This is the specialization to embed an extra bit of information
|
||||
//!in a raw pointer. The extra bit is stored in the lower bit of the pointer.
|
||||
template<class T>
|
||||
struct pointer_plus_bit<T*>
|
||||
{
|
||||
typedef T* pointer;
|
||||
|
||||
//Check that the pointer can embed the bit
|
||||
BOOST_STATIC_ASSERT((has_pointer_plus_bit<T*>::value));
|
||||
|
||||
static pointer get_pointer(pointer n)
|
||||
{ return pointer(std::size_t(n) & std::size_t(~1u)); }
|
||||
|
||||
static void set_pointer(pointer &n, pointer p)
|
||||
{
|
||||
assert(0 == (std::size_t(p) & std::size_t(1u)));
|
||||
n = pointer(std::size_t(p) | (std::size_t(n) & std::size_t(1u)));
|
||||
}
|
||||
|
||||
static bool get_bit(pointer n)
|
||||
{ return (std::size_t(n) & std::size_t(1u)) != 0; }
|
||||
|
||||
static void set_bit(pointer &n, bool c)
|
||||
{ n = pointer(std::size_t(get_pointer(n)) | std::size_t(c)); }
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#endif //BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP
|
1141
include/boost/intrusive/rbtree.hpp
Normal file
1141
include/boost/intrusive/rbtree.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1165
include/boost/intrusive/rbtree_algorithms.hpp
Normal file
1165
include/boost/intrusive/rbtree_algorithms.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1714
include/boost/intrusive/set.hpp
Normal file
1714
include/boost/intrusive/set.hpp
Normal file
File diff suppressed because it is too large
Load Diff
367
include/boost/intrusive/set_hook.hpp
Normal file
367
include/boost/intrusive/set_hook.hpp
Normal file
@ -0,0 +1,367 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_SET_HOOK_HPP
|
||||
#define BOOST_INTRUSIVE_SET_HOOK_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/detail/rbtree_node.hpp>
|
||||
#include <boost/intrusive/rbtree_algorithms.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/tag.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//! Derive a class from set_base_hook in order to store objects in
|
||||
//! in an set/multiset. set_base_hook holds the data necessary to maintain
|
||||
//! the set/multiset and provides an appropriate value_traits class for set/multiset.
|
||||
//!
|
||||
//! The first integer template argument defines a tag to identify the node.
|
||||
//! The same tag value can be used in different classes, but if a class is
|
||||
//! derived from more than one set_base_hook, then each set_base_hook needs its
|
||||
//! unique tag.
|
||||
//!
|
||||
//! The second boolean template parameter will specify the linking mode of the hook.
|
||||
//!
|
||||
//! The third argument is the pointer type that will be used internally in the hook
|
||||
//! and the set/multiset configured from this hook.
|
||||
template< class Tag //= tag
|
||||
, linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
class set_base_hook
|
||||
: private detail::rbtree_node_traits<VoidPointer>::node
|
||||
{
|
||||
public:
|
||||
typedef detail::rbtree_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef rbtree_algorithms<node_traits> node_algorithms;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef set_base_hook
|
||||
<Tag, Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type>::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type>::type const_this_type_ptr;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
set_base_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using set_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
set_base_hook(const set_base_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using set_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
set_base_hook& operator=(const set_base_hook& )
|
||||
{ return *this; }
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~set_base_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether set::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink_and_rebalance(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
|
||||
//! The value_traits class is used as the first template argument for multiset.
|
||||
//! The template argument T defines the class type stored in multiset. Objects
|
||||
//! of type T and of types derived from T can be stored. T don't need to be
|
||||
//! copy-constructible or assignable.
|
||||
template<class T>
|
||||
struct value_traits
|
||||
: detail::derivation_value_traits<T, this_type, Tag>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return this_type_ptr(static_cast<set_base_hook*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return const_this_type_ptr(static_cast<const set_base_hook*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
};
|
||||
|
||||
//! Put a public data member set_member_hook in order to store objects of this class in
|
||||
//! an set/multiset. set_member_hook holds the data necessary for maintaining the
|
||||
//! set/multiset and provides an appropriate value_traits class for set/multiset.
|
||||
//!
|
||||
//! The first boolean template parameter will specify the linking mode of the hook.
|
||||
//!
|
||||
//! The second argument is the pointer type that will be used internally in the hook
|
||||
//! and the set/multiset configured from this hook.
|
||||
template< linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
class set_member_hook
|
||||
: private detail::rbtree_node_traits<VoidPointer>::node
|
||||
{
|
||||
public:
|
||||
typedef detail::rbtree_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef rbtree_algorithms<node_traits> node_algorithms;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef set_member_hook
|
||||
<Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type >::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type >::type const_this_type_ptr;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
set_member_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using set_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work.
|
||||
set_member_hook(const set_member_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using set_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work.
|
||||
set_member_hook& operator=(const set_member_hook& )
|
||||
{ return *this; }
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~set_member_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink_and_rebalance(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
|
||||
//! The value_traits class is used as the first template argument for multiset.
|
||||
//! The template argument is a pointer to member pointing to the node in
|
||||
//! the class. Objects of type T and of types derived from T can be stored.
|
||||
//! T don't need to be copy-constructible or assignable.
|
||||
template<class T, this_type T::* P>
|
||||
struct value_traits
|
||||
: detail::member_value_traits<T, this_type, P>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return this_type_ptr(static_cast<this_type*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return const_this_type_ptr(static_cast<const this_type*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_SET_HOOK_HPP
|
1428
include/boost/intrusive/slist.hpp
Normal file
1428
include/boost/intrusive/slist.hpp
Normal file
File diff suppressed because it is too large
Load Diff
407
include/boost/intrusive/slist_hook.hpp
Normal file
407
include/boost/intrusive/slist_hook.hpp
Normal file
@ -0,0 +1,407 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_SLIST_HOOK_HPP
|
||||
#define BOOST_INTRUSIVE_SLIST_HOOK_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/detail/slist_node.hpp>
|
||||
#include <boost/intrusive/circular_slist_algorithms.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/tag.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//! Derive a class from slist_base_hook in order to store objects in
|
||||
//! in an slist. slist_base_hook holds the data necessary to maintain the
|
||||
//! list and provides an appropriate value_traits class for slist.
|
||||
//!
|
||||
//! The first integer template argument defines a tag to identify the node.
|
||||
//! The same tag value can be used in different classes, but if a class is
|
||||
//! derived from more than one slist_base_hook, then each slist_base_hook needs its
|
||||
//! unique tag.
|
||||
//!
|
||||
//! The second boolean template parameter will specify the linking mode of the hook.
|
||||
//!
|
||||
//! The third argument is the pointer type that will be used internally in the hook
|
||||
//! and the slist configured from this hook.
|
||||
template< class Tag //= tag
|
||||
, linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
class slist_base_hook
|
||||
: private detail::slist_node_traits<VoidPointer>::node
|
||||
{
|
||||
public:
|
||||
typedef detail::slist_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef circular_slist_algorithms<node_traits> node_algorithms;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef slist_base_hook
|
||||
<Tag, Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type>::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type>::type const_this_type_ptr;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
slist_base_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using slist_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
slist_base_hook(const slist_base_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using slist_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
slist_base_hook& operator=(const slist_base_hook& )
|
||||
{ return *this; }
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~slist_base_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(slist_base_hook &other)
|
||||
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether list::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
|
||||
//! The value_traits class is used as the first template argument for list.
|
||||
//! The template argument T defines the class type stored in list. Objects
|
||||
//! of type T and of types derived from T can be stored. T doesn't need to be
|
||||
//! copy-constructible or assignable.
|
||||
template<class T>
|
||||
struct value_traits
|
||||
: detail::derivation_value_traits<T, this_type, Tag>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return this_type_ptr(static_cast<slist_base_hook*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return const_this_type_ptr(static_cast<const slist_base_hook*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
};
|
||||
|
||||
//! Put a public data member slist_member_hook in order to store objects of this class in
|
||||
//! an slist. slist_member_hook holds the data necessary for maintaining the list and
|
||||
//! provides an appropriate value_traits class for slist.
|
||||
//!
|
||||
//! The template argument T defines the class type stored in slist. Objects of type
|
||||
//! T and of types derived from T can be stored. T doesn't need to be
|
||||
//! copy-constructible or assignable.
|
||||
//!
|
||||
//! The second boolean template parameter will specify the linking mode of the hook.
|
||||
//!
|
||||
//! The third argument is the pointer type that will be used internally in the hook
|
||||
//! and the slist configured from this hook.
|
||||
template< linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
class slist_member_hook
|
||||
: private detail::slist_node_traits<VoidPointer>::node
|
||||
{
|
||||
public:
|
||||
typedef detail::slist_node_traits<VoidPointer> node_traits;
|
||||
enum { linking_policy = Policy };
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef circular_slist_algorithms<node_traits> node_algorithms;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef slist_member_hook
|
||||
<Policy, VoidPointer> this_type;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type >::type this_type_ptr;
|
||||
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type >::type const_this_type_ptr;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
node_ptr this_as_node()
|
||||
{ return node_ptr(static_cast<node *const>(this)); }
|
||||
|
||||
const_node_ptr this_as_node() const
|
||||
{ return const_node_ptr(static_cast<const node *const>(this)); }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
slist_member_hook()
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using slist_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
slist_member_hook(const slist_member_hook& )
|
||||
: node()
|
||||
{
|
||||
if(Policy == safe_link || Policy == auto_unlink){
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using slist_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
slist_member_hook& operator=(const slist_member_hook& )
|
||||
{ return *this; }
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~slist_member_hook()
|
||||
{ detail::destructor_impl(*this, detail::dispatcher<Policy>()); }
|
||||
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(slist_member_hook& other)
|
||||
{ node_algorithms::swap_nodes(this_as_node(), other.this_as_node()); }
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether list::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{
|
||||
//is_linked() can be only used in safe-mode or auto-unlink
|
||||
BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink));
|
||||
return !node_algorithms::unique(this_as_node());
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{
|
||||
BOOST_STATIC_ASSERT((Policy == auto_unlink));
|
||||
node_algorithms::unlink(this_as_node());
|
||||
node_algorithms::init(this_as_node());
|
||||
}
|
||||
|
||||
//! The value_traits class is used as the first template argument for list.
|
||||
//! The template argument is a pointer to member pointing to the node in
|
||||
//! the class. Objects of type T and of types derived from T can be stored.
|
||||
//! T doesn't need to be copy-constructible or assignable.
|
||||
template<class T, this_type T::* M>
|
||||
struct value_traits
|
||||
: detail::member_value_traits<T, this_type, M>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return this_type_ptr(static_cast<this_type*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return const_this_type_ptr(static_cast<const this_type*> (get_pointer(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return this_as_node(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return this_as_node(); }
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include<boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_SLIST_HOOK_HPP
|
26
include/boost/intrusive/tag.hpp
Normal file
26
include/boost/intrusive/tag.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_DEFAULT_TAG_HPP
|
||||
#define BOOST_INTRUSIVE_DEFAULT_TAG_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//!This is the declaration of the default
|
||||
//!hook used by base hooks
|
||||
class tag;
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#endif //BOOST_INTRUSIVE_DEFAULT_TAG_HPP
|
1761
include/boost/intrusive/unordered_set.hpp
Normal file
1761
include/boost/intrusive/unordered_set.hpp
Normal file
File diff suppressed because it is too large
Load Diff
297
include/boost/intrusive/unordered_set_hook.hpp
Normal file
297
include/boost/intrusive/unordered_set_hook.hpp
Normal file
@ -0,0 +1,297 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztañaga 2006-2007
|
||||
//
|
||||
// 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_HASHSET_HOOK_HPP
|
||||
#define BOOST_INTRUSIVE_HASHSET_HOOK_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/detail/pointer_type.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include <boost/intrusive/slist_hook.hpp>
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//! Derive a class from unordered_set_base_hook in order to store objects in
|
||||
//! in an unordered_set/unordered_multi_set. unordered_set_base_hook holds the data necessary to maintain
|
||||
//! the unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set.
|
||||
//!
|
||||
//! The first integer template argument defines a tag to identify the node.
|
||||
//! The same tag value can be used in different classes, but if a class is
|
||||
//! derived from more than one unordered_set_base_hook, then each unordered_set_base_hook needs its
|
||||
//! unique tag.
|
||||
//!
|
||||
//! The second boolean template parameter will specify the linking mode of the hook.
|
||||
//!
|
||||
//! The third argument is the pointer type that will be used internally in the hook
|
||||
//! and the unordered_set/unordered_multi_set configured from this hook.
|
||||
template< class Tag //= tag
|
||||
, linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
class unordered_set_base_hook
|
||||
{
|
||||
/// @cond
|
||||
typedef slist_base_hook<Tag, Policy, VoidPointer> IsListHook;
|
||||
IsListHook m_slisthook;
|
||||
typedef IsListHook implementation_defined;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
enum { linking_policy = Policy };
|
||||
typedef typename implementation_defined::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef unordered_set_base_hook
|
||||
<Tag, Policy, VoidPointer> this_type;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type>::type this_type_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type>::type const_this_type_ptr;
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
unordered_set_base_hook()
|
||||
: m_slisthook()
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using unordered_set_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
unordered_set_base_hook(const unordered_set_base_hook &other)
|
||||
: m_slisthook(other.m_slisthook)
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using unordered_set_base_hook STL-compliant without forcing the
|
||||
//! user to do some additional work. "swap" can be used to emulate
|
||||
//! move-semantics.
|
||||
unordered_set_base_hook& operator=(const unordered_set_base_hook &other)
|
||||
{ return *this; }
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~unordered_set_base_hook()
|
||||
{} //m_slisthook's destructor does the job
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether unordered_set/unordered_multiset::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{ return m_slisthook.is_linked(); }
|
||||
|
||||
//! The value_traits class is used as the first template argument for unordered_set/unordered_multiset.
|
||||
//! The template argument T defines the class type stored in unordered_set/unordered_multiset. Objects
|
||||
//! of type T and of types derived from T can be stored. T doesn't need to be
|
||||
//! copy-constructible or assignable.
|
||||
template<class T>
|
||||
struct value_traits
|
||||
: detail::derivation_value_traits<T, this_type, Tag>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return this_type_ptr((this_type*)get_pointer(IsListHook::to_hook_ptr(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return const_this_type_ptr((const this_type*)get_pointer(IsListHook::to_hook_ptr(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return m_slisthook.to_node_ptr(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return m_slisthook.to_node_ptr(); }
|
||||
};
|
||||
|
||||
//! Put a public data member unordered_set_member_hook in order to store objects of this class in
|
||||
//! an unordered_set/unordered_multi_set. unordered_set_member_hook holds the data necessary for maintaining the
|
||||
//! unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set.
|
||||
//!
|
||||
//! The first boolean template parameter will specify the linking mode of the hook.
|
||||
//!
|
||||
//! The second argument is the pointer type that will be used internally in the hook
|
||||
//! and the unordered_set/unordered_multi_set configured from this hook.
|
||||
template< linking_policy Policy //= safe_link
|
||||
, class VoidPointer //= void *
|
||||
>
|
||||
class unordered_set_member_hook
|
||||
{
|
||||
/// @cond
|
||||
typedef slist_member_hook<Policy, VoidPointer> IsListHook;
|
||||
IsListHook m_slisthook;
|
||||
typedef IsListHook implementation_defined;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
enum { linking_policy = Policy };
|
||||
typedef typename implementation_defined::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, node>::type node_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const node>::type const_node_ptr;
|
||||
typedef unordered_set_member_hook
|
||||
<Policy, VoidPointer> this_type;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, this_type>::type this_type_ptr;
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPointer, const this_type>::type const_this_type_ptr;
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
unordered_set_member_hook()
|
||||
: m_slisthook()
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: If Policy is auto_unlink or safe_mode_linnk
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using unordered_set_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work.
|
||||
unordered_set_member_hook(const unordered_set_member_hook &other)
|
||||
: m_slisthook(other.m_slisthook)
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using unordered_set_member_hook STL-compliant without forcing the
|
||||
//! user to do some additional work.
|
||||
unordered_set_member_hook& operator=(const unordered_set_member_hook &other)
|
||||
{ return *this; }
|
||||
|
||||
//! <b>Effects</b>: If Policy is normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If Policy is safe_link and the
|
||||
//! object is stored in an list an assertion is raised. If Policy is
|
||||
//! auto_unlink and "is_linked()" is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~unordered_set_member_hook()
|
||||
{} //m_slisthook's destructor does the job
|
||||
|
||||
//! <b>Precondition</b>: Policy must be safe_link or auto_unlink.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const
|
||||
{ return m_slisthook.is_linked(); }
|
||||
|
||||
//! The value_traits class is used as the first template argument for unordered_set/unordered_multiset.
|
||||
//! The template argument is a pointer to member pointing to the node in
|
||||
//! the class. Objects of type T and of types derived from T can be stored.
|
||||
//! T doesn't need to be copy-constructible or assignable.
|
||||
template<class T, this_type T::* M>
|
||||
struct value_traits
|
||||
: detail::member_value_traits<T, this_type, M>
|
||||
{};
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if Policy is auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink()
|
||||
{ m_slisthook.unlink(); }
|
||||
|
||||
//! <b>Effects</b>: Converts a pointer to a node into
|
||||
//! a pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static this_type_ptr to_hook_ptr(node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return this_type_ptr((this_type*)get_pointer(IsListHook::to_hook_ptr(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Converts a const pointer to a node stored in a container into
|
||||
//! a const pointer to the hook that holds that node.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static const_this_type_ptr to_hook_ptr(const_node_ptr p)
|
||||
{
|
||||
using boost::get_pointer;
|
||||
return const_this_type_ptr((const this_type*)get_pointer(IsListHook::to_hook_ptr(p)));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_ptr to_node_ptr()
|
||||
{ return m_slisthook.to_node_ptr(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const pointer to the node that this hook holds.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_node_ptr to_node_ptr() const
|
||||
{ return m_slisthook.to_node_ptr(); }
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_HASHSET_HOOK_HPP
|
Loading…
x
Reference in New Issue
Block a user