stack allocate fingers
This commit is contained in:
parent
5e1c43f87b
commit
3569dfe6cb
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue