Merge pull request #4899 from sgiraudot/STL_Extension-Multiset_with_CC_allocation-GF

Surface Sweep: Enhance memory allocation with Compact Container
This commit is contained in:
Laurent Rineau 2020-11-05 08:49:36 +01:00
commit c45ac23ed6
6 changed files with 266 additions and 173 deletions

View File

@ -18,6 +18,7 @@
#include <CGAL/enum.h> #include <CGAL/enum.h>
#include <CGAL/memory.h> #include <CGAL/memory.h>
#include <CGAL/number_utils_classes.h> #include <CGAL/number_utils_classes.h>
#include <CGAL/Compact_container.h>
#include <iterator> #include <iterator>
namespace CGAL { namespace CGAL {
@ -50,7 +51,12 @@ namespace CGAL {
template <typename Type_, template <typename Type_,
class Compare_ = CGAL::Compare<Type_>, class Compare_ = CGAL::Compare<Type_>,
class Allocator_ = CGAL_ALLOCATOR(int)> class Allocator_ = CGAL_ALLOCATOR(int),
#ifdef CGAL_MULTISET_USE_COMPACT_CONTAINER_AS_DEFAULT
typename UseCompactContainer = Tag_true>
#else
typename UseCompactContainer = Tag_false>
#endif
class Multiset class Multiset
{ {
public: public:
@ -59,7 +65,8 @@ public:
typedef Type_ Type; typedef Type_ Type;
typedef Compare_ Compare; typedef Compare_ Compare;
typedef Allocator_ Allocator; typedef Allocator_ Allocator;
typedef Multiset<Type, Compare, Allocator> Self; typedef Multiset<Type, Compare, Allocator, UseCompactContainer>
Self;
// Type definitions for STL compatibility. // Type definitions for STL compatibility.
typedef Type value_type; typedef Type value_type;
@ -224,11 +231,64 @@ protected:
return (succP); return (succP);
} }
void* for_compact_container() const
{
return parentP;
}
void for_compact_container (void * p)
{
reinterpret_cast<void*&>(parentP) = p;
}
}; };
// Rebind the allocator to the Node type: // Rebind the allocator to the Node type:
typedef std::allocator_traits<Allocator> Allocator_traits; class Default_node_allocator
typedef typename Allocator_traits::template rebind_alloc<Node> Node_allocator; {
typedef std::allocator_traits<Allocator> Allocator_traits;
typedef typename Allocator_traits::template rebind_alloc<Node> Base;
Base base;
public:
Node* allocate (const Node& n)
{
Node* new_node = base.allocate(1);
std::allocator_traits<Base>::construct(base, new_node, n);
return new_node;
}
void deallocate (Node* n)
{
std::allocator_traits<Base>::destroy(base, n);
base.deallocate (n, 1);
}
};
class CC_node_allocator
{
typedef Compact_container<Node> Base;
Base base;
public:
Node* allocate (const Node& n)
{
Node* new_node = &*base.emplace(n);
return new_node;
}
void deallocate (Node* n)
{
base.erase (base.iterator_to(*n));
}
};
typedef typename std::conditional<UseCompactContainer::value,
CC_node_allocator,
Default_node_allocator>::type Node_allocator;
public: public:
@ -242,7 +302,7 @@ public:
class iterator class iterator
{ {
// Give the red-black tree class template access to the iterator's members. // Give the red-black tree class template access to the iterator's members.
friend class Multiset<Type, Compare, Allocator>; friend class Multiset<Type, Compare, Allocator, UseCompactContainer>;
friend class const_iterator; friend class const_iterator;
public: public:
@ -353,7 +413,7 @@ public:
class const_iterator class const_iterator
{ {
// Give the red-black tree class template access to the iterator's members. // Give the red-black tree class template access to the iterator's members.
friend class Multiset<Type, Compare, Allocator>; friend class Multiset<Type, Compare, Allocator, UseCompactContainer>;
public: public:
@ -1429,20 +1489,7 @@ protected:
* \return A pointer to the newly created node. * \return A pointer to the newly created node.
*/ */
Node* _allocate_node (const Type& object, Node* _allocate_node (const Type& object,
typename Node::Node_color color) typename Node::Node_color color);
#ifdef CGAL_CFG_OUTOFLINE_MEMBER_DEFINITION_BUG
{
CGAL_multiset_assertion (color != Node::DUMMY_BEGIN &&
color != Node::DUMMY_END);
Node* new_node = node_alloc.allocate(1);
std::allocator_traits<Node_allocator>::construct(node_alloc, new_node, beginNode);
new_node->init(object, color);
return (new_node);
}
#else
;
#endif
/*! /*!
* De-allocate a tree node. * De-allocate a tree node.
@ -1455,8 +1502,8 @@ protected:
//--------------------------------------------------------- //---------------------------------------------------------
// Default constructor. // Default constructor.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
Multiset<Type, Compare, Allocator>::Multiset () : Multiset<Type, Compare, Allocator, UseCompactContainer>::Multiset () :
rootP (nullptr), rootP (nullptr),
iSize (0), iSize (0),
iBlackHeight (0), iBlackHeight (0),
@ -1470,8 +1517,8 @@ Multiset<Type, Compare, Allocator>::Multiset () :
//--------------------------------------------------------- //---------------------------------------------------------
// Constructor with a pointer to comparison object. // Constructor with a pointer to comparison object.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
Multiset<Type, Compare, Allocator>::Multiset (const Compare& comp) : Multiset<Type, Compare, Allocator, UseCompactContainer>::Multiset (const Compare& comp) :
rootP (nullptr), rootP (nullptr),
iSize (0), iSize (0),
iBlackHeight (0), iBlackHeight (0),
@ -1485,8 +1532,8 @@ Multiset<Type, Compare, Allocator>::Multiset (const Compare& comp) :
//--------------------------------------------------------- //---------------------------------------------------------
// Copy constructor. // Copy constructor.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
Multiset<Type, Compare, Allocator>::Multiset (const Self& tree) : Multiset<Type, Compare, Allocator, UseCompactContainer>::Multiset (const Self& tree) :
rootP (nullptr), rootP (nullptr),
iSize (tree.iSize), iSize (tree.iSize),
iBlackHeight (tree.iBlackHeight), iBlackHeight (tree.iBlackHeight),
@ -1517,9 +1564,12 @@ Multiset<Type, Compare, Allocator>::Multiset (const Self& tree) :
//--------------------------------------------------------- //---------------------------------------------------------
// Destructor. // Destructor.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
Multiset<Type, Compare, Allocator>::~Multiset () Multiset<Type, Compare, Allocator, UseCompactContainer>::~Multiset ()
{ {
if (UseCompactContainer::value)
return;
// Delete the entire tree recursively. // Delete the entire tree recursively.
if (rootP != nullptr) if (rootP != nullptr)
_destroy (rootP); _destroy (rootP);
@ -1532,9 +1582,9 @@ Multiset<Type, Compare, Allocator>::~Multiset ()
//--------------------------------------------------------- //---------------------------------------------------------
// Assignment operator. // Assignment operator.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
Multiset<Type, Compare, Allocator>& Multiset<Type, Compare, Allocator, UseCompactContainer>&
Multiset<Type, Compare, Allocator>::operator= (const Self& tree) Multiset<Type, Compare, Allocator, UseCompactContainer>::operator= (const Self& tree)
{ {
// Avoid self-assignment. // Avoid self-assignment.
if (this == &tree) if (this == &tree)
@ -1570,8 +1620,8 @@ Multiset<Type, Compare, Allocator>::operator= (const Self& tree)
//--------------------------------------------------------- //---------------------------------------------------------
// Swap two trees (replace their contents). // Swap two trees (replace their contents).
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::swap (Self& tree) void Multiset<Type, Compare, Allocator, UseCompactContainer>::swap (Self& tree)
{ {
// Avoid self-swapping. // Avoid self-swapping.
if (this == &tree) if (this == &tree)
@ -1613,8 +1663,8 @@ void Multiset<Type, Compare, Allocator>::swap (Self& tree)
//--------------------------------------------------------- //---------------------------------------------------------
// Test two trees for equality. // Test two trees for equality.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
bool Multiset<Type,Compare,Allocator>::operator== (const Self& tree) const bool Multiset<Type,Compare,Allocator,UseCompactContainer>::operator== (const Self& tree) const
{ {
// The sizes of the two trees must be the same. // The sizes of the two trees must be the same.
if (size() != tree.size()) if (size() != tree.size())
@ -1640,8 +1690,8 @@ bool Multiset<Type,Compare,Allocator>::operator== (const Self& tree) const
//--------------------------------------------------------- //---------------------------------------------------------
// Check if our tree is lexicographically smaller that a given tree. // Check if our tree is lexicographically smaller that a given tree.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
bool Multiset<Type,Compare,Allocator>::operator< (const Self& tree) const bool Multiset<Type,Compare,Allocator,UseCompactContainer>::operator< (const Self& tree) const
{ {
// Go over all elements in both tree and compare them pairwise. // Go over all elements in both tree and compare them pairwise.
const_iterator it1 = this->begin(); const_iterator it1 = this->begin();
@ -1680,9 +1730,9 @@ bool Multiset<Type,Compare,Allocator>::operator< (const Self& tree) const
//--------------------------------------------------------- //---------------------------------------------------------
// Get an iterator for the minimum object in the tree (non-const version). // Get an iterator for the minimum object in the tree (non-const version).
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
inline typename Multiset<Type,Compare,Allocator>::iterator inline typename Multiset<Type,Compare,Allocator,UseCompactContainer>::iterator
Multiset<Type, Compare, Allocator>::begin () Multiset<Type, Compare, Allocator, UseCompactContainer>::begin ()
{ {
if (beginNode.parentP != nullptr) if (beginNode.parentP != nullptr)
return (iterator (beginNode.parentP)); return (iterator (beginNode.parentP));
@ -1693,9 +1743,9 @@ Multiset<Type, Compare, Allocator>::begin ()
//--------------------------------------------------------- //---------------------------------------------------------
// Get a past-the-end iterator for the tree objects (non-const version). // Get a past-the-end iterator for the tree objects (non-const version).
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
inline typename Multiset<Type, Compare,Allocator>::iterator inline typename Multiset<Type, Compare,Allocator, UseCompactContainer>::iterator
Multiset<Type, Compare, Allocator>::end () Multiset<Type, Compare, Allocator, UseCompactContainer>::end ()
{ {
return (iterator (&endNode)); return (iterator (&endNode));
} }
@ -1703,9 +1753,9 @@ Multiset<Type, Compare, Allocator>::end ()
//--------------------------------------------------------- //---------------------------------------------------------
// Get an iterator for the minimum object in the tree (const version). // Get an iterator for the minimum object in the tree (const version).
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
inline typename Multiset<Type,Compare,Allocator>::const_iterator inline typename Multiset<Type,Compare,Allocator,UseCompactContainer>::const_iterator
Multiset<Type, Compare, Allocator>::begin () const Multiset<Type, Compare, Allocator, UseCompactContainer>::begin () const
{ {
if (beginNode.parentP != nullptr) if (beginNode.parentP != nullptr)
return (const_iterator (beginNode.parentP)); return (const_iterator (beginNode.parentP));
@ -1716,9 +1766,9 @@ Multiset<Type, Compare, Allocator>::begin () const
//--------------------------------------------------------- //---------------------------------------------------------
// Get a past-the-end iterator for the tree objects (const version). // Get a past-the-end iterator for the tree objects (const version).
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
inline typename Multiset<Type,Compare,Allocator>::const_iterator inline typename Multiset<Type,Compare,Allocator,UseCompactContainer>::const_iterator
Multiset<Type, Compare, Allocator>::end () const Multiset<Type, Compare, Allocator, UseCompactContainer>::end () const
{ {
return (const_iterator (&endNode)); return (const_iterator (&endNode));
} }
@ -1727,9 +1777,9 @@ Multiset<Type, Compare, Allocator>::end () const
// Get a reverse iterator for the maxnimum object in the tree // Get a reverse iterator for the maxnimum object in the tree
// (non-const version). // (non-const version).
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
inline typename Multiset<Type,Compare,Allocator>::reverse_iterator inline typename Multiset<Type,Compare,Allocator,UseCompactContainer>::reverse_iterator
Multiset<Type, Compare, Allocator>::rbegin () Multiset<Type, Compare, Allocator, UseCompactContainer>::rbegin ()
{ {
return (reverse_iterator (end())); return (reverse_iterator (end()));
} }
@ -1738,9 +1788,9 @@ Multiset<Type, Compare, Allocator>::rbegin ()
// Get a pre-the-begin reverse iterator for the tree objects // Get a pre-the-begin reverse iterator for the tree objects
// (non-const version). // (non-const version).
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
inline typename Multiset<Type,Compare,Allocator>::reverse_iterator inline typename Multiset<Type,Compare,Allocator,UseCompactContainer>::reverse_iterator
Multiset<Type, Compare, Allocator>::rend () Multiset<Type, Compare, Allocator, UseCompactContainer>::rend ()
{ {
return (reverse_iterator (begin())); return (reverse_iterator (begin()));
} }
@ -1748,9 +1798,9 @@ Multiset<Type, Compare, Allocator>::rend ()
//--------------------------------------------------------- //---------------------------------------------------------
// Get a reverse iterator for the maximum object in the tree (const version). // Get a reverse iterator for the maximum object in the tree (const version).
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
inline typename Multiset<Type,Compare,Allocator>::const_reverse_iterator inline typename Multiset<Type,Compare,Allocator,UseCompactContainer>::const_reverse_iterator
Multiset<Type, Compare, Allocator>::rbegin () const Multiset<Type, Compare, Allocator, UseCompactContainer>::rbegin () const
{ {
return (const_reverse_iterator (end())); return (const_reverse_iterator (end()));
} }
@ -1758,9 +1808,9 @@ Multiset<Type, Compare, Allocator>::rbegin () const
//--------------------------------------------------------- //---------------------------------------------------------
// Get a pre-the-begin reverse iterator for the tree objects (const version). // Get a pre-the-begin reverse iterator for the tree objects (const version).
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
inline typename Multiset<Type,Compare,Allocator>::const_reverse_iterator inline typename Multiset<Type,Compare,Allocator,UseCompactContainer>::const_reverse_iterator
Multiset<Type, Compare, Allocator>::rend () const Multiset<Type, Compare, Allocator, UseCompactContainer>::rend () const
{ {
return (const_reverse_iterator (begin())); return (const_reverse_iterator (begin()));
} }
@ -1768,8 +1818,8 @@ Multiset<Type, Compare, Allocator>::rend () const
//--------------------------------------------------------- //---------------------------------------------------------
// Get the size of the tree. // Get the size of the tree.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
size_t Multiset<Type, Compare, Allocator>::size () const size_t Multiset<Type, Compare, Allocator, UseCompactContainer>::size () const
{ {
if (rootP == nullptr) if (rootP == nullptr)
// The tree is empty: // The tree is empty:
@ -1798,9 +1848,9 @@ size_t Multiset<Type, Compare, Allocator>::size () const
//--------------------------------------------------------- //---------------------------------------------------------
// Insert a new object to the tree. // Insert a new object to the tree.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
typename Multiset<Type, Compare, Allocator>::iterator typename Multiset<Type, Compare, Allocator, UseCompactContainer>::iterator
Multiset<Type, Compare, Allocator>::insert (const Type& object) Multiset<Type, Compare, Allocator, UseCompactContainer>::insert (const Type& object)
{ {
if (rootP == nullptr) if (rootP == nullptr)
{ {
@ -1897,9 +1947,9 @@ Multiset<Type, Compare, Allocator>::insert (const Type& object)
//--------------------------------------------------------- //---------------------------------------------------------
// Insert an object to the tree, with a given hint to its position. // Insert an object to the tree, with a given hint to its position.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
typename Multiset<Type, Compare, Allocator>::iterator typename Multiset<Type, Compare, Allocator, UseCompactContainer>::iterator
Multiset<Type, Compare, Allocator>::insert (iterator position, Multiset<Type, Compare, Allocator, UseCompactContainer>::insert (iterator position,
const Type& object) const Type& object)
{ {
Node *nodeP = position.nodeP; Node *nodeP = position.nodeP;
@ -1973,9 +2023,9 @@ Multiset<Type, Compare, Allocator>::insert (iterator position,
//--------------------------------------------------------- //---------------------------------------------------------
// Insert a new object to the tree as the a successor of a given node. // Insert a new object to the tree as the a successor of a given node.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
typename Multiset<Type, Compare, Allocator>::iterator typename Multiset<Type, Compare, Allocator, UseCompactContainer>::iterator
Multiset<Type, Compare, Allocator>::insert_after (iterator position, Multiset<Type, Compare, Allocator, UseCompactContainer>::insert_after (iterator position,
const Type& object) const Type& object)
{ {
Node *nodeP = position.nodeP; Node *nodeP = position.nodeP;
@ -2071,9 +2121,9 @@ Multiset<Type, Compare, Allocator>::insert_after (iterator position,
//--------------------------------------------------------- //---------------------------------------------------------
// Insert a new object to the tree as the a predecessor of a given node. // Insert a new object to the tree as the a predecessor of a given node.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
typename Multiset<Type, Compare, Allocator>::iterator typename Multiset<Type, Compare, Allocator, UseCompactContainer>::iterator
Multiset<Type, Compare, Allocator>::insert_before (iterator position, Multiset<Type, Compare, Allocator, UseCompactContainer>::insert_before (iterator position,
const Type& object) const Type& object)
{ {
Node *nodeP = position.nodeP; Node *nodeP = position.nodeP;
@ -2169,8 +2219,8 @@ Multiset<Type, Compare, Allocator>::insert_before (iterator position,
//--------------------------------------------------------- //---------------------------------------------------------
// Remove an object from the tree. // Remove an object from the tree.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
size_t Multiset<Type, Compare, Allocator>::erase (const Type& object) size_t Multiset<Type, Compare, Allocator, UseCompactContainer>::erase (const Type& object)
{ {
// Find the first node containing an object not less than the object to // Find the first node containing an object not less than the object to
// be erased and from there look for objects equivalent to the given object. // be erased and from there look for objects equivalent to the given object.
@ -2201,8 +2251,8 @@ size_t Multiset<Type, Compare, Allocator>::erase (const Type& object)
//--------------------------------------------------------- //---------------------------------------------------------
// Remove the object pointed by the given iterator. // Remove the object pointed by the given iterator.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::erase (iterator position) void Multiset<Type, Compare, Allocator, UseCompactContainer>::erase (iterator position)
{ {
Node *nodeP = position.nodeP; Node *nodeP = position.nodeP;
@ -2215,8 +2265,8 @@ void Multiset<Type, Compare, Allocator>::erase (iterator position)
//--------------------------------------------------------- //---------------------------------------------------------
// Remove all objects from the tree. // Remove all objects from the tree.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::clear () void Multiset<Type, Compare, Allocator, UseCompactContainer>::clear ()
{ {
// Delete all the tree nodes recursively. // Delete all the tree nodes recursively.
if (rootP != nullptr) if (rootP != nullptr)
@ -2236,8 +2286,8 @@ void Multiset<Type, Compare, Allocator>::clear ()
//--------------------------------------------------------- //---------------------------------------------------------
// Replace the object pointed by a given iterator with another object. // Replace the object pointed by a given iterator with another object.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::replace (iterator position, void Multiset<Type, Compare, Allocator, UseCompactContainer>::replace (iterator position,
const Type& object) const Type& object)
{ {
Node *nodeP = position.nodeP; Node *nodeP = position.nodeP;
@ -2264,8 +2314,8 @@ void Multiset<Type, Compare, Allocator>::replace (iterator position,
//--------------------------------------------------------- //---------------------------------------------------------
// Swap the location two objects in the tree, given by their positions. // Swap the location two objects in the tree, given by their positions.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::swap (iterator pos1, void Multiset<Type, Compare, Allocator, UseCompactContainer>::swap (iterator pos1,
iterator pos2) iterator pos2)
{ {
Node *node1_P = pos1.nodeP; Node *node1_P = pos1.nodeP;
@ -2310,8 +2360,8 @@ void Multiset<Type, Compare, Allocator>::swap (iterator pos1,
//--------------------------------------------------------- //---------------------------------------------------------
// Check if the tree is a valid one. // Check if the tree is a valid one.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
bool Multiset<Type, Compare, Allocator>::is_valid () const bool Multiset<Type, Compare, Allocator, UseCompactContainer>::is_valid () const
{ {
if (rootP == nullptr) if (rootP == nullptr)
{ {
@ -2362,8 +2412,8 @@ bool Multiset<Type, Compare, Allocator>::is_valid () const
//--------------------------------------------------------- //---------------------------------------------------------
// Get the height of the tree. // Get the height of the tree.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
size_t Multiset<Type, Compare, Allocator>::height () const size_t Multiset<Type, Compare, Allocator, UseCompactContainer>::height () const
{ {
if (rootP == nullptr) if (rootP == nullptr)
// Empty tree. // Empty tree.
@ -2376,8 +2426,8 @@ size_t Multiset<Type, Compare, Allocator>::height () const
//--------------------------------------------------------- //---------------------------------------------------------
// Catenate the tree with another given tree. // Catenate the tree with another given tree.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::catenate (Self& tree) void Multiset<Type, Compare, Allocator, UseCompactContainer>::catenate (Self& tree)
{ {
// Get the maximal node in our tree and the minimal node in the other tree. // Get the maximal node in our tree and the minimal node in the other tree.
Node *max1_P = endNode.parentP; Node *max1_P = endNode.parentP;
@ -2614,8 +2664,8 @@ void Multiset<Type, Compare, Allocator>::catenate (Self& tree)
// in the range [begin, position) and all objects in the range // in the range [begin, position) and all objects in the range
// [position, end) form a new output tree. // [position, end) form a new output tree.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::split (iterator position, void Multiset<Type, Compare, Allocator, UseCompactContainer>::split (iterator position,
Self& tree) Self& tree)
{ {
CGAL_multiset_precondition (tree.empty()); CGAL_multiset_precondition (tree.empty());
@ -3032,8 +3082,8 @@ void Multiset<Type, Compare, Allocator>::split (iterator position,
// Move the contents of one tree to another without actually duplicating // Move the contents of one tree to another without actually duplicating
// the nodes. This operation also clears the copied tree. // the nodes. This operation also clears the copied tree.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::_shallow_assign (Self& tree) void Multiset<Type, Compare, Allocator, UseCompactContainer>::_shallow_assign (Self& tree)
{ {
// Copy the assigned tree properties. // Copy the assigned tree properties.
rootP = tree.rootP; rootP = tree.rootP;
@ -3060,8 +3110,8 @@ void Multiset<Type, Compare, Allocator>::_shallow_assign (Self& tree)
//--------------------------------------------------------- //---------------------------------------------------------
// Clear the properties of the tree, without actually deallocating its nodes. // Clear the properties of the tree, without actually deallocating its nodes.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::_shallow_clear () void Multiset<Type, Compare, Allocator, UseCompactContainer>::_shallow_clear ()
{ {
rootP = nullptr; rootP = nullptr;
iSize = 0; iSize = 0;
@ -3075,8 +3125,8 @@ void Multiset<Type, Compare, Allocator>::_shallow_clear ()
//--------------------------------------------------------- //---------------------------------------------------------
// Remove the given tree node. // Remove the given tree node.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::_remove_at (Node* nodeP) void Multiset<Type, Compare, Allocator, UseCompactContainer>::_remove_at (Node* nodeP)
{ {
CGAL_multiset_precondition (_is_valid (nodeP)); CGAL_multiset_precondition (_is_valid (nodeP));
@ -3191,8 +3241,8 @@ void Multiset<Type, Compare, Allocator>::_remove_at (Node* nodeP)
//--------------------------------------------------------- //---------------------------------------------------------
// Swap the location two nodes in the tree. // Swap the location two nodes in the tree.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::_swap (Node* node1_P, void Multiset<Type, Compare, Allocator, UseCompactContainer>::_swap (Node* node1_P,
Node* node2_P) Node* node2_P)
{ {
CGAL_multiset_assertion (_is_valid (node1_P)); CGAL_multiset_assertion (_is_valid (node1_P));
@ -3332,8 +3382,8 @@ void Multiset<Type, Compare, Allocator>::_swap (Node* node1_P,
//--------------------------------------------------------- //---------------------------------------------------------
// Swap the location two sibling nodes in the tree. // Swap the location two sibling nodes in the tree.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::_swap_siblings (Node* node1_P, void Multiset<Type, Compare, Allocator, UseCompactContainer>::_swap_siblings (Node* node1_P,
Node* node2_P) Node* node2_P)
{ {
CGAL_multiset_assertion (_is_valid (node1_P)); CGAL_multiset_assertion (_is_valid (node1_P));
@ -3408,8 +3458,8 @@ void Multiset<Type, Compare, Allocator>::_swap_siblings (Node* node1_P,
//--------------------------------------------------------- //---------------------------------------------------------
// Calculate the height of the subtree spanned by a given node. // Calculate the height of the subtree spanned by a given node.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
size_t Multiset<Type, Compare, Allocator>::_sub_height size_t Multiset<Type, Compare, Allocator, UseCompactContainer>::_sub_height
(const Node* nodeP) const (const Node* nodeP) const
{ {
CGAL_multiset_assertion (_is_valid (nodeP)); CGAL_multiset_assertion (_is_valid (nodeP));
@ -3432,8 +3482,8 @@ size_t Multiset<Type, Compare, Allocator>::_sub_height
//--------------------------------------------------------- //---------------------------------------------------------
// Calculate the height of the subtree spanned by a given node. // Calculate the height of the subtree spanned by a given node.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
bool Multiset<Type, Compare, Allocator>::_sub_is_valid bool Multiset<Type, Compare, Allocator, UseCompactContainer>::_sub_is_valid
(const Node* nodeP, (const Node* nodeP,
size_t& sub_size, size_t& sub_size,
size_t& sub_bh) const size_t& sub_bh) const
@ -3496,9 +3546,9 @@ bool Multiset<Type, Compare, Allocator>::_sub_is_valid
//--------------------------------------------------------- //---------------------------------------------------------
// Get the leftmost node in the sub-tree spanned by the given node. // Get the leftmost node in the sub-tree spanned by the given node.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
typename Multiset<Type, Compare, Allocator>::Node* typename Multiset<Type, Compare, Allocator, UseCompactContainer>::Node*
Multiset<Type, Compare, Allocator>::_sub_minimum (Node* nodeP) const Multiset<Type, Compare, Allocator, UseCompactContainer>::_sub_minimum (Node* nodeP) const
{ {
CGAL_multiset_assertion (_is_valid (nodeP)); CGAL_multiset_assertion (_is_valid (nodeP));
@ -3512,9 +3562,9 @@ Multiset<Type, Compare, Allocator>::_sub_minimum (Node* nodeP) const
//--------------------------------------------------------- //---------------------------------------------------------
// Get the rightmost node in the sub-tree spanned by the given node. // Get the rightmost node in the sub-tree spanned by the given node.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
typename Multiset<Type, Compare, Allocator>::Node* typename Multiset<Type, Compare, Allocator, UseCompactContainer>::Node*
Multiset<Type, Compare, Allocator>::_sub_maximum (Node* nodeP) const Multiset<Type, Compare, Allocator, UseCompactContainer>::_sub_maximum (Node* nodeP) const
{ {
CGAL_multiset_assertion (_is_valid (nodeP)); CGAL_multiset_assertion (_is_valid (nodeP));
@ -3535,8 +3585,8 @@ Multiset<Type, Compare, Allocator>::_sub_maximum (Node* nodeP) const
// / \ <-------------- / \ . // / \ <-------------- / \ .
// T1 T2 T2 T3 // T1 T2 T2 T3
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::_rotate_left (Node* xNodeP) void Multiset<Type, Compare, Allocator, UseCompactContainer>::_rotate_left (Node* xNodeP)
{ {
// Get the right child of the node. // Get the right child of the node.
Node *yNodeP = xNodeP->rightP; Node *yNodeP = xNodeP->rightP;
@ -3581,8 +3631,8 @@ void Multiset<Type, Compare, Allocator>::_rotate_left (Node* xNodeP)
//--------------------------------------------------------- //---------------------------------------------------------
// Right-rotate the sub-tree spanned by the given node. // Right-rotate the sub-tree spanned by the given node.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::_rotate_right (Node* yNodeP) void Multiset<Type, Compare, Allocator, UseCompactContainer>::_rotate_right (Node* yNodeP)
{ {
// Get the left child of the node. // Get the left child of the node.
Node *xNodeP = yNodeP->leftP; Node *xNodeP = yNodeP->leftP;
@ -3627,9 +3677,9 @@ void Multiset<Type, Compare, Allocator>::_rotate_right (Node* yNodeP)
//--------------------------------------------------------- //---------------------------------------------------------
// Duplicate the entire sub-tree rooted at the given node. // Duplicate the entire sub-tree rooted at the given node.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
typename Multiset<Type, Compare, Allocator>::Node* typename Multiset<Type, Compare, Allocator, UseCompactContainer>::Node*
Multiset<Type, Compare, Allocator>::_duplicate (const Node* nodeP) Multiset<Type, Compare, Allocator, UseCompactContainer>::_duplicate (const Node* nodeP)
{ {
CGAL_multiset_assertion (_is_valid (nodeP)); CGAL_multiset_assertion (_is_valid (nodeP));
@ -3656,8 +3706,8 @@ Multiset<Type, Compare, Allocator>::_duplicate (const Node* nodeP)
//--------------------------------------------------------- //---------------------------------------------------------
// Destroy the entire sub-tree rooted at the given node. // Destroy the entire sub-tree rooted at the given node.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::_destroy (Node* nodeP) void Multiset<Type, Compare, Allocator, UseCompactContainer>::_destroy (Node* nodeP)
{ {
CGAL_multiset_assertion (_is_valid (nodeP)); CGAL_multiset_assertion (_is_valid (nodeP));
@ -3679,8 +3729,8 @@ void Multiset<Type, Compare, Allocator>::_destroy (Node* nodeP)
//--------------------------------------------------------- //---------------------------------------------------------
// Fix-up the tree so it maintains the red-black properties after insertion. // Fix-up the tree so it maintains the red-black properties after insertion.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::_insert_fixup (Node* nodeP) void Multiset<Type, Compare, Allocator, UseCompactContainer>::_insert_fixup (Node* nodeP)
{ {
CGAL_multiset_precondition (_is_red (nodeP)); CGAL_multiset_precondition (_is_red (nodeP));
@ -3791,8 +3841,8 @@ void Multiset<Type, Compare, Allocator>::_insert_fixup (Node* nodeP)
//--------------------------------------------------------- //---------------------------------------------------------
// Fix-up the tree so it maintains the red-black properties after removal. // Fix-up the tree so it maintains the red-black properties after removal.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::_remove_fixup (Node* nodeP, void Multiset<Type, Compare, Allocator, UseCompactContainer>::_remove_fixup (Node* nodeP,
Node* parentP) Node* parentP)
{ {
Node *currP = nodeP; Node *currP = nodeP;
@ -3953,33 +4003,27 @@ void Multiset<Type, Compare, Allocator>::_remove_fixup (Node* nodeP,
//--------------------------------------------------------- //---------------------------------------------------------
// Allocate and initialize new tree node. // Allocate and initialize new tree node.
// //
#ifndef CGAL_CFG_OUTOFLINE_MEMBER_DEFINITION_BUG template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
template <class Type, class Compare, typename Allocator> typename Multiset<Type, Compare, Allocator, UseCompactContainer>::Node*
typename Multiset<Type, Compare, Allocator>::Node* Multiset<Type, Compare, Allocator, UseCompactContainer>::_allocate_node
Multiset<Type, Compare, Allocator>::_allocate_node
(const Type& object, (const Type& object,
typename Node::Node_color color) typename Node::Node_color color)
{ {
CGAL_multiset_assertion (color != Node::DUMMY_BEGIN && CGAL_multiset_assertion (color != Node::DUMMY_BEGIN &&
color != Node::DUMMY_END); color != Node::DUMMY_END);
Node* new_node = node_alloc.allocate(1); Node* new_node = node_alloc.allocate(beginNode);
std::allocator_traits<Node_allocator>::construct(node_alloc, new_node, beginNode);
new_node->init(object, color); new_node->init(object, color);
return (new_node); return (new_node);
} }
#endif
//--------------------------------------------------------- //---------------------------------------------------------
// De-allocate a tree node. // De-allocate a tree node.
// //
template <class Type, class Compare, typename Allocator> template <class Type, class Compare, typename Allocator, typename UseCompactContainer>
void Multiset<Type, Compare, Allocator>::_deallocate_node (Node* nodeP) void Multiset<Type, Compare, Allocator, UseCompactContainer>::_deallocate_node (Node* nodeP)
{ {
std::allocator_traits<Node_allocator>::destroy(node_alloc, nodeP); node_alloc.deallocate (nodeP);
node_alloc.deallocate (nodeP, 1);
return;
} }
} //namespace CGAL } //namespace CGAL

View File

@ -34,6 +34,11 @@ if ( CGAL_FOUND )
create_single_source_cgal_program( "test_lexcompare_outputrange.cpp" ) create_single_source_cgal_program( "test_lexcompare_outputrange.cpp" )
create_single_source_cgal_program( "test_Modifiable_priority_queue.cpp" ) create_single_source_cgal_program( "test_Modifiable_priority_queue.cpp" )
create_single_source_cgal_program( "test_multiset.cpp" ) create_single_source_cgal_program( "test_multiset.cpp" )
add_executable( test_multiset_cc "test_multiset.cpp" )
target_link_libraries( test_multiset_cc PUBLIC CGAL::CGAL )
target_compile_options( test_multiset_cc PUBLIC -DCGAL_MULTISET_USE_COMPACT_CONTAINER_AS_DEFAULT )
create_single_source_cgal_program( "test_N_tuple.cpp" ) create_single_source_cgal_program( "test_N_tuple.cpp" )
create_single_source_cgal_program( "test_namespaces.cpp" ) create_single_source_cgal_program( "test_namespaces.cpp" )
create_single_source_cgal_program( "test_Nested_iterator.cpp" ) create_single_source_cgal_program( "test_Nested_iterator.cpp" )

View File

@ -143,7 +143,8 @@ protected:
public: public:
typedef CGAL::Surface_sweep_2::Event_comparer<Traits_adaptor_2, Event> typedef CGAL::Surface_sweep_2::Event_comparer<Traits_adaptor_2, Event>
Event_comparer; Event_comparer;
typedef Multiset<Event*, Event_comparer, Allocator> Event_queue; typedef Multiset<Event*, Event_comparer, Allocator, Tag_true>
Event_queue;
typedef typename Event_queue::iterator Event_queue_iterator; typedef typename Event_queue::iterator Event_queue_iterator;
typedef typename Event::Subcurve_iterator typedef typename Event::Subcurve_iterator
@ -159,19 +160,11 @@ public:
typedef typename Status_line::iterator Status_line_iterator; typedef typename Status_line::iterator Status_line_iterator;
typedef std::allocator_traits<Allocator> Allocator_traits; typedef std::allocator_traits<Allocator> Allocator_traits;
typedef typename Allocator_traits::template rebind_alloc<Event> Event_alloc;
typedef typename Allocator_traits::template rebind_alloc<Subcurve> Subcurve_alloc; typedef typename Allocator_traits::template rebind_alloc<Subcurve> Subcurve_alloc;
protected: protected:
/*! \struct
* An auxiliary functor for comparing event pointers.
*/
struct CompEventPtr {
Comparison_result operator()(Event* e1, Event* e2) const
{ return (e1 < e2) ? SMALLER : ((e1 > e2) ? LARGER : EQUAL); }
};
typedef Multiset<Event*, CompEventPtr> Allocated_events_set; typedef Compact_container<Event> Allocated_events_set;
typedef typename Allocated_events_set::iterator Allocated_events_iterator; typedef typename Allocated_events_set::iterator Allocated_events_iterator;
// Data members: // Data members:
@ -204,7 +197,6 @@ protected:
// may happen only with events that are // may happen only with events that are
// associated with isolated query points. // associated with isolated query points.
Event_alloc m_eventAlloc; // An allocator for the events objects.
Subcurve_alloc m_subCurveAlloc; // An allocator for the subcurve objects. Subcurve_alloc m_subCurveAlloc; // An allocator for the subcurve objects.
Event m_masterEvent; // A master Event (created once by the Event m_masterEvent; // A master Event (created once by the

View File

@ -78,15 +78,6 @@ No_intersection_surface_sweep_2<Vis>::~No_intersection_surface_sweep_2()
// Free the event queue. // Free the event queue.
delete m_queue; delete m_queue;
// Free all the event that have not been de-allocated so far.
Event* p_event;
Allocated_events_iterator iter = m_allocated_events.begin();
for (; iter != m_allocated_events.end(); ++iter) {
p_event = *iter;
std::allocator_traits<Event_alloc>::destroy(m_eventAlloc, p_event);
m_eventAlloc.deallocate(p_event,1);
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -125,11 +116,7 @@ template <typename Vis>
void No_intersection_surface_sweep_2<Vis>::deallocate_event(Event* event) void No_intersection_surface_sweep_2<Vis>::deallocate_event(Event* event)
{ {
// Remove the event from the set of allocated events. // Remove the event from the set of allocated events.
m_allocated_events.erase(event); m_allocated_events.erase(m_allocated_events.iterator_to(*event));
// Perfrom the actual deallocation.
std::allocator_traits<Event_alloc>::destroy(m_eventAlloc, event);
m_eventAlloc.deallocate(event, 1);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -629,12 +616,8 @@ No_intersection_surface_sweep_2<Vis>::_allocate_event(const Point_2& pt,
Arr_parameter_space ps_y) Arr_parameter_space ps_y)
{ {
// Allocate the event. // Allocate the event.
Event* e = m_eventAlloc.allocate(1); Event* e = &*m_allocated_events.emplace();
std::allocator_traits<Event_alloc>::construct(m_eventAlloc, e, m_masterEvent);
e->init(pt, type, ps_x, ps_y); e->init(pt, type, ps_x, ps_y);
// Insert it to the set of allocated events.
m_allocated_events.insert(e);
return e; return e;
} }
@ -649,11 +632,8 @@ _allocate_event_at_open_boundary(Attribute type,
Arr_parameter_space ps_x, Arr_parameter_space ps_x,
Arr_parameter_space ps_y) Arr_parameter_space ps_y)
{ {
Event* e = m_eventAlloc.allocate(1); Event* e = &*m_allocated_events.emplace();
std::allocator_traits<Event_alloc>::construct(m_eventAlloc, e, m_masterEvent);
e->init_at_open_boundary(type, ps_x, ps_y); e->init_at_open_boundary(type, ps_x, ps_y);
m_allocated_events.insert(e);
return e; return e;
} }

View File

@ -27,6 +27,60 @@
namespace CGAL { namespace CGAL {
namespace Surface_sweep_2 { namespace Surface_sweep_2 {
// This class is used to test if `void* T::for_compact_container()`
// exists, to avoid adding a void* pointer to the Event_base structure
// if Point_2 can already be used as a handle for this
template<typename T>
struct has_for_compact_container
{
private:
template<typename U> static
auto test(void*) -> decltype(std::declval<U>().for_compact_container() == nullptr, Tag_true());
template<typename> static Tag_false test(...);
public:
static constexpr bool value = std::is_same<decltype(test<T>(nullptr)),Tag_true>::value;
};
template <typename Point_2, bool HasFor>
class Event_base_for_compact_container { };
template <typename Point_2>
class Event_base_for_compact_container<Point_2, false>
{
void* p = nullptr;
public:
void* operator()(const Point_2&) const
{
return p;
}
void operator() (Point_2&, void* ptr)
{
p = ptr;
}
};
template <typename Point_2>
class Event_base_for_compact_container<Point_2, true>
{
public:
void* operator()(const Point_2& p) const
{
return p.for_compact_container();
}
void operator() (Point_2& p, void* ptr)
{
p.for_compact_container(ptr);
}
};
/*! \class No_overlap_event_base /*! \class No_overlap_event_base
* *
* A class associated with an event in a surface-sweep algorithm. * A class associated with an event in a surface-sweep algorithm.
@ -71,6 +125,9 @@ public:
typedef typename Subcurve_container::reverse_iterator typedef typename Subcurve_container::reverse_iterator
Subcurve_reverse_iterator; Subcurve_reverse_iterator;
typedef Event_base_for_compact_container
<Point_2, has_for_compact_container<Point_2>::value> For_compact_container;
/*! \enum The event type (with other information bits). */ /*! \enum The event type (with other information bits). */
enum Attribute { enum Attribute {
@ -102,6 +159,10 @@ protected:
char m_closed; // Is the event closed (associated with char m_closed; // Is the event closed (associated with
// a valid point. // a valid point.
// A handle for the compact container (either using the functions of
// `m_point` if available, or an additional pointer)
For_compact_container m_for_compact_container;
public: public:
/*! Default constructor. */ /*! Default constructor. */
No_overlap_event_base() : No_overlap_event_base() :
@ -111,6 +172,16 @@ public:
m_closed(1) m_closed(1)
{} {}
/*! Squat the content of Point_2 for the pointer of Compact Container */
void* for_compact_container() const
{
return m_for_compact_container(m_point);
}
void for_compact_container (void* p)
{
m_for_compact_container(m_point, p);
}
/*! Initialize an event that is associated with a valid point. */ /*! Initialize an event that is associated with a valid point. */
void init(const Point_2& point, Attribute type, void init(const Point_2& point, Attribute type,
Arr_parameter_space ps_x, Arr_parameter_space ps_y) Arr_parameter_space ps_x, Arr_parameter_space ps_y)

View File

@ -2,6 +2,7 @@ Algebraic_foundations
Arithmetic_kernel Arithmetic_kernel
Arrangement_on_surface_2 Arrangement_on_surface_2
Cartesian_kernel Cartesian_kernel
Circulator
Distance_2 Distance_2
Distance_3 Distance_3
Filtered_kernel Filtered_kernel