This commit is contained in:
watrabi
2025-09-18 17:55:52 -04:00
commit 977f1ff4b8
15030 changed files with 17324420 additions and 0 deletions
+249
View File
@@ -0,0 +1,249 @@
#pragma once
#include "RBX/Debug.h"
#include "boost/noncopyable.hpp"
namespace RBX { namespace Intrusive {
// A very efficient, constant time, unordered set
// Features:
// Constant-time insert
// Constant-time remove
// Constant-time membership test
// items can remove themselves
// Items in the set auto-remove themselves upon destruction
// no memory is allocated for operations
// everything is nothrow
//
// TODO: Adding an item to a set silently removes it for membership in another set. Is this desirable? Should it be a runtime error?
// TODO: Implement ConstIterator
template<class Item, class Tag = Item>
class Set : boost::noncopyable
{
private:
class NextRef
{
friend class Set;
protected:
Item* next;
inline NextRef() throw()
:next(0)
{
}
inline NextRef(const NextRef& other) throw()
:next(0)
{
// Copies of objects aren't automatically added to containers
}
inline NextRef& operator=(const NextRef& other) throw()
{
// This object retains its membership to its container
}
};
public:
class Hook : public NextRef
{
friend class Set;
Set* _container;
NextRef* prev;
public:
inline Hook() throw()
:_container(0),prev(0)
{
}
inline Hook(const Hook& other) throw()
:_container(0),prev(0)
{
// Copies of objects aren't automatically added to containers
}
inline Hook& operator=(const Hook& other) throw()
{
// This object retains its membership to its container
}
inline ~Hook() throw()
{
remove();
}
inline void remove() throw()
{
if (is_linked())
{
RBXASSERT(prev!=0 || Set::NextRef::next!=0);
if (prev)
prev->Set::NextRef::next = NextRef::next;
if (NextRef::next)
NextRef::next->Set::Hook::prev = prev;
_container->count--;
NextRef::next = 0;
prev = 0;
_container = 0;
}
}
inline bool is_linked() const throw()
{
RBXASSERT((_container != 0) == ((Set::NextRef::next != 0) || (prev != 0)));
return _container != 0;
}
inline Set* container() throw()
{
return _container;
}
};
class Iterator
{
friend class Set;
Item* item;
Iterator(Item* item) throw()
:item(item)
{
RBXASSERT(!item || item->Set::Hook::is_linked());
}
public:
inline Iterator() throw()
:item(0) {}
inline bool operator==(const Iterator& other) const throw()
{
return item == other.item;
}
inline bool operator!=(const Iterator& other) const throw()
{
return item != other.item;
}
inline Item* operator->() throw()
{
RBXASSERT(item);
RBXASSERT(!item || item->Set::Hook::is_linked());
return item;
}
inline Item& operator*() throw()
{
RBXASSERT(item);
RBXASSERT(!item || item->Set::Hook::is_linked());
return *item;
}
inline Iterator& operator++() throw()
{
RBXASSERT(item);
item = item->Set::Hook::next;
RBXASSERT(!item || item->Set::Hook::is_linked());
return *this;
}
inline bool empty() const throw()
{
return item == 0;
}
// for std iterators:
typedef std::forward_iterator_tag iterator_category;
typedef Item& value_type;
typedef void difference_type;
typedef /*typename*/ Item* pointer;
typedef /*typename*/ Item& reference;
};
inline Set() throw()
:count(0)
{}
inline ~Set() throw()
{
for (Iterator iter = begin(); !iter.empty(); iter = erase(iter))
;
}
inline size_t size() const throw() { return count; }
inline bool empty() const throw() { return count==0; }
Iterator erase(Iterator iter) throw()
{
Item& item(*iter);
++iter;
remove_element(item);
return iter;
}
bool remove_element(Item& item) throw()
{
if (item.Set::Hook::_container == this)
{
item.Set::Hook::remove();
return true;
}
else
return false;
}
void insert(Item& item) throw()
{
if (item.Set::Hook::_container == this)
return;
// Items can be in only one list at a time
item.Set::Hook::remove();
RBXASSERT(!item.Set::Hook::next);
RBXASSERT(!item.Set::Hook::prev);
Item* head = head_ref.next;
if (head)
{
RBXASSERT(head->Set::Hook::is_linked());
RBXASSERT(head->Set::Hook::container() == this);
item.Set::NextRef::next = head;
head->Set::Hook::prev = &item;
}
head_ref.next = &item;
item.Set::Hook::prev = &head_ref;
item.Set::Hook::_container = this;
RBXASSERT(item.Set::Hook::next || item.Set::Hook::prev);
count++;
}
inline Iterator begin() throw()
{
return Iterator(head_ref.next);
}
inline Iterator end() throw()
{
return Iterator();
}
// For the std iterator pattern:
typedef Iterator iterator;
// For the boost::intrusive pattern:
inline void push_front(Item& item) throw()
{
insert(item);
}
// For the boost::intrusive pattern:
inline Iterator iterator_to(Item& item) throw()
{
return item.Set::Hook::_container == this ? Iterator(&item) : Iterator();
}
private:
size_t count;
NextRef head_ref;
};
}}