github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/lib/list/x_com_skl.go (about)

     1  package list
     2  
     3  import (
     4  	"cmp"
     5  	"sync/atomic"
     6  
     7  	"github.com/benz9527/xboot/lib/infra"
     8  )
     9  
    10  var _ XSkipList[uint8, uint8] = (*xComSkl[uint8, uint8])(nil)
    11  
    12  // A common (not thread safe) implementation of skip-list.
    13  // @field head A sentinel node.
    14  // The head.indices[0].succ is the first data node of skip-list.
    15  // From head.indices[1], all of them are cache used to implement binary search.
    16  // @field tail A sentinel node. Points the skip-list tail node.
    17  type xComSkl[K infra.OrderedKey, V any] struct {
    18  	vcmp         SklValComparator[V] // value comparator
    19  	rand         SklRand
    20  	head         *xComSklNode[K, V]
    21  	tail         *xComSklNode[K, V]
    22  	nodeLen      int64  // skip-list's node count.
    23  	indexCount   uint64 // skip-list's index count.
    24  	levels       int32  // skip-list's max height value inside the indexCount.
    25  	isKeyCmpDesc bool
    26  }
    27  
    28  // findPredecessor0 is used to find the (succ) first element whose key value equals to target key value.
    29  // Preparing for linear probing. O(N)
    30  // @return value 1: the pred node
    31  // @return value 2: the query traverse path (nodes)
    32  func (skl *xComSkl[K, V]) findPredecessor0(key K, aux []*xComSklNode[K, V]) (*xComSklNode[K, V], []*xComSklNode[K, V]) {
    33  	var forward *xComSklNode[K, V]
    34  	forward = skl.head
    35  	for /* vertical */ i := skl.Levels() - 1; i >= 0; i-- {
    36  		for /* horizontal */ forward.levels()[i] != nil {
    37  			cur := forward.levels()[i]
    38  			res := cmp.Compare[K](key, cur.Element().Key())
    39  			if /* greater, forward next */ cur != nil && (!skl.isKeyCmpDesc && res > 0) || (skl.isKeyCmpDesc && res < 0) {
    40  				// Linear probing (forward next) at level 0 most likely.
    41  				forward = cur
    42  			} else /* lower or equal, downward to next level */ {
    43  				break
    44  			}
    45  		}
    46  		if aux != nil {
    47  			aux[i] = forward
    48  		}
    49  	}
    50  
    51  	if /* not found */ forward == nil {
    52  		return nil, aux
    53  	}
    54  
    55  	target := forward.levels()[0]
    56  	if /* found */ target != nil && key == target.Element().Key() {
    57  		return forward, aux
    58  	}
    59  	return /* not found */ nil, aux
    60  }
    61  
    62  // removeNode will reduce the levels.
    63  func (skl *xComSkl[K, V]) removeNode(x *xComSklNode[K, V], aux []*xComSklNode[K, V]) {
    64  	for i := int32(0); i < skl.Levels(); i++ {
    65  		if aux[i].levels()[i] == x {
    66  			aux[i].levels()[i] = x.levels()[i]
    67  		}
    68  	}
    69  	if /* unlink */ next := x.levels()[0]; next != nil {
    70  		next.setBackward(x.backward())
    71  	} else {
    72  		skl.tail = x.backward()
    73  	}
    74  	atomic.AddUint64(&skl.indexCount, ^uint64(len(x.indices)-1))
    75  	for /* reduce levels */ skl.Levels() > 1 && skl.head.levels()[skl.Levels()-1] == nil {
    76  		atomic.AddInt32(&skl.levels, -1)
    77  	}
    78  	atomic.AddInt64(&skl.nodeLen, -1)
    79  }
    80  
    81  // Classic Skip-List basic APIs
    82  
    83  func (skl *xComSkl[K, V]) Len() int64 {
    84  	return atomic.LoadInt64(&skl.nodeLen)
    85  }
    86  
    87  func (skl *xComSkl[K, V]) IndexCount() uint64 {
    88  	return atomic.LoadUint64(&skl.indexCount)
    89  }
    90  
    91  func (skl *xComSkl[K, V]) Levels() int32 {
    92  	return atomic.LoadInt32(&skl.levels)
    93  }
    94  
    95  func (skl *xComSkl[K, V]) Insert(key K, val V, ifNotPresent ...bool) error {
    96  	if skl.Len() >= sklMaxSize {
    97  		return infra.WrapErrorStack(ErrXSklIsFull)
    98  	}
    99  
   100  	var (
   101  		pred = skl.head
   102  		aux  = make([]*xComSklNode[K, V], sklMaxLevel)
   103  	)
   104  
   105  	if len(ifNotPresent) <= 0 {
   106  		ifNotPresent = insertReplaceDisabled
   107  	}
   108  
   109  	for /* vertical */ i := atomic.LoadInt32(&skl.levels) - 1; i >= 0; i-- {
   110  		for /* horizontal */ pred.levels()[i] != nil {
   111  			cur := pred.levels()[i]
   112  			res := func() int64 {
   113  				curKey := cur.Element().Key()
   114  				_res := cmp.Compare[K](key, curKey)
   115  				if (!skl.isKeyCmpDesc && _res > 0) || (skl.isKeyCmpDesc && _res < 0) {
   116  					return +1
   117  				} else if _res == 0 {
   118  					return 0
   119  				}
   120  				return -1
   121  			}()
   122  			if /* next insert position */ res > 0 || (res == 0 && skl.vcmp(val, cur.Element().Val()) > 0) {
   123  				pred = cur
   124  			} else /* replace */ if res == 0 && skl.vcmp(val, cur.Element().Val()) == 0 {
   125  				if /* disabled */ ifNotPresent[0] {
   126  					return infra.WrapErrorStack(ErrXSklDisabledValReplace)
   127  
   128  				}
   129  				cur.element = &xSklElement[K, V]{
   130  					key: key,
   131  					val: val,
   132  				}
   133  				return nil
   134  			} else {
   135  				break
   136  			}
   137  		}
   138  		// 1. (key duplicated) If new element hash is lower than current node's (do pre-append to current node)
   139  		// 2. (key duplicated) If new element hash is greater than current node's (do append next to current node)
   140  		// 3. (key duplicated) If new element hash equals to current node's (replace an element, because the hash
   141  		//      value and element are not strongly correlated)
   142  		// 4. (new key) If a new element does not exist, (do append next to the current node)
   143  		aux[i] = pred
   144  	}
   145  
   146  	// Each duplicated key element may contain its cache levels.
   147  	// It means that duplicated key elements query through the cache (O(logN))
   148  	// But duplicated elements query (linear probe) will be degraded into O(N)
   149  	lvl := skl.rand(sklMaxLevel, skl.Len())
   150  	if lvl > skl.Levels() {
   151  		for i := skl.Levels(); i < lvl; i++ {
   152  			// Update the whole traverse path, from top to bottom.
   153  			aux[i] = skl.head // avoid nil pointer
   154  		}
   155  		atomic.StoreInt32(&skl.levels, lvl)
   156  	}
   157  	atomic.AddUint64(&skl.indexCount, uint64(lvl))
   158  	newNode := genXComSklNode[K, V](key, val, lvl)
   159  	for i := int32(0); i < lvl; i++ {
   160  		next := aux[i].levels()[i]
   161  		newNode.levels()[i] = next
   162  		aux[i].levels()[i] = newNode
   163  	}
   164  	if aux[0] == skl.head {
   165  		newNode.setBackward(nil)
   166  	} else {
   167  		newNode.setBackward(aux[0])
   168  	}
   169  	if newNode.levels()[0] == nil {
   170  		skl.tail = newNode
   171  	} else {
   172  		newNode.levels()[0].setBackward(newNode)
   173  	}
   174  	atomic.AddInt64(&skl.nodeLen, 1)
   175  	return nil
   176  }
   177  
   178  func (skl *xComSkl[K, V]) LoadFirst(key K) (SklElement[K, V], error) {
   179  	if skl.Len() <= 0 {
   180  		return nil, infra.WrapErrorStack(ErrXSklIsEmpty)
   181  	}
   182  
   183  	e, _ := skl.findPredecessor0(key, nil)
   184  	if e.levels() == nil {
   185  		return nil, infra.WrapErrorStack(ErrXSklNotFound)
   186  	}
   187  	return e.levels()[0].Element(), nil
   188  }
   189  
   190  func (skl *xComSkl[K, V]) RemoveFirst(key K) (SklElement[K, V], error) {
   191  	if skl.Len() <= 0 {
   192  		return nil, infra.WrapErrorStack(ErrXSklIsEmpty)
   193  	}
   194  
   195  	aux := make([]*xComSklNode[K, V], sklMaxLevel)
   196  	pred, aux := skl.findPredecessor0(key, aux[:])
   197  	if pred == nil {
   198  		return nil, infra.WrapErrorStack(ErrXSklNotFound)
   199  	}
   200  
   201  	target := pred.levels()[0]
   202  	if target != nil && key == target.Element().Key() {
   203  		skl.removeNode(target, aux)
   204  		return target.Element(), nil
   205  	}
   206  	return nil, infra.WrapErrorStack(ErrXSklNotFound)
   207  }
   208  
   209  func (skl *xComSkl[K, V]) Foreach(action func(i int64, item SklIterationItem[K, V]) bool) {
   210  	if skl.Len() <= 0 {
   211  		return
   212  	}
   213  
   214  	var (
   215  		x    *xComSklNode[K, V]
   216  		i    int64
   217  		item = &xSklIter[K, V]{}
   218  	)
   219  	x = skl.head.levels()[0]
   220  	for x != nil {
   221  		next := x.levels()[0]
   222  		item.keyFn = x.element.Key
   223  		item.valFn = x.element.Val
   224  		item.nodeLevelFn = func() uint32 {
   225  			return uint32(len(x.levels()))
   226  		}
   227  		item.nodeItemCountFn = func() int64 {
   228  			return 1
   229  		}
   230  		if !action(i, item) {
   231  			break
   232  		}
   233  		i++
   234  		x = next
   235  	}
   236  }
   237  
   238  func (skl *xComSkl[K, V]) PeekHead() SklElement[K, V] {
   239  	target := skl.head
   240  	if target == nil || skl.Len() <= 0 {
   241  		return nil
   242  	}
   243  	if target = target.levels()[0]; target == nil {
   244  		return nil
   245  	}
   246  	return target.Element()
   247  }
   248  
   249  func (skl *xComSkl[K, V]) PopHead() (element SklElement[K, V], err error) {
   250  	target := skl.head
   251  	if skl.Len() <= 0 || target == nil {
   252  		return nil, infra.WrapErrorStack(ErrXSklIsEmpty)
   253  	}
   254  	if target = target.levels()[0]; target == nil {
   255  		return nil, infra.WrapErrorStack(ErrXSklIsEmpty)
   256  	}
   257  	element = target.Element()
   258  	return skl.RemoveFirst(element.Key())
   259  }
   260  
   261  // Duplicated element Skip-List basic APIs
   262  
   263  func (skl *xComSkl[K, V]) LoadIfMatch(key K, matcher func(that V) bool) ([]SklElement[K, V], error) {
   264  	if skl.Len() <= 0 {
   265  		return nil, infra.WrapErrorStack(ErrXSklIsEmpty)
   266  	}
   267  
   268  	aux := make([]*xComSklNode[K, V], sklMaxLevel)
   269  	pred, _ := skl.findPredecessor0(key, aux)
   270  	if pred == nil {
   271  		return nil, infra.WrapErrorStack(ErrXSklNotFound)
   272  	}
   273  
   274  	elements := make([]SklElement[K, V], 0, 16)
   275  	for cur := pred.levels()[0]; cur != nil && key == cur.Element().Key(); cur = cur.levels()[0] {
   276  		if matcher(cur.Element().Val()) {
   277  			elements = append(elements, cur.Element())
   278  		}
   279  	}
   280  	return elements, nil
   281  }
   282  
   283  func (skl *xComSkl[K, V]) LoadAll(key K) ([]SklElement[K, V], error) {
   284  	if skl.Len() <= 0 {
   285  		return nil, infra.WrapErrorStack(ErrXSklIsEmpty)
   286  	}
   287  
   288  	pred, _ := skl.findPredecessor0(key, nil)
   289  	if pred == nil {
   290  		return nil, infra.WrapErrorStack(ErrXSklNotFound)
   291  	}
   292  
   293  	elements := make([]SklElement[K, V], 0, 16)
   294  	for cur := pred.levels()[0]; cur != nil && key == cur.Element().Key(); cur = cur.levels()[0] {
   295  		elements = append(elements, cur.Element())
   296  	}
   297  	return elements, nil
   298  }
   299  
   300  func (skl *xComSkl[K, V]) RemoveIfMatch(key K, matcher func(that V) bool) ([]SklElement[K, V], error) {
   301  	if skl.Len() <= 0 {
   302  		return nil, infra.WrapErrorStack(ErrXSklIsEmpty)
   303  	}
   304  
   305  	aux := make([]*xComSklNode[K, V], sklMaxLevel)
   306  	pred, aux := skl.findPredecessor0(key, aux)
   307  	if pred == nil {
   308  		return nil, infra.WrapErrorStack(ErrXSklNotFound)
   309  	}
   310  
   311  	elements := make([]SklElement[K, V], 0, 16)
   312  	for cur := pred.levels()[0]; cur != nil && key == cur.Element().Key(); {
   313  		if matcher(cur.Element().Val()) {
   314  			skl.removeNode(cur, aux)
   315  			elements = append(elements, cur.Element())
   316  			next := cur.levels()[0]
   317  			cur.Free()
   318  			cur = next
   319  		} else {
   320  			// Merge the traverse path.
   321  			for i := 0; i < len(cur.levels()); i++ {
   322  				aux[i] = cur
   323  			}
   324  			cur = cur.levels()[0]
   325  		}
   326  	}
   327  	return elements, nil
   328  }
   329  
   330  func (skl *xComSkl[K, V]) RemoveAll(key K) ([]SklElement[K, V], error) {
   331  	if skl.Len() <= 0 {
   332  		return nil, infra.WrapErrorStack(ErrXSklIsEmpty)
   333  	}
   334  
   335  	aux := make([]*xComSklNode[K, V], sklMaxLevel)
   336  	pred, aux := skl.findPredecessor0(key, aux)
   337  	if pred == nil {
   338  		return nil, infra.WrapErrorStack(ErrXSklNotFound)
   339  	}
   340  
   341  	elements := make([]SklElement[K, V], 0, 16)
   342  	for cur := pred.levels()[0]; cur != nil && key == cur.Element().Key(); {
   343  		skl.removeNode(cur, aux)
   344  		elements = append(elements, cur.Element())
   345  		free := cur
   346  		cur = cur.levels()[0]
   347  		free.Free()
   348  	}
   349  	return elements, nil
   350  }
   351  
   352  func (skl *xComSkl[K, V]) Release() {
   353  	var (
   354  		x, next *xComSklNode[K, V]
   355  		idx     int
   356  	)
   357  	x = skl.head.levels()[0]
   358  	for x != nil {
   359  		next = x.levels()[0]
   360  		x.Free()
   361  		x = next
   362  	}
   363  	for idx = 0; idx < sklMaxLevel; idx++ {
   364  		skl.head.levels()[idx] = nil
   365  	}
   366  	skl.tail = nil
   367  }