mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-05 05:07:48 +00:00
GEEKING
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
Reference in New Issue
Block a user