github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/common/dlnode.go (about) 1 // Copyright 2021 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package common 16 17 import ( 18 "sync" 19 ) 20 21 // Usage Example 22 /* 23 type Row struct { 24 id int 25 } 26 27 func compare(a, b *Row) int { 28 if a.id > b.id { 29 return 1 30 } else if a.id < b.id { 31 return -1 32 } 33 return 0 34 } 35 36 dlist := NewGenericSortedDList[*Row](compare) 37 n1 := dlist.Insert(&Row{id: 10}) // [10] 38 n2 := dlist.Insert(&Row{id: 5}) // [10]<->[5] 39 n3 := dlist.Insert(&Row{id: 13}) // [13]<->[10]<->[5] 40 n3.id = 8 41 dlist.Update(n3) // [10]<->[8]<->[5] 42 dlist.Delete(n1) // [8]<->[5] 43 44 it := NewGenericSortedDListIt(nil, dlist,true) 45 for it.Valid() { 46 n := it.GetPayload() 47 // n.xxx 48 it.Next() 49 } 50 */ 51 52 // Sorted doubly linked-list 53 type GenericSortedDList[T any] struct { 54 head *GenericDLNode[T] 55 tail *GenericDLNode[T] 56 compare func(T, T) int 57 depth int 58 } 59 60 func NewGenericSortedDList[T any](compare func(T, T) int) *GenericSortedDList[T] { 61 return &GenericSortedDList[T]{ 62 compare: compare, 63 } 64 } 65 66 // Get the head node 67 func (l *GenericSortedDList[T]) GetHead() *GenericDLNode[T] { 68 return l.head 69 } 70 71 // Get the tail node 72 func (l *GenericSortedDList[T]) GetTail() *GenericDLNode[T] { 73 return l.tail 74 } 75 76 // Update the node to keep the list be sorted 77 // 78 // [List] [1,x1] <-> [3,x3] <-> [10,x10] <-> [20,x20] 79 // 80 // | 81 // 82 // [Node] [10,x10] 83 // 84 // --------- UPDATE [10,x10] TO [2, x10]-------------- 85 // 86 // [List] [1,x1] <-> [2,x10] <-> [3,x3] <-> [20,x20] 87 func (l *GenericSortedDList[T]) Update(n *GenericDLNode[T]) { 88 nhead, ntail := n.KeepSorted(l.compare) 89 if nhead != nil { 90 l.head = nhead 91 } 92 if ntail != nil { 93 l.tail = ntail 94 } 95 } 96 97 // Get the length of the list 98 func (l *GenericSortedDList[T]) Depth() int { 99 return l.depth 100 } 101 102 // Insert a object and wrap it as GenericDLNode into the list 103 // The inserted object must be instance of interface NodePayload 104 // [List]: [1,x1] <-> [5,x5] <-> [10,x10] 105 // Insert a node [7,x7] 106 // [List]: [1,x1] <-> [5,x5] <-> [7,x7] <-> [10,x10] 107 func (l *GenericSortedDList[T]) Insert(payload T) *GenericDLNode[T] { 108 var ( 109 n *GenericDLNode[T] 110 tail *GenericDLNode[T] 111 ) 112 n, l.head, tail = InsertGenericDLNode(payload, l.head, l.compare) 113 if tail != nil { 114 l.tail = tail 115 } 116 l.depth += 1 117 return n 118 } 119 120 // Given a node and remove it from the list 121 // 122 // Delete [node] 123 // 124 // [prev node] <-> [node] <-> [next node] =============> [prev node] <-> [next node] 125 func (l *GenericSortedDList[T]) Delete(n *GenericDLNode[T]) { 126 prev := n.prev 127 next := n.next 128 if prev != nil && next != nil { 129 prev.next = next 130 next.prev = prev 131 } else if prev == nil && next != nil { 132 l.head = next 133 next.prev = nil 134 } else if prev != nil && next == nil { 135 l.tail = prev 136 prev.next = nil 137 } else { 138 l.head = nil 139 l.tail = nil 140 } 141 l.depth -= 1 142 } 143 144 // Loop the list and apply fn on each node 145 func (l *GenericSortedDList[T]) Loop(fn func(n *GenericDLNode[T]) bool, reverse bool) { 146 if reverse { 147 LoopGenericSortedDList(l.tail, fn, reverse) 148 } else { 149 LoopGenericSortedDList(l.head, fn, reverse) 150 } 151 } 152 153 // Doubly sorted linked-list node 154 type GenericDLNode[T any] struct { 155 prev, next *GenericDLNode[T] 156 payload T 157 } 158 159 func (l *GenericDLNode[T]) GetPayload() T { return l.payload } 160 func (l *GenericDLNode[T]) GetPrev() *GenericDLNode[T] { return l.prev } 161 func (l *GenericDLNode[T]) GetNext() *GenericDLNode[T] { return l.next } 162 163 // Keep node be sorted in the list 164 func (l *GenericDLNode[T]) KeepSorted(compare func(T, T) int) (head, tail *GenericDLNode[T]) { 165 curr := l 166 head = curr 167 prev := l.prev 168 next := l.next 169 for (curr != nil && next != nil) && (compare(curr.payload, next.payload) < 0) { 170 if head == curr { 171 head = next 172 } 173 174 if prev != nil { 175 prev.next = next 176 } 177 next.prev = prev 178 179 prev = next 180 next = next.next 181 182 prev.next = curr 183 curr.prev = prev 184 curr.next = next 185 if next != nil { 186 next.prev = curr 187 } 188 } 189 if next == nil { 190 tail = curr 191 } 192 if head.prev != nil { 193 head = nil 194 } 195 return head, tail 196 } 197 198 // Insert a wrapped object into a list specified by a head node 199 // node is the inserted dlnode 200 // nhead is the new head node 201 // ntail is the new tail node. 202 // If ntail is not nil, tail is updated. Else tail is not updated 203 func InsertGenericDLNode[T any](payload T, 204 head *GenericDLNode[T], 205 compare func(T, T) int) (node, nhead, ntail *GenericDLNode[T]) { 206 node = &GenericDLNode[T]{ 207 payload: payload, 208 } 209 if head == nil { 210 nhead = node 211 ntail = node 212 return 213 } 214 215 node.next = head 216 head.prev = node 217 nhead, ntail = node.KeepSorted(compare) 218 return 219 } 220 221 // Loop the list and apply fn on each node 222 // head is the head node of a list 223 // fn is operation applied to each node during iterating. 224 // if fn(node) returns false, stop iterating. 225 // reverse is true to loop in reversed way. 226 func LoopGenericSortedDList[T any](head *GenericDLNode[T], 227 fn func(node *GenericDLNode[T]) bool, 228 reverse bool) { 229 curr := head 230 for curr != nil { 231 goNext := fn(curr) 232 if !goNext { 233 break 234 } 235 if reverse { 236 curr = curr.prev 237 } else { 238 curr = curr.next 239 } 240 } 241 } 242 243 // Sorted doubly linked-list iterator 244 type GenericSortedDListIt[T any] struct { 245 linkLocker *sync.RWMutex 246 curr *GenericDLNode[T] 247 nextFunc func(*GenericDLNode[T]) *GenericDLNode[T] 248 } 249 250 // linkLocker is the outer locker to guard dlist access 251 func NewGenericSortedDListIt[T any](linkLocker *sync.RWMutex, 252 dlist *GenericSortedDList[T], 253 reverse bool) *GenericSortedDListIt[T] { 254 it := &GenericSortedDListIt[T]{ 255 linkLocker: linkLocker, 256 } 257 if reverse { 258 it.nextFunc = func(n *GenericDLNode[T]) *GenericDLNode[T] { 259 return n.prev 260 } 261 it.curr = dlist.tail 262 } else { 263 it.nextFunc = func(n *GenericDLNode[T]) *GenericDLNode[T] { 264 return n.next 265 } 266 it.curr = dlist.head 267 } 268 return it 269 } 270 271 func (it *GenericSortedDListIt[T]) Valid() bool { 272 return it.curr != nil 273 } 274 275 func (it *GenericSortedDListIt[T]) Next() { 276 if it.linkLocker == nil { 277 it.curr = it.nextFunc(it.curr) 278 return 279 } 280 it.linkLocker.RLock() 281 it.curr = it.nextFunc(it.curr) 282 it.linkLocker.RUnlock() 283 } 284 285 func (it *GenericSortedDListIt[T]) Get() *GenericDLNode[T] { 286 return it.curr 287 }