perf improvement for DfLinkedList::end(), erase/insert/insert_after/push_front implementations

develop
Ben Lubar 2018-06-18 13:36:57 -05:00
parent 0b9d46712f
commit 1606483e7e
No known key found for this signature in database
GPG Key ID: 018BAB45DB2D2B24
1 changed files with 134 additions and 155 deletions

@ -241,133 +241,49 @@ namespace DFHack
class iterator;
class const_iterator;
class proxy
{
L *root;
L *prev;
friend class iterator;
proxy(L *root, L *prev) : root(root), prev(prev)
{
CHECK_NULL_POINTER(root);
CHECK_NULL_POINTER(prev);
}
public:
operator I * & ()
{
CHECK_NULL_POINTER(prev->next);
return prev->next->item;
}
operator I *() const
{
CHECK_NULL_POINTER(prev->next);
return prev->next->item;
}
I *operator->() const
{
CHECK_NULL_POINTER(prev->next);
return prev->next->item;
}
proxy & operator=(I *item)
{
if (!prev->next)
{
prev->next = new L();
if (prev != root)
prev->next->prev = prev;
}
prev->next->item = item;
return *this;
}
};
class iterator
{
L *root;
L *prev;
bool next;
L *cur;
friend struct DfLinkedList<L, I>;
friend class const_iterator;
void ensure_prev()
{
CHECK_NULL_POINTER(root);
if (!prev && !next)
{
for (prev = root; prev->next && prev->next->next; prev = prev->next)
{
next = true;
}
}
}
iterator() : root(nullptr), prev(nullptr), next(false) {}
iterator(L *root, L *cur) : root(root), cur(cur) {}
public:
using difference_type = void;
using value_type = I *;
using pointer = I **;
using reference = proxy;
using iterator_category = std::output_iterator_tag;
using reference = I * &;
using iterator_category = std::bidirectional_iterator_tag;
iterator(L *root, L *prev, bool next = false) : root(root), prev(prev), next(next) {}
iterator(const iterator & other) : root(other.root), prev(other.prev), next(other.next) {}
iterator() : root(nullptr), cur(nullptr) {}
iterator(const iterator & other) : root(other.root), cur(other.cur) {}
iterator & operator++()
{
CHECK_NULL_POINTER(root);
CHECK_NULL_POINTER(cur);
CHECK_NULL_POINTER(prev);
CHECK_NULL_POINTER(prev->next);
if (!next && !prev->next->next)
{
next = true;
return *this;
}
CHECK_NULL_POINTER(prev->next->next);
prev = prev->next;
cur = cur->next;
return *this;
}
iterator & operator--()
{
CHECK_NULL_POINTER(root);
ensure_prev();
if (next)
if (!cur)
{
next = false;
return *this;
}
CHECK_NULL_POINTER(prev);
if (prev == root)
{
throw DFHack::Error::NullPointer("prev->prev", DFHACK_FUNCTION_SIG);
}
if (root->next == prev)
{
prev = root;
return *this;
}
if (prev->prev)
{
prev = prev->prev;
return *this;
}
for (L *it = root; it->next; it = it->next)
{
if (it->next == prev)
// find end() - 1
for (cur = root->next; cur && cur->next; cur = cur->next)
{
prev = it;
return *this;
}
return *this;
}
throw DFHack::Error::NullPointer("prev->prev", DFHACK_FUNCTION_SIG);
CHECK_NULL_POINTER(cur);
CHECK_NULL_POINTER(cur->prev);
cur = cur->prev;
return *this;
}
iterator operator++(int)
{
@ -384,36 +300,24 @@ namespace DFHack
iterator & operator=(const iterator & other)
{
root = other.root;
prev = other.prev;
next = other.next;
cur = other.cur;
return *this;
}
proxy operator*()
I * & operator*()
{
CHECK_NULL_POINTER(prev);
CHECK_NULL_POINTER(prev->next);
if (next)
return proxy(root, prev->next);
CHECK_NULL_POINTER(root);
CHECK_NULL_POINTER(cur);
return proxy(root, prev);
return cur->item;
}
const proxy operator*() const
I * const & operator*() const
{
CHECK_NULL_POINTER(prev);
CHECK_NULL_POINTER(prev->next);
if (next)
return proxy(root, prev->next);
return proxy(root, prev);
}
CHECK_NULL_POINTER(root);
CHECK_NULL_POINTER(cur);
I * operator->() const
{
return **this;
return cur->item;
}
operator const_iterator() const
@ -422,26 +326,7 @@ namespace DFHack
}
bool operator==(const iterator & other) const
{
if (root != other.root)
return false;
if (!next && !prev && !other.next && !other.prev)
return true;
if ((!next && !prev) || (!other.next && !other.prev))
{
iterator this_copy = *this;
this_copy.ensure_prev();
iterator other_copy = other;
other_copy.ensure_prev();
return this_copy == other_copy;
}
if (other.next && !next)
return prev && other.prev && prev->next == other.prev;
if (next && !other.next)
return prev && other.prev && other.prev->next == prev;
return other.prev == prev;
return root == other.root && cur == other.cur;
}
bool operator!=(const iterator & other) const
{
@ -454,9 +339,9 @@ namespace DFHack
friend struct DfLinkedList<L, I>;
public:
using difference_type = void;
using value_type = I * ;
using value_type = I *;
using pointer = I * const *;
using reference = const proxy;
using reference = I * const &;
using iterator_category = std::bidirectional_iterator_tag;
const_iterator(const iterator & iter) : iter(iter) {}
@ -475,13 +360,13 @@ namespace DFHack
const_iterator operator++(int)
{
const_iterator copy(*this);
++*this;
++iter;
return copy;
}
const_iterator operator--(int)
{
const_iterator copy(*this);
--*this;
--iter;
return copy;
}
const_iterator & operator=(const const_iterator & other)
@ -489,11 +374,7 @@ namespace DFHack
iter = other.iter;
return *this;
}
const proxy operator*() const
{
return *iter;
}
I *operator->() const
I * const & operator*() const
{
return *iter;
}
@ -526,11 +407,11 @@ namespace DFHack
iterator begin()
{
return iterator(static_cast<L *>(this), static_cast<L *>(this));
return iterator(static_cast<L *>(this), static_cast<L *>(this)->next);
}
const_iterator begin() const
{
return const_iterator(static_cast<L *>(this), static_cast<L *>(this));
return const_iterator(static_cast<L *>(this), static_cast<L *>(this)->next);
}
const_iterator cbegin() const
{
@ -538,15 +419,113 @@ namespace DFHack
}
iterator end()
{
return iterator(static_cast<L *>(this), nullptr, false);
return iterator(static_cast<L *>(this), nullptr);
}
const_iterator end() const
{
return const_iterator(static_cast<L *>(this), nullptr, false);
return const_iterator(static_cast<L *>(this), nullptr);
}
const_iterator cend() const
{
return end();
}
iterator erase(const_iterator pos)
{
auto root = static_cast<L *>(this);
CHECK_INVALID_ARGUMENT(pos.iter.root == root);
CHECK_NULL_POINTER(pos.iter.cur);
auto link = pos.iter.cur;
auto next = link->next;
if (link->next && link->prev)
{
link->next->prev = link->prev;
link->prev->next = link->next;
}
else if (link->next)
{
link->next->prev = nullptr;
}
else if (link->prev)
{
link->prev->next = nullptr;
}
if (root->next == link)
{
root->next = next;
}
delete link;
return iterator(root, next);
}
iterator insert(const_iterator pos, I * const & item)
{
auto root = static_cast<L *>(this);
CHECK_INVALID_ARGUMENT(pos.iter.root == root);
auto link = pos.iter.cur;
if (!link || !link->prev)
{
if (!link && root->next)
{
pos--;
return insert_after(pos, item);
}
CHECK_INVALID_ARGUMENT(root->next == link);
push_front(item);
return begin();
}
auto newlink = new L();
newlink->prev = link->prev;
newlink->next = link;
link->prev = newlink;
if (newlink->prev)
{
newlink->prev->next = newlink;
}
else if (link == root->next)
{
root->next = newlink;
}
newlink->item = item;
return iterator(root, newlink);
}
iterator insert_after(const_iterator pos, I * const & item)
{
auto root = static_cast<L *>(this);
CHECK_INVALID_ARGUMENT(pos.iter.root == root);
CHECK_NULL_POINTER(pos.iter.cur);
auto link = pos.iter.cur;
auto next = link->next;
auto newlink = new L();
newlink->prev = link;
newlink->next = next;
link->next = newlink;
if (next)
{
next->prev = newlink;
}
newlink->item = item;
return iterator(root, newlink);
}
void push_front(I * const & item)
{
auto root = static_cast<L *>(this);
auto link = new L();
link->prev = nullptr;
if (root->next)
{
root->next->prev = link;
link->next = root->next;
}
link->item = item;
root->next = link;
}
};
}