Sync AMTL.

This commit is contained in:
David Anderson 2013-08-29 11:45:28 -07:00
parent 1c40d77b14
commit da9debda67
5 changed files with 128 additions and 62 deletions

View File

@ -31,11 +31,14 @@
#define _include_amtl_inline_list_h_ #define _include_amtl_inline_list_h_
#include <stddef.h> #include <stddef.h>
#include <assert.h>
namespace ke { namespace ke {
template <typename T> class InlineList; template <typename T> class InlineList;
// Objects can recursively inherit from InlineListNode in order to have
// membership in an InlineList<T>.
template <typename T> template <typename T>
class InlineListNode class InlineListNode
{ {
@ -43,14 +46,14 @@ class InlineListNode
public: public:
InlineListNode() InlineListNode()
: next_(NULL), : next_(NULL),
prev_(NULL) prev_(NULL)
{ {
} }
InlineListNode(InlineListNode *next, InlineListNode *prev) InlineListNode(InlineListNode *next, InlineListNode *prev)
: next_(next), : next_(next),
prev_(prev) prev_(prev)
{ {
} }
@ -59,6 +62,14 @@ class InlineListNode
InlineListNode *prev_; InlineListNode *prev_;
}; };
// An InlineList is a linked list that threads link pointers through objects,
// rather than allocating node memory. A node can be in at most one list at
// any time.
//
// Since InlineLists are designed to be very cheap, there is no requirement
// that elements be removed from a list once the list is destructed. However,
// for as long as the list is alive, all of its contained nodes must also
// be alive.
template <typename T> template <typename T>
class InlineList class InlineList
{ {
@ -66,12 +77,26 @@ class InlineList
Node head_; Node head_;
// Work around a clang bug where we can't initialize with &head_ in the ctor.
inline Node *head() {
return &head_;
}
public: public:
InlineList() InlineList()
: head_(&head_, &head_) : head_(head(), head())
{ {
} }
~InlineList()
{
#if !defined(NDEBUG)
// Remove all items to clear their next/prev fields.
while (begin() != end())
remove(*begin());
#endif
}
public: public:
class iterator class iterator
{ {
@ -86,7 +111,7 @@ class InlineList
iterator & operator ++() { iterator & operator ++() {
iter_ = iter_->next; iter_ = iter_->next;
return *iter_; return *this;
} }
iterator operator ++(int) { iterator operator ++(int) {
iterator old(*this); iterator old(*this);
@ -105,14 +130,6 @@ class InlineList
bool operator ==(const iterator &where) const { bool operator ==(const iterator &where) const {
return iter_ == where.iter_; return iter_ == where.iter_;
} }
iterator prev() const {
iterator p(iter_->prev_);
return p;
}
iterator next() const {
iterator p(iter_->next_);
return p;
}
}; };
iterator begin() { iterator begin() {
@ -126,9 +143,17 @@ class InlineList
void remove(Node *t) { void remove(Node *t) {
t->prev_->next_ = t->next_; t->prev_->next_ = t->next_;
t->next_->prev_ = t->prev_; t->next_->prev_ = t->prev_;
#if !defined(NDEBUG)
t->next_ = NULL;
t->prev_ = NULL;
#endif
} }
void insert(Node *t) { void append(Node *t) {
assert(!t->next_);
assert(!t->prev_);
t->prev_ = head_.prev_; t->prev_ = head_.prev_;
t->next_ = &head_; t->next_ = &head_;
head_.prev_->next_ = t; head_.prev_->next_ = t;

View File

@ -34,6 +34,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <am-allocator-policies.h> #include <am-allocator-policies.h>
#include <am-utility.h> #include <am-utility.h>
#include <am-moveable.h>
namespace ke { namespace ke {
@ -58,6 +59,10 @@ class LinkedList : public AllocPolicy
: obj(o) : obj(o)
{ {
} }
Node(Moveable<T> o)
: obj(o)
{
}
T obj; T obj;
Node *next; Node *next;
@ -68,29 +73,28 @@ public:
LinkedList(AllocPolicy = AllocPolicy()) LinkedList(AllocPolicy = AllocPolicy())
: length_(0) : length_(0)
{ {
head()->prev = head();
head()->next = head();
} }
~LinkedList() { ~LinkedList() {
clear(); clear();
} }
bool append(const T &obj) { bool append(const T &obj) {
Node *node = allocNode(obj); return insertBefore(end(), obj) != end();
if (!node) }
return false; bool append(Moveable<T> obj) {
return insertBefore(end(), obj) != end();
node->prev = head()->prev;
node->next = head();
head()->prev->next = node;
head()->prev = node;
length_++;
} }
bool prepend(const T &obj) { bool prepend(const T &obj) {
return insert(begin(), obj); return insertBefore(begin(), obj) != begin();
}
bool prepend(Moveable<T> obj) {
return insertBefore(begin(), obj) != begin();
} }
size_t size() const { size_t length() const {
return length_; return length_;
} }
@ -137,6 +141,13 @@ public:
new (node) Node(obj); new (node) Node(obj);
return node; return node;
} }
Node *allocNode(Moveable<T> obj) {
Node *node = (Node *)this->malloc(sizeof(Node));
if (!node)
return NULL;
new (node) Node(obj);
return node;
}
void freeNode(Node *node) { void freeNode(Node *node) {
node->obj.~T(); node->obj.~T();
@ -221,29 +232,9 @@ public:
Node *this_; Node *this_;
}; };
public: private:
iterator begin() const { // Insert obj right before where.
return iterator(head()->next); iterator insert(iterator where, Node *node) {
}
iterator end() const {
return iterator(head());
}
iterator erase(iterator &where) {
Node *pNode = where.this_;
iterator iter(where);
iter++;
pNode->prev->next = pNode->next;
pNode->next->prev = pNode->prev;
freeNode(pNode);
length_--;
return iter;
}
iterator insert(iterator where, const T &obj) {
// Insert obj right before where
Node *node = allocNode(obj);
if (!node) if (!node)
return where; return where;
@ -259,6 +250,34 @@ public:
} }
public: public:
iterator begin() {
return iterator(head()->next);
}
iterator end() {
return iterator(head());
}
iterator erase(iterator where) {
Node *pNode = where.this_;
iterator iter(where);
iter++;
pNode->prev->next = pNode->next;
pNode->next->prev = pNode->prev;
freeNode(pNode);
length_--;
return iter;
}
iterator insertBefore(iterator where, const T &obj) {
return insert(where, allocNode(obj));
}
iterator insertBefore(iterator where, Moveable<T> obj) {
return insert(where, allocNode(obj));
}
public:
// Removes one instance of |obj| from the list, if found.
void remove(const T &obj) { void remove(const T &obj) {
for (iterator b = begin(); b != end(); b++) { for (iterator b = begin(); b != end(); b++) {
if (*b == obj) { if (*b == obj) {
@ -269,7 +288,7 @@ public:
} }
template <typename U> template <typename U>
iterator find(const U &equ) const { iterator find(const U &equ) {
for (iterator iter = begin(); iter != end(); iter++) { for (iterator iter = begin(); iter != end(); iter++) {
if (*iter == equ) if (*iter == equ)
return iter; return iter;

View File

@ -61,6 +61,13 @@ struct Moveable
T &t_; T &t_;
}; };
template <typename T>
static inline Moveable<T>
Move(T &t)
{
return Moveable<T>(t);
}
} // namespace ke } // namespace ke
#endif // _include_amtl_moveable_h_ #endif // _include_amtl_moveable_h_

View File

@ -81,6 +81,9 @@ class AString
return *this; return *this;
} }
int compare(const char *str) const {
return strcmp(chars(), str);
}
int compare(const AString &other) const { int compare(const AString &other) const {
return strcmp(chars(), other.chars()); return strcmp(chars(), other.chars());
} }

View File

@ -43,24 +43,23 @@ class Vector : public AllocPolicy
{ {
public: public:
Vector(AllocPolicy = AllocPolicy()) Vector(AllocPolicy = AllocPolicy())
: data_(NULL), : data_(NULL),
nitems_(0), nitems_(0),
maxsize_(0) maxsize_(0)
{ {
} }
Vector(Moveable<Vector<T, AllocPolicy> > other) {
data_ = other->data_;
nitems_ = other->nitems_;
maxsize_ = other->maxsize_;
other->reset();
}
~Vector() { ~Vector() {
zap(); zap();
} }
void steal(Vector &other) {
zap();
data_ = other.data_;
nitems_ = other.nitems_;
maxsize_ = other.maxsize_;
other.reset();
}
bool append(const T &item) { bool append(const T &item) {
if (!growIfNeeded(1)) if (!growIfNeeded(1))
return false; return false;
@ -68,11 +67,24 @@ class Vector : public AllocPolicy
nitems_++; nitems_++;
return true; return true;
} }
bool append(Moveable<T> item) {
if (!growIfNeeded(1))
return false;
new (&data_[nitems_]) T(item);
nitems_++;
return true;
}
void infallibleAppend(const T &item) { void infallibleAppend(const T &item) {
assert(growIfNeeded(1)); assert(growIfNeeded(1));
new (&data_[nitems_]) T(item); new (&data_[nitems_]) T(item);
nitems_++; nitems_++;
} }
void infallibleAppend(Moveable<T> item) {
assert(growIfNeeded(1));
new (&data_[nitems_]) T(item);
nitems_++;
}
T popCopy() { T popCopy() {
T t = at(length() - 1); T t = at(length() - 1);
pop(); pop();