stack allocate fingers
This commit is contained in:
parent
dcdda88794
commit
5a8ec488d3
|
@ -67,6 +67,49 @@ namespace PTreeImpl {
|
|||
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>
|
||||
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*/) {
|
||||
|
@ -118,53 +161,35 @@ namespace PTreeImpl {
|
|||
// TODO: Remove the number of invocations of operator<, and replace with something closer to memcmp.
|
||||
// and same for upper_bound.
|
||||
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) {
|
||||
while (f.size() && !(lessThan.back())) {
|
||||
while (f.size() && !(f.back_less())) {
|
||||
f.pop_back();
|
||||
lessThan.pop_back();
|
||||
}
|
||||
return;
|
||||
}
|
||||
f.push_back(p.getPtr());
|
||||
int cmp = compare(x, p->data);
|
||||
bool less = cmp < 0;
|
||||
lessThan.push_back(less);
|
||||
f.push_back(p.getPtr(), less);
|
||||
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>
|
||||
void lower_bound(const Reference<PTree<T>>& p, Version at, const X& x, std::vector<const PTree<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){
|
||||
void upper_bound(const Reference<PTree<T>>& p, Version at, const X& x, PTreeFinger<T>& f) {
|
||||
if (!p) {
|
||||
while (f.size() && !(lessThan.back())) {
|
||||
while (f.size() && !(f.back_less())) {
|
||||
f.pop_back();
|
||||
lessThan.pop_back();
|
||||
}
|
||||
return;
|
||||
}
|
||||
f.push_back(p.getPtr());
|
||||
bool less = x < p->data;
|
||||
lessThan.push_back(less);
|
||||
upper_bound(p->child(!less, at), 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){
|
||||
assert(!f.size());
|
||||
std::vector<bool> lessThan;
|
||||
upper_bound(p, at, x, f, lessThan);
|
||||
f.push_back(p.getPtr(), less);
|
||||
upper_bound(p->child(!less, at), at, x, f);
|
||||
}
|
||||
|
||||
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());
|
||||
const PTree<T> *n;
|
||||
n = f.back();
|
||||
|
@ -183,7 +208,7 @@ namespace PTreeImpl {
|
|||
}
|
||||
|
||||
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
|
||||
ASSERT(f.size());
|
||||
const PTree<T> *n;
|
||||
|
@ -206,27 +231,27 @@ namespace PTreeImpl {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T get(std::vector<const PTree<T>*>& f){
|
||||
T get(PTreeFinger<T>& f) {
|
||||
ASSERT(f.size());
|
||||
return f.back()->data;
|
||||
}
|
||||
|
@ -261,19 +286,19 @@ namespace PTreeImpl {
|
|||
}
|
||||
|
||||
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;
|
||||
f.push_back(p.getPtr());
|
||||
firstOrLastFinger<T, last>(p->child(last, at), at, f);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -543,6 +568,7 @@ class VersionedMap : NonCopyable {
|
|||
//private:
|
||||
public:
|
||||
typedef PTreeImpl::PTree<MapPair<K,std::pair<T,Version>>> PTreeT;
|
||||
typedef PTreeImpl::PTreeFinger<MapPair<K, std::pair<T, Version>>> PTreeFingerT;
|
||||
typedef Reference< PTreeT > Tree;
|
||||
|
||||
Version oldestVersion, latestVersion;
|
||||
|
@ -709,7 +735,7 @@ public:
|
|||
friend class VersionedMap<K,T>;
|
||||
Tree root;
|
||||
Version at;
|
||||
std::vector< PTreeT const* > finger;
|
||||
PTreeFingerT finger;
|
||||
};
|
||||
|
||||
class ViewAtVersion {
|
||||
|
|
|
@ -135,6 +135,7 @@ inline bool operator<(const ExtStringRef& lhs, const WriteMapEntry& rhs) {
|
|||
class WriteMap {
|
||||
private:
|
||||
typedef PTreeImpl::PTree<WriteMapEntry> PTreeT;
|
||||
typedef PTreeImpl::PTreeFinger<WriteMapEntry> PTreeFingerT;
|
||||
typedef Reference<PTreeT> Tree;
|
||||
|
||||
public:
|
||||
|
@ -390,7 +391,7 @@ public:
|
|||
Tree tree;
|
||||
Version at;
|
||||
int beginLen, endLen;
|
||||
vector< PTreeT const* > finger;
|
||||
PTreeFingerT finger;
|
||||
bool offset; // false-> the operation stack at entry(); true-> the following cleared or unmodified range
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue