github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/go/callgraph/vta/internal/trie/trie.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // trie implements persistent Patricia trie maps. 6 // 7 // Each Map is effectively a map from uint64 to interface{}. Patricia tries are 8 // a form of radix tree that are particularly appropriate when many maps will be 9 // created, merged together and large amounts of sharing are expected (e.g. 10 // environment abstract domains in program analysis). 11 // 12 // This implementation closely follows the paper: 13 // 14 // C. Okasaki and A. Gill, “Fast mergeable integer maps,” in ACM SIGPLAN 15 // Workshop on ML, September 1998, pp. 77–86. 16 // 17 // Each Map is immutable and can be read from concurrently. The map does not 18 // guarantee that the value pointed to by the interface{} value is not updated 19 // concurrently. 20 // 21 // These Maps are optimized for situations where there will be many maps created at 22 // with a high degree of sharing and combining of maps together. If you do not expect, 23 // significant amount of sharing, the builtin map[T]U is much better choice! 24 // 25 // Each Map is created by a Builder. Each Builder has a unique Scope and each node is 26 // created within this scope. Maps x and y are == if they contains the same 27 // (key,value) mappings and have equal scopes. 28 // 29 // Internally these are big endian Patricia trie nodes, and the keys are sorted. 30 package trie 31 32 import ( 33 "fmt" 34 "strings" 35 ) 36 37 // Map is effectively a finite mapping from uint64 keys to interface{} values. 38 // Maps are immutable and can be read from concurrently. 39 // 40 // Notes on concurrency: 41 // - A Map value itself is an interface and assignments to a Map value can race. 42 // - Map does not guarantee that the value pointed to by the interface{} value 43 // is not updated concurrently. 44 type Map struct { 45 s Scope 46 n node 47 } 48 49 func (m Map) Scope() Scope { 50 return m.s 51 } 52 func (m Map) Size() int { 53 if m.n == nil { 54 return 0 55 } 56 return m.n.size() 57 } 58 func (m Map) Lookup(k uint64) (interface{}, bool) { 59 if m.n != nil { 60 if leaf := m.n.find(key(k)); leaf != nil { 61 return leaf.v, true 62 } 63 } 64 return nil, false 65 } 66 67 // Converts the map into a {<key>: <value>[, ...]} string. This uses the default 68 // %s string conversion for <value>. 69 func (m Map) String() string { 70 var kvs []string 71 m.Range(func(u uint64, i interface{}) bool { 72 kvs = append(kvs, fmt.Sprintf("%d: %s", u, i)) 73 return true 74 }) 75 return fmt.Sprintf("{%s}", strings.Join(kvs, ", ")) 76 } 77 78 // Range over the leaf (key, value) pairs in the map in order and 79 // applies cb(key, value) to each. Stops early if cb returns false. 80 // Returns true if all elements were visited without stopping early. 81 func (m Map) Range(cb func(uint64, interface{}) bool) bool { 82 if m.n != nil { 83 return m.n.visit(cb) 84 } 85 return true 86 } 87 88 // DeepEqual returns true if m and other contain the same (k, v) mappings 89 // [regardless of Scope]. 90 // 91 // Equivalently m.DeepEqual(other) <=> reflect.DeepEqual(Elems(m), Elems(other)) 92 func (m Map) DeepEqual(other Map) bool { 93 if m.Scope() == other.Scope() { 94 return m.n == other.n 95 } 96 if (m.n == nil) || (other.n == nil) { 97 return m.Size() == 0 && other.Size() == 0 98 } 99 return m.n.deepEqual(other.n) 100 } 101 102 // Elems are the (k,v) elements in the Map as a map[uint64]interface{} 103 func Elems(m Map) map[uint64]interface{} { 104 dest := make(map[uint64]interface{}, m.Size()) 105 m.Range(func(k uint64, v interface{}) bool { 106 dest[k] = v 107 return true 108 }) 109 return dest 110 } 111 112 // node is an internal node within a trie map. 113 // A node is either empty, a leaf or a branch. 114 type node interface { 115 size() int 116 117 // visit the leaves (key, value) pairs in the map in order and 118 // applies cb(key, value) to each. Stops early if cb returns false. 119 // Returns true if all elements were visited without stopping early. 120 visit(cb func(uint64, interface{}) bool) bool 121 122 // Two nodes contain the same elements regardless of scope. 123 deepEqual(node) bool 124 125 // find the leaf for the given key value or nil if it is not present. 126 find(k key) *leaf 127 128 // implementations must implement this. 129 nodeImpl() 130 } 131 132 // empty represents the empty map within a scope. 133 // 134 // The current builder ensure 135 type empty struct { 136 s Scope 137 } 138 139 // leaf represents a single <key, value> pair. 140 type leaf struct { 141 k key 142 v interface{} 143 } 144 145 // branch represents a tree node within the Patricia trie. 146 // 147 // All keys within the branch match a `prefix` of the key 148 // up to a `branching` bit, and the left and right nodes 149 // contain keys that disagree on the bit at the `branching` bit. 150 type branch struct { 151 sz int // size. cached for O(1) lookup 152 prefix prefix // == mask(p0, branching) for some p0 153 branching bitpos 154 155 // Invariants: 156 // - neither is nil. 157 // - neither is *empty. 158 // - all keys in left are <= p. 159 // - all keys in right are > p. 160 left, right node 161 } 162 163 // all of these types are Maps. 164 var _ node = &empty{} 165 var _ node = &leaf{} 166 var _ node = &branch{} 167 168 func (*empty) nodeImpl() {} 169 func (*leaf) nodeImpl() {} 170 func (*branch) nodeImpl() {} 171 172 func (*empty) find(k key) *leaf { return nil } 173 func (l *leaf) find(k key) *leaf { 174 if k == l.k { 175 return l 176 } 177 return nil 178 } 179 func (br *branch) find(k key) *leaf { 180 kp := prefix(k) 181 if !matchPrefix(kp, br.prefix, br.branching) { 182 return nil 183 } 184 if zeroBit(kp, br.branching) { 185 return br.left.find(k) 186 } 187 return br.right.find(k) 188 } 189 190 func (*empty) size() int { return 0 } 191 func (*leaf) size() int { return 1 } 192 func (br *branch) size() int { return br.sz } 193 194 func (*empty) deepEqual(m node) bool { 195 _, ok := m.(*empty) 196 return ok 197 } 198 func (l *leaf) deepEqual(m node) bool { 199 if m, ok := m.(*leaf); ok { 200 return m == l || (l.k == m.k && l.v == m.v) 201 } 202 return false 203 } 204 205 func (br *branch) deepEqual(m node) bool { 206 if m, ok := m.(*branch); ok { 207 if br == m { 208 return true 209 } 210 return br.sz == m.sz && br.branching == m.branching && br.prefix == m.prefix && 211 br.left.deepEqual(m.left) && br.right.deepEqual(m.right) 212 } 213 // if m is not a branch, m contains 0 or 1 elem. 214 // br contains at least 2 keys that disagree on a prefix. 215 return false 216 } 217 218 func (*empty) visit(cb func(uint64, interface{}) bool) bool { 219 return true 220 } 221 func (l *leaf) visit(cb func(uint64, interface{}) bool) bool { 222 return cb(uint64(l.k), l.v) 223 } 224 func (br *branch) visit(cb func(uint64, interface{}) bool) bool { 225 if !br.left.visit(cb) { 226 return false 227 } 228 return br.right.visit(cb) 229 }