BPlusTree
struct BPlusTree[k: Type, v: Type, r: Eff]Sourcemut root: Node[k, v, r]arity: Int32rootLock: Lock[r]rc: Region[r]counter: AtomicCounter[r]search: SearchType of mutable concurrent B+ trees.
The tree maps keys of type k to values of type v.
A B+ Tree is an m-ary self-balancing search tree where each node is either an internal
node or a leaf node. In contrast to binary search trees, a B+ Tree of arity m only
allows nodes with at most m children and m-1 keys. A B+ Tree stores its keys in
a sorted order in its internal nodes, which are used to guide searches to leaf nodes
that store the keys' corresponding values.
See below for more details:
- The Ubiquitous B-Tree (1979) by Douglas Comer (https://dl.acm.org/doi/10.1145/356770.356776)
A BPlusTree satisfies the following.
root is the root node of the tree, which upon creation of the tree is a leaf node.
Through insertion into the tree, a new node may be created and propagated up to become
the new root of the tree.
arity or m is the arity of the tree which determines the maximum number of children
a node may have. The arity must be at least 3.
rootLock is a lock on the root pointer, which a thread must first acquire before
accessing the root node. It must also be acquired before changing root. The node
root has a separate lock concerning the contents of the node. The lock of root
must first be acquired after successfully acquiring rootLock.
rc is the region for the tree.
search is only used internally within the Fixpoint module where keys are of type
Vector[Int64]. A search describes the order in which elements should be
compared. E.g. [0, 1, 2, ..., n] is the natural order. A search may only be used
when using Vector[Int64] as keys.
counter is used for keeping track of the number of inserted elements.
For all other usages search will be a vector of size 0.
Concurrency: thread-safe operations use optimistic stamps and validation. Functions marked "Not thread-safe" traverse or mutate the live tree without a stable snapshot, so concurrent writes may affect the observed result.
Type of mutable concurrent B+ trees, and its functions.
Type Aliases
Definitions
Updates t with k => f(v) if k => v is in t.
Otherwise, t is unchanged.
Thread-safe.
def adjustWithKey(f: k -> (v -> v \ ef), k: k, t: BPlusTree[k, v, r]): Unit \ ef + r with Order[k]§ SourceUpdates t with k => f(k, v) if k => v is in t.
Otherwise, t is unchanged.
Thread-safe.
Returns true if and only if t is a structurally correct tree.
Only used for internal testing.
def computeIfAbsent(f: Unit -> v \ ef, k: k, t: BPlusTree[k, v, r]): v \ ef + r with Order[k]§ SourceReturns v if k => v is in t. Otherwise, computes v = f(), inserts k => v
and returns v. That is, f is only evaluated if k is not in t.
This operation is atomic.
Thread-safe.
@Parallel Returns the number of mappings in t that satisfy the predicate function f.
This method unsafely removes the effect r when spawning threads.
Not thread-safe: Traverses the live leaf chain of t in parallel.
Returns a fresh empty BPlusTree tree of standard arity.
Returns a fresh empty BPlusTree with arity m. A node may have at most m
children and m - 1 keys.
The arity must be at least 3.
def emptyWithArityAndSearch(rc: Region[r], m: Int32, search: Search): BPlusTree[k, v, r] \ r§ SourceReturns a fresh empty BPlusTree with arity m. A node may have at most m
children and m - 1 keys.
The arity must be at least 3.
search decides the comparison order for the stored vectors.
Returns a fresh empty BPlusTree of standard arity.
search decided the comparison order for the stored vectors.
Returns true if and only if there exists k => v in t such that f(k, v) == true.
Not thread-safe: Traverses the live leaf chain of t.
Alias for findLeft.
Not thread-safe: Traverses the live leaf chain of t.
Optionally returns the first mapping in t satisfying the function f.
Not thread-safe: Traverses the live leaf chain of t.
Applies f to a start value i and all values in t going from left to right.
Not thread-safe: Traverses the live leaf chain of t.
def foldLeftWithKey(f: b -> (k -> (v -> b \ ef)), i: b, t: BPlusTree[k, v, r]): b \ ef + r with Order[k]§ SourceApplies f to a start value i and all mappings k => v in t going from left to right.
Not thread-safe: Traverses the live leaf chain of t.
def foldWithKey(f: b -> (k -> (v -> b \ ef)), i: b, t: BPlusTree[k, v, r]): b \ r + ef with Order[k]§ SourceAlias for foldLeftWithKey
Returns true if and only if for all k => v in t, f(k, v) == true.
Not thread-safe: Traverses the live leaf chain of t.
Applies f to all mappings k => v in t.
Not thread-safe: Traverses the live leaf chain of t.
def forEachWithIndex(f: Int32 -> (k -> (v -> Unit \ ef)), t: BPlusTree[k, v, r]): Unit \ ef + r§ SourceApplies f to all mappings k => v in t, passing an index as the first argument.
Not thread-safe: Traverses the live leaf chain of t.
Returns Some(v) if k => v is in t. Otherwise, returns None.
Thread-safe.
Returns Some((k, v)) if k => v is in t. Otherwise, returns None.
Thread-safe.
Returns v if k => v is in t. Aborts with a trace message if k is not in t.
Thread-safe.
Returns v if k => v is in t.
Otherwise updates t with a new mapping k => d and returns d.
Atomic and thread-safe
Returns v if k => v is in t. Otherwise, returns d.
Thread-safe.
Returns true if and only if t is the empty tree.
Thread-safe.
def isProperSubmapOf(t1: BPlusTree[k, v, r1], t2: BPlusTree[k, v, r2]): Bool \ r1 + r2 with Order[k], Eq[v]§ SourceReturns true if t1 is a proper submap of t2, i.e. t1 is a submap of t2 and
there exists a key in t2 that is not in t1.
Not thread-safe: Traverses the live leaf chains of t1 and t2.
def isSubmapOf(t1: BPlusTree[k, v, r1], t2: BPlusTree[k, v, r2]): Bool \ r1 + r2 with Order[k], Eq[v]§ SourceReturns true if t1 is a submap of t2, i.e. for every key in t1, t2
contains the same key with the same value.
Not thread-safe: Traverses the live leaf chains of t1 and t2.
Returns an iterator over all key-value pairs in t,
Not thread-safe: The iterator reads from the live leaf chain of t.
def iteratorValues(rc1: Region[r1], t: BPlusTree[k, v, r2]): Iterator[v, r1 + r2, r1] \ r1 + r2§ SourceReturns an iterator over values in t.
Not thread-safe: The iterator reads from the live leaf chain of t.
def iteratorWithKeys(rc1: Region[r1], t: BPlusTree[k, v, r2]): Iterator[k, r1 + r2, r1] \ r1 + r2§ SourceReturns an iterator over keys in t.
Not thread-safe: The iterator reads from the live leaf chain of t.
Returns a string containing all keys in t, in key order,
with each key formatted by its ToString instance and separated by sep.
Not thread-safe.
Builds the result by traversing the live leaf chain of t.
Returns a string containing all values in t, in key order,
with each value formatted by its ToString instance and separated by sep.
Not thread-safe: Builds the result by traversing the live leaf chain of t.
def joinWith(f: k -> (v -> String \ ef), sep: String, t: BPlusTree[k, v, r]): String \ r + ef§ SourceApplies f to each key-value pair in t, in key order, to obtain a
string and returns all results joined together using sep.
Not thread-safe: Builds the result by traversing the live leaf chain of t.
Returns the set of keys in t.
Not thread-safe: Builds the result by traversing the live leaf chain of t.
def map(rc1: Region[r1], f: v1 -> v2 \ ef, t: BPlusTree[k, v1, r]): BPlusTree[k, v2, r1] \ ef + r + r1 with Order[k]§ SourceReturns a BPlusTree with mappings k => f(v) for every k => v in t.
Not thread-safe: Builds the result by traversing the live leaf chain of t.
def mapWithKey(rc1: Region[r1], f: k -> (v1 -> v2 \ ef), t: BPlusTree[k, v1, r]): BPlusTree[k, v2, r1] \ ef + r + r1 with Order[k]§ SourceReturns a BPlusTree with mappings k => f(k, v) for every k => v in t.
Not thread-safe: Builds the result by traversing the live leaf chain of t.
Optionally returns k => v where k is the largest key in t according to the
Order instance on k.
Returns None if t is empty.
Thread-safe.
Returns true if and only if t contains the key k.
Thread-safe.
Returns true if and only if t contains the mapping k => v.
Thread-safe.
Merge src into dst, modifying dst in a left-biased manner.
That is, key collisions are resolved by taking the mapping from src.
Not thread-safe: Traverses the live leaf chain of src.
def mergeWith(f: v -> (v -> v \ ef), src: BPlusTree[k, v, r1], dst: BPlusTree[k, v, r2]): Unit \ r1 + r2 + ef with Order[k]§ SourceMerges src into dst, modifying dst. If k => v1 is in src and k => v2 is
in dst, updates dst with k => f(v1, v2).
Not thread-safe: Traverses the live leaf chain of src.
def mergeWithKey(f: k -> (v -> (v -> v \ ef)), src: BPlusTree[k, v, r1], dst: BPlusTree[k, v, r2]): Unit \ r1 + r2 + ef with Order[k]§ SourceMerges src into dst, modifying dst in-place. If k => v1 is in src and
k => v2 is in dst, then dst is updated with k => f(k, v1, v2).
Not thread-safe: Traverses the live leaf chain of src.
Optionally returns k => v where k is the smallest key in t according to the
Order instance on k.
Returns None if t is empty.
Thread-safe.
Returns true if and only if t contains at least one mapping.
Thread-safe.
@Parallel Applies f to all mappings k => v in t in parallel.
f must not modify t.
This method unsafe removes the r effect when spawning threads.
Not thread-safe: Traverses the live leaf chain of t in parallel.
@Parallel def parForEachWhen(f1: k -> (v -> Unit \ r), f2: k -> (v -> Unit \ r), parLimit: Int32, t: BPlusTree[k, v, r]): Unit \ r§ SourceApplies f1 to all mappings k => v in t sequentially if t contains strictly less than
parLimit elements. If t contains parLimit or more elements f2 is applied in parallel
to all mappings.
f1 and f2 must not modify t.
This method unsafe removes the r effect when spawning threads in case 2.
Not thread-safe: Traverses the live leaf chain of t, potentially in parallel.
Updates the tree t with the mapping k => v, replacing any existing mapping.
Thread-safe.
def putAll(kvs: f[(k, v)], t: BPlusTree[k, v, r]): Unit \ r + Aef[f] with Order[k], Foldable[f]§ SourceUpdates the tree t with all mappings k => v in kvs, replacing any existing mappings.
Thread-safe.
def putIf(decider: k -> (v -> (k -> (v -> Bool))), k: k, v: v, t: BPlusTree[k, v, r]): Unit \ r with Order[k]§ SourceUpdates the tree t with the mapping k => v, replacing any existing mapping,
k2 => v2, if decider(k, v, k2, v2) == true.
Thread-safe and atomic.
def putWith(f: v -> (v -> v \ ef), k: k, v: v, t: BPlusTree[k, v, r]): Unit \ ef + r with Order[k]§ SourceUpdates t with k => f(v, v1) if k => v1 is in t.
Otherwise, updates t with k => v.
Thread-safe.
def putWithKey(f: k -> (v -> (v -> v \ ef)), k: k, v: v, t: BPlusTree[k, v, r]): Unit \ r + ef with Order[k]§ SourceUpdates t with the mapping k => f(k, v, v1) if k => v1 is in t.
Otherwise, updates t with the mapping k => v.
Thread-safe.
Returns the list of mappings k => v in t where min <= k <= max according to
the Order instance on k.
Not thread-safe: Builds the result by traversing the live leaf chain of t in range order.
def rangeQueryWith(f: k -> (v -> Unit \ ef), min: k, max: k, t: BPlusTree[k, v, r]): Unit \ r + ef with Order[k]§ SourceApplies f in ascending order to all mappings k => v in t where
min <= k <= max.
Not thread-safe: Traverses the live leaf chain of t in range order.
def sameElements(t1: BPlusTree[k, v, r1], t2: BPlusTree[k, v, r2]): Bool \ r1 + r2 with Order[k], Eq[v]§ SourceReturns true if t1 and t2 contain the same keys and values, regardless of
each individual tree's internal structure.
Not thread-safe: Compares the live leaf chains of t1 and t2.
Returns the size of t. This operation is O(1).
Not atomic.
Thread-safe.
Returns a list of the key-value pairs in t. Elements are ordered from smallest
(left) to largest (right).
Not thread-safe: Builds the result by traversing the live leaf chain of t.
Returns t as an immutable map.
Not thread-safe: Builds the result by traversing the live leaf chain of t.
Returns t as a set of key-value pairs.
Not thread-safe: Builds the result by traversing the live leaf chain of t.
Returns a string representation of t.
Not thread-safe: Traverses the live tree without synchronization.
Returns t as a vector of key-value pairs.
Not thread-safe: Builds the result by traversing the live leaf chain of t.
Applies the function f to every value in t.
Not thread-safe: Mutates the live leaf chain of t in place.