stack allocate fingers

This commit is contained in:
Russell Sears 2020-04-15 18:02:18 -07:00
parent 5e1c43f87b
commit 3569dfe6cb
2 changed files with 115 additions and 88 deletions

View File

@ -67,6 +67,49 @@ namespace PTreeImpl {
PTree(PTree const&); PTree(PTree const&);
}; };
// TODO: Figure out proper copy / move semantics for this (callers copy this around!)
template <class T>
class PTreeFinger { // NonCopyable
struct PTreeFingerEntry {
PTreeFingerEntry() : node(nullptr), less(false) {}
PTreeFingerEntry(PTree<T> const* node, bool less) : node(node), less(less) {}
PTreeFingerEntry(PTreeFingerEntry const& entry) : node(entry.node), less(entry.less) {}
PTreeFingerEntry& operator=(PTreeFingerEntry const& entry) {
node = entry.node;
less = entry.less;
return *this;
}
PTree<T> const* node;
bool less;
};
static constexpr size_t N = 64;
PTreeFingerEntry entries_[N];
size_t size_ = 0;
public:
PTreeFinger() {}
size_t size() const { return size_; }
void push_back(PTree<T> const* node) { this->push_back(node, false); }
PTree<T> const* back() const { return entries_[size_ - 1].node; }
bool back_less() const { return entries_[size_ - 1].less; }
void pop_back() { size_--; }
void clear() { size_ = 0; }
PTree<T> const* operator[](size_t i) const { return entries_[i].node; }
void resize(size_t sz) {
size_ = sz;
ASSERT(size_ < N);
}
void push_back(PTree<T> const* node, bool less) {
entries_[size_++] = { node, less };
ASSERT(size_ < N);
}
};
template<class T> template<class T>
static Reference<PTree<T>> update( Reference<PTree<T>> const& node, bool which, Reference<PTree<T>> const& ptr, Version at ) { static Reference<PTree<T>> update( Reference<PTree<T>> const& node, bool which, Reference<PTree<T>> const& ptr, Version at ) {
if (ptr.getPtr() == node->child(which, at).getPtr()/* && node->replacedVersion <= at*/) { if (ptr.getPtr() == node->child(which, at).getPtr()/* && node->replacedVersion <= at*/) {
@ -118,53 +161,35 @@ namespace PTreeImpl {
// TODO: Remove the number of invocations of operator<, and replace with something closer to memcmp. // TODO: Remove the number of invocations of operator<, and replace with something closer to memcmp.
// and same for upper_bound. // and same for upper_bound.
template <class T, class X> template <class T, class X>
void lower_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f, std::vector<bool>& lessThan){ void lower_bound(const Reference<PTree<T>>& p, Version at, const X& x, PTreeFinger<T>& f) {
if (!p) { if (!p) {
while (f.size() && !(lessThan.back())) { while (f.size() && !(f.back_less())) {
f.pop_back(); f.pop_back();
lessThan.pop_back();
} }
return; return;
} }
f.push_back(p.getPtr());
int cmp = compare(x, p->data); int cmp = compare(x, p->data);
bool less = cmp < 0; bool less = cmp < 0;
lessThan.push_back(less); f.push_back(p.getPtr(), less);
if (cmp == 0) return; if (cmp == 0) return;
lower_bound(p->child(!less, at), at, x, f, lessThan); lower_bound(p->child(!less, at), at, x, f);
} }
template <class T, class X> template <class T, class X>
void lower_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f) { void upper_bound(const Reference<PTree<T>>& p, Version at, const X& x, PTreeFinger<T>& f) {
assert(!f.size());
std::vector<bool> lessThan;
lower_bound(p, at, x, f, lessThan);
}
template<class T, class X>
void upper_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f, std::vector<bool>& lessThan){
if (!p) { if (!p) {
while (f.size() && !(lessThan.back())) { while (f.size() && !(f.back_less())) {
f.pop_back(); f.pop_back();
lessThan.pop_back();
} }
return; return;
} }
f.push_back(p.getPtr());
bool less = x < p->data; bool less = x < p->data;
lessThan.push_back(less); f.push_back(p.getPtr(), less);
upper_bound(p->child(!less, at), at, x, f, lessThan); upper_bound(p->child(!less, at), at, x, f);
}
template<class T, class X>
void upper_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<T>*>& f){
assert(!f.size());
std::vector<bool> lessThan;
upper_bound(p, at, x, f, lessThan);
} }
template <class T, bool forward> template <class T, bool forward>
void move(Version at, std::vector<const PTree<T>*>& f){ void move(Version at, PTreeFinger<T>& f) {
ASSERT(f.size()); ASSERT(f.size());
const PTree<T> *n; const PTree<T> *n;
n = f.back(); n = f.back();
@ -183,7 +208,7 @@ namespace PTreeImpl {
} }
template <class T, bool forward> template <class T, bool forward>
int halfMove(Version at, std::vector<const PTree<T>*>& f) { int halfMove(Version at, PTreeFinger<T>& f) {
// Post: f[:return_value] is the finger that would have been returned by move<forward>(at,f), and f[:original_length_of_f] is unmodified // Post: f[:return_value] is the finger that would have been returned by move<forward>(at,f), and f[:original_length_of_f] is unmodified
ASSERT(f.size()); ASSERT(f.size());
const PTree<T> *n; const PTree<T> *n;
@ -206,27 +231,27 @@ namespace PTreeImpl {
} }
template <class T> template <class T>
void next(Version at, std::vector<const PTree<T>*>& f){ void next(Version at, PTreeFinger<T>& f) {
move<T,true>(at, f); move<T,true>(at, f);
} }
template <class T> template <class T>
void previous(Version at, std::vector<const PTree<T>*>& f){ void previous(Version at, PTreeFinger<T>& f) {
move<T,false>(at, f); move<T,false>(at, f);
} }
template <class T> template <class T>
int halfNext(Version at, std::vector<const PTree<T>*>& f){ int halfNext(Version at, PTreeFinger<T>& f) {
return halfMove<T,true>(at, f); return halfMove<T,true>(at, f);
} }
template <class T> template <class T>
int halfPrevious(Version at, std::vector<const PTree<T>*>& f){ int halfPrevious(Version at, PTreeFinger<T>& f) {
return halfMove<T,false>(at, f); return halfMove<T,false>(at, f);
} }
template <class T> template <class T>
T get(std::vector<const PTree<T>*>& f){ T get(PTreeFinger<T>& f) {
ASSERT(f.size()); ASSERT(f.size());
return f.back()->data; return f.back()->data;
} }
@ -261,19 +286,19 @@ namespace PTreeImpl {
} }
template <class T, bool last> template <class T, bool last>
void firstOrLastFinger(const Reference<PTree<T>>& p, Version at, std::vector<const PTree<T>*>& f) { void firstOrLastFinger(const Reference<PTree<T>>& p, Version at, PTreeFinger<T>& f) {
if (!p) return; if (!p) return;
f.push_back(p.getPtr()); f.push_back(p.getPtr());
firstOrLastFinger<T, last>(p->child(last, at), at, f); firstOrLastFinger<T, last>(p->child(last, at), at, f);
} }
template <class T> template <class T>
void first(const Reference<PTree<T>>& p, Version at, std::vector<const PTree<T>*>& f) { void first(const Reference<PTree<T>>& p, Version at, PTreeFinger<T>& f) {
return firstOrLastFinger<T, false>(p, at, f); return firstOrLastFinger<T, false>(p, at, f);
} }
template <class T> template <class T>
void last(const Reference<PTree<T>>& p, Version at, std::vector<const PTree<T>*>& f) { void last(const Reference<PTree<T>>& p, Version at, PTreeFinger<T>& f) {
return firstOrLastFinger<T, true>(p, at, f); return firstOrLastFinger<T, true>(p, at, f);
} }
@ -543,6 +568,7 @@ class VersionedMap : NonCopyable {
//private: //private:
public: public:
typedef PTreeImpl::PTree<MapPair<K,std::pair<T,Version>>> PTreeT; typedef PTreeImpl::PTree<MapPair<K,std::pair<T,Version>>> PTreeT;
typedef PTreeImpl::PTreeFinger<MapPair<K, std::pair<T, Version>>> PTreeFingerT;
typedef Reference< PTreeT > Tree; typedef Reference< PTreeT > Tree;
Version oldestVersion, latestVersion; Version oldestVersion, latestVersion;
@ -709,7 +735,7 @@ public:
friend class VersionedMap<K,T>; friend class VersionedMap<K,T>;
Tree root; Tree root;
Version at; Version at;
std::vector< PTreeT const* > finger; PTreeFingerT finger;
}; };
class ViewAtVersion { class ViewAtVersion {

View File

@ -135,6 +135,7 @@ inline bool operator<(const ExtStringRef& lhs, const WriteMapEntry& rhs) {
class WriteMap { class WriteMap {
private: private:
typedef PTreeImpl::PTree<WriteMapEntry> PTreeT; typedef PTreeImpl::PTree<WriteMapEntry> PTreeT;
typedef PTreeImpl::PTreeFinger<WriteMapEntry> PTreeFingerT;
typedef Reference<PTreeT> Tree; typedef Reference<PTreeT> Tree;
public: public:
@ -390,7 +391,7 @@ public:
Tree tree; Tree tree;
Version at; Version at;
int beginLen, endLen; int beginLen, endLen;
vector< PTreeT const* > finger; PTreeFingerT finger;
bool offset; // false-> the operation stack at entry(); true-> the following cleared or unmodified range bool offset; // false-> the operation stack at entry(); true-> the following cleared or unmodified range
}; };