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  }