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

     1  package list
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"sync"
     7  
     8  	"go.uber.org/multierr"
     9  
    10  	"github.com/benz9527/xboot/lib/id"
    11  	"github.com/benz9527/xboot/lib/infra"
    12  )
    13  
    14  // References:
    15  // https://people.csail.mit.edu/shanir/publications/DCAS.pdf
    16  // https://www.cl.cam.ac.uk/teaching/0506/Algorithms/skiplists.pdf
    17  // https://people.csail.mit.edu/shanir/publications/LazySkipList.pdf
    18  //
    19  // github:
    20  // classic: https://github.com/antirez/disque/blob/master/src/skiplist.h
    21  // classic: https://github.com/antirez/disque/blob/master/src/skiplist.c
    22  // zskiplist: https://github1s.com/redis/redis/blob/unstable/src/t_zset.c
    23  // https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
    24  // https://github.com/zhangyunhao116/skipmap
    25  // https://github.com/liyue201/gostl
    26  // https://github.com/chen3feng/stl4go
    27  // https://github.com/slclub/skiplist/blob/master/skipList.go
    28  // https://github.com/andy-kimball/arenaskl
    29  // https://github.com/dgraph-io/badger/tree/master/skl
    30  // https://github.com/BazookaMusic/goskiplist/blob/master/skiplist.go
    31  // https://github.com/boltdb/bolt/blob/master/freelist.go
    32  // https://github.com/xuezhaokun/150-algorithm/tree/master
    33  //
    34  // test:
    35  // https://github.com/chen3feng/skiplist-survey
    36  //
    37  //
    38  // Head nodes          Index nodes
    39  // +-+    right        +-+                      +-+
    40  // |2|---------------->| |--------------------->| |->null
    41  // +-+                 +-+                      +-+
    42  //  | down              |                        |
    43  //  v                   v                        v
    44  // +-+            +-+  +-+       +-+            +-+       +-+
    45  // |1|----------->| |->| |------>| |----------->| |------>| |->null
    46  // +-+            +-+  +-+       +-+            +-+       +-+
    47  //  v              |    |         |              |         |
    48  // Nodes  next     v    v         v              v         v
    49  // +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+
    50  // | |->|A|->|B|->|C|->|D|->|E|->|F|->|G|->|H|->|I|->|J|->|K|->null
    51  // +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+
    52  
    53  const (
    54  	sklMaxLevel    = 32                     // level 0 is the data node level.
    55  	sklMaxSize     = 1<<(sklMaxLevel-1) - 1 //  2^31 - 1 elements
    56  	sklProbability = 0.25                   // P = 1/4, a skip list node element has 1/4 probability to have a level
    57  )
    58  
    59  type sklError string
    60  
    61  func (err sklError) Error() string {
    62  	return string(err)
    63  }
    64  
    65  const (
    66  	ErrXSklNotFound             = sklError("[x-skl] key or value not found")
    67  	ErrXSklDisabledValReplace   = sklError("[x-skl] value replace is disabled")
    68  	ErrXSklConcRWLoadFailed     = sklError("[x-skl] concurrent read-write causes load failed")
    69  	ErrXSklConcRWLoadEmpty      = sklError("[x-skl] concurrent read-write causes load empty")
    70  	ErrXSklConcRemoving         = sklError("[x-skl] concurrent removing")
    71  	ErrXSklConcRemoveTryLock    = sklError("[x-skl] concurrent remove acquires segmented lock failed")
    72  	ErrXSklUnknownReason        = sklError("[x-skl] unknown reason error")
    73  	ErrXSklUnknownType          = sklError("[x-skl] unknown skip list type")
    74  	ErrXSklIsFull               = sklError("[x-skl] is full")
    75  	ErrXSklIsEmpty              = sklError("[x-skl] is empty")
    76  	errXSklRbtreeRedViolation   = sklError("[x-skl] red-black tree violation")
    77  	errXSklRbtreeBlackViolation = sklError("[x-skl] red-black tree violation")
    78  	errSklOptionWrongTypeApply  = sklError("[skl-option] init with wrong type")
    79  	errSklOptionHasBeenEnabled  = sklError("[skl-option] it has been enabled or set already")
    80  	errSklOptionEmptySettingVal = sklError("[skl-option] empty setting value")
    81  )
    82  
    83  type SklType uint8
    84  
    85  const (
    86  	// XComSkl is the classic skip list.
    87  	// It does not support duplicate keys and values.
    88  	// It is not thread-safe.
    89  	XComSkl SklType = iota
    90  	// XConcSkl is the concurrent skip list.
    91  	// It supports duplicate keys and values.
    92  	XConcSkl
    93  )
    94  
    95  type sklOptions[K infra.OrderedKey, V any] struct {
    96  	valComparator            SklValComparator[V]
    97  	randLevelGen             SklRand
    98  	comRWMutex               *sync.RWMutex
    99  	concOptimisticLockVerGen id.UUIDGen
   100  	concDataNodeMode         *xNodeMode
   101  	sklType                  SklType
   102  	isConcRbtreeBorrowSucc   bool
   103  	keyCmpDesc               bool
   104  }
   105  
   106  type SklOption[K infra.OrderedKey, V any] func(*sklOptions[K, V]) error
   107  
   108  func WithSklKeyCmpDesc[K infra.OrderedKey, V any]() SklOption[K, V] {
   109  	return func(opts *sklOptions[K, V]) error {
   110  		opts.keyCmpDesc = true
   111  		return nil
   112  	}
   113  }
   114  
   115  func WithSklRandLevelGen[K infra.OrderedKey, V any](gen SklRand) SklOption[K, V] {
   116  	return func(opts *sklOptions[K, V]) error {
   117  		if opts.randLevelGen != nil {
   118  			return fmt.Errorf("[x-skl] random level generator %w", errSklOptionHasBeenEnabled)
   119  		} else if gen == nil {
   120  			return fmt.Errorf("[x-skl] random level generator %w", errSklOptionEmptySettingVal)
   121  		}
   122  		opts.randLevelGen = gen
   123  		return nil
   124  	}
   125  }
   126  
   127  func WithXComSklEnableConc[K infra.OrderedKey, V any]() SklOption[K, V] {
   128  	return func(opts *sklOptions[K, V]) error {
   129  		if opts.sklType != XComSkl {
   130  			return fmt.Errorf("[x-com-skl] %w", errSklOptionWrongTypeApply)
   131  		} else if opts.comRWMutex != nil {
   132  			return fmt.Errorf("[x-com-skl] concurrent read-write %w", errSklOptionHasBeenEnabled)
   133  		}
   134  		opts.comRWMutex = &sync.RWMutex{}
   135  		return nil
   136  	}
   137  }
   138  
   139  func WithXComSklValComparator[K infra.OrderedKey, V any](cmp SklValComparator[V]) SklOption[K, V] {
   140  	return func(opts *sklOptions[K, V]) error {
   141  		if opts.sklType != XComSkl {
   142  			return fmt.Errorf("[x-com-skl] %w", errSklOptionWrongTypeApply)
   143  		} else if opts.valComparator != nil {
   144  			return fmt.Errorf("[x-com-skl] value comparator %w", errSklOptionHasBeenEnabled)
   145  		} else if cmp == nil {
   146  			return fmt.Errorf("[x-com-skl] value comparator %w", errSklOptionEmptySettingVal)
   147  		}
   148  		opts.valComparator = cmp
   149  		return nil
   150  	}
   151  }
   152  
   153  func WithXConcSklOptimisticVersionGen[K infra.OrderedKey, V any](verGen id.UUIDGen) SklOption[K, V] {
   154  	return func(opts *sklOptions[K, V]) error {
   155  		if opts.sklType != XConcSkl {
   156  			return fmt.Errorf("[x-conc-skl] %w", errSklOptionWrongTypeApply)
   157  		} else if opts.concOptimisticLockVerGen != nil {
   158  			return fmt.Errorf("[x-conc-skl] optimistic lock version generator %w", errSklOptionHasBeenEnabled)
   159  		} else if verGen == nil {
   160  			return fmt.Errorf("[x-conc-skl] optimistic lock version generator %w", errSklOptionEmptySettingVal)
   161  		}
   162  		opts.concOptimisticLockVerGen = verGen
   163  		return nil
   164  	}
   165  }
   166  
   167  func WithXConcSklDataNodeUniqueMode[K infra.OrderedKey, V any]() SklOption[K, V] {
   168  	return func(opts *sklOptions[K, V]) error {
   169  		if opts.sklType != XConcSkl {
   170  			return fmt.Errorf("[x-conc-skl] %w", errSklOptionWrongTypeApply)
   171  		} else if opts.concDataNodeMode != nil && *opts.concDataNodeMode != unique {
   172  			return fmt.Errorf("[x-conc-skl] unique data node mode set failed, previous mode: %s, %w", *opts.concDataNodeMode, errSklOptionHasBeenEnabled)
   173  		} else if opts.valComparator != nil {
   174  			return fmt.Errorf("[x-conc-skl] unique data node mode not support value comparator %w", errSklOptionHasBeenEnabled)
   175  		}
   176  
   177  		mode := unique
   178  		opts.concDataNodeMode = &mode
   179  		return nil
   180  	}
   181  }
   182  
   183  func WithXConcSklDataNodeLinkedListMode[K infra.OrderedKey, V any](cmp SklValComparator[V]) SklOption[K, V] {
   184  	return func(opts *sklOptions[K, V]) error {
   185  		if opts.sklType != XConcSkl {
   186  			return fmt.Errorf("[x-conc-skl] %w", errSklOptionWrongTypeApply)
   187  		} else if opts.concDataNodeMode != nil {
   188  			return fmt.Errorf("[x-conc-skl] linked list data node mode set failed, previous mode: %s, %w", *opts.concDataNodeMode, errSklOptionHasBeenEnabled)
   189  		} else if opts.valComparator != nil {
   190  			return fmt.Errorf("[x-conc-skl] val comparator %w", errSklOptionHasBeenEnabled)
   191  		} else if cmp == nil {
   192  			return fmt.Errorf("[x-conc-skl] val comparator%w", errSklOptionEmptySettingVal)
   193  		}
   194  
   195  		mode := linkedList
   196  		opts.concDataNodeMode = &mode
   197  		opts.valComparator = cmp
   198  		return nil
   199  	}
   200  }
   201  
   202  func WithXConcSklDataNodeRbtreeMode[K infra.OrderedKey, V any](cmp SklValComparator[V], borrowSucc ...bool) SklOption[K, V] {
   203  	return func(opts *sklOptions[K, V]) error {
   204  		if opts.sklType != XConcSkl {
   205  			return fmt.Errorf("[x-conc-skl] %w", errSklOptionWrongTypeApply)
   206  		} else if opts.concDataNodeMode != nil {
   207  			return fmt.Errorf("[x-conc-skl] rbtree data node mode set failed, previous mode: %s, %w", *opts.concDataNodeMode, errSklOptionHasBeenEnabled)
   208  		} else if opts.valComparator != nil {
   209  			return fmt.Errorf("[x-conc-skl] value comparator %w", errSklOptionHasBeenEnabled)
   210  		} else if cmp == nil {
   211  			return fmt.Errorf("[x-conc-skl] value comparator %w", errSklOptionEmptySettingVal)
   212  		}
   213  
   214  		opts.isConcRbtreeBorrowSucc = len(borrowSucc) > 0 && borrowSucc[0]
   215  		mode := rbtree
   216  		opts.concDataNodeMode = &mode
   217  		opts.valComparator = cmp
   218  		return nil
   219  	}
   220  }
   221  
   222  var _ SkipList[uint8, struct{}] = (*sklDelegator[uint8, struct{}])(nil)
   223  
   224  // sklDelegator is the skip list delegator.
   225  // It does not support duplicate keys and values.
   226  // Concurrent read-write mode is supported if enabled.
   227  type sklDelegator[K infra.OrderedKey, V any] struct {
   228  	rwmu *sync.RWMutex
   229  	impl SkipList[K, V]
   230  }
   231  
   232  func (skl *sklDelegator[K, V]) Len() int64         { return skl.impl.Len() }
   233  func (skl *sklDelegator[K, V]) Levels() int32      { return skl.impl.Levels() }
   234  func (skl *sklDelegator[K, V]) IndexCount() uint64 { return skl.impl.IndexCount() }
   235  func (skl *sklDelegator[K, V]) Insert(key K, val V, ifNotPresent ...bool) error {
   236  	if skl.rwmu != nil {
   237  		skl.rwmu.Lock()
   238  		defer skl.rwmu.Unlock()
   239  	}
   240  	return skl.impl.Insert(key, val, ifNotPresent...)
   241  }
   242  
   243  func (skl *sklDelegator[K, V]) Foreach(action func(int64, SklIterationItem[K, V]) bool) {
   244  	if skl.rwmu != nil {
   245  		skl.rwmu.RLock()
   246  		defer skl.rwmu.RUnlock()
   247  	}
   248  	skl.impl.Foreach(action)
   249  }
   250  
   251  func (skl *sklDelegator[K, V]) LoadFirst(key K) (SklElement[K, V], error) {
   252  	if skl.rwmu != nil {
   253  		skl.rwmu.RLock()
   254  		defer skl.rwmu.RUnlock()
   255  	}
   256  	return skl.impl.LoadFirst(key)
   257  }
   258  func (skl *sklDelegator[K, V]) PeekHead() SklElement[K, V] { return skl.impl.PeekHead() }
   259  func (skl *sklDelegator[K, V]) PopHead() (SklElement[K, V], error) {
   260  	if skl.rwmu != nil {
   261  		skl.rwmu.Lock()
   262  		defer skl.rwmu.Unlock()
   263  	}
   264  	return skl.impl.PopHead()
   265  }
   266  
   267  func (skl *sklDelegator[K, V]) RemoveFirst(key K) (SklElement[K, V], error) {
   268  	if skl.rwmu != nil {
   269  		skl.rwmu.Lock()
   270  		defer skl.rwmu.Unlock()
   271  	}
   272  	return skl.impl.RemoveFirst(key)
   273  }
   274  
   275  func NewSkl[K infra.OrderedKey, V any](typ SklType, opts ...SklOption[K, V]) (SkipList[K, V], error) {
   276  	sklOpts := &sklOptions[K, V]{
   277  		sklType: typ,
   278  	}
   279  
   280  	var err error
   281  	for _, o := range opts {
   282  		err = multierr.Append(err, o(sklOpts))
   283  	}
   284  	if err != nil {
   285  		return nil, err
   286  	}
   287  
   288  	if sklOpts.randLevelGen == nil {
   289  		sklOpts.randLevelGen = randomLevelV2
   290  	}
   291  
   292  	switch typ {
   293  	case XComSkl:
   294  		if sklOpts.valComparator != nil {
   295  			return nil, errors.New("[x-com-skl] init the unique data node mode but value comparator is set")
   296  		}
   297  	case XConcSkl:
   298  		if sklOpts.concDataNodeMode == nil {
   299  			mode := unique
   300  			sklOpts.concDataNodeMode = &mode
   301  		}
   302  		if *sklOpts.concDataNodeMode != unique {
   303  			return nil, fmt.Errorf("[x-conc-skl] init with the wrong mode: %s", *sklOpts.concDataNodeMode)
   304  		}
   305  		if sklOpts.valComparator != nil {
   306  			return nil, errors.New("[x-conc-skl] init the unique data node mode but value comparator is set")
   307  		}
   308  		if sklOpts.concOptimisticLockVerGen == nil {
   309  			gen, _ := id.MonotonicNonZeroID() // fallback to monotonic non-zero id
   310  			sklOpts.concOptimisticLockVerGen = gen
   311  		}
   312  		if sklOpts.concDataNodeMode == nil {
   313  			mode := unique // fallback to unique
   314  			sklOpts.concDataNodeMode = &mode
   315  		}
   316  	default:
   317  		return nil, ErrXSklUnknownType
   318  	}
   319  
   320  	impl, err := sklFactory(sklOpts)
   321  	if err != nil {
   322  		return nil, err
   323  	}
   324  	d := &sklDelegator[K, V]{
   325  		impl: impl,
   326  	}
   327  	if typ == XComSkl && sklOpts.comRWMutex != nil {
   328  		d.rwmu = sklOpts.comRWMutex
   329  	}
   330  	return d, nil
   331  }
   332  
   333  var _ XSkipList[uint8, struct{}] = (*xSklDelegator[uint8, struct{}])(nil)
   334  
   335  // xSklDelegator is the skip list delegator.
   336  // It supports duplicate keys and values.
   337  // Concurrent read-write mode is supported if enabled.
   338  type xSklDelegator[K infra.OrderedKey, V any] struct {
   339  	rwmu *sync.RWMutex
   340  	impl XSkipList[K, V]
   341  }
   342  
   343  func (skl *xSklDelegator[K, V]) Len() int64         { return skl.impl.Len() }
   344  func (skl *xSklDelegator[K, V]) Levels() int32      { return skl.impl.Levels() }
   345  func (skl *xSklDelegator[K, V]) IndexCount() uint64 { return skl.impl.IndexCount() }
   346  func (skl *xSklDelegator[K, V]) Insert(key K, val V, ifNotPresent ...bool) error {
   347  	if skl.rwmu != nil {
   348  		skl.rwmu.Lock()
   349  		defer skl.rwmu.Unlock()
   350  	}
   351  	return skl.impl.Insert(key, val, ifNotPresent...)
   352  }
   353  
   354  func (skl *xSklDelegator[K, V]) Foreach(action func(int64, SklIterationItem[K, V]) bool) {
   355  	if skl.rwmu != nil {
   356  		skl.rwmu.RLock()
   357  		defer skl.rwmu.RUnlock()
   358  	}
   359  	skl.impl.Foreach(action)
   360  }
   361  
   362  func (skl *xSklDelegator[K, V]) LoadFirst(key K) (SklElement[K, V], error) {
   363  	if skl.rwmu != nil {
   364  		skl.rwmu.RLock()
   365  		defer skl.rwmu.RUnlock()
   366  	}
   367  	return skl.impl.LoadFirst(key)
   368  }
   369  func (skl *xSklDelegator[K, V]) PeekHead() SklElement[K, V] { return skl.impl.PeekHead() }
   370  func (skl *xSklDelegator[K, V]) PopHead() (SklElement[K, V], error) {
   371  	if skl.rwmu != nil {
   372  		skl.rwmu.Lock()
   373  		defer skl.rwmu.Unlock()
   374  	}
   375  	return skl.impl.PopHead()
   376  }
   377  
   378  func (skl *xSklDelegator[K, V]) RemoveFirst(key K) (SklElement[K, V], error) {
   379  	if skl.rwmu != nil {
   380  		skl.rwmu.Lock()
   381  		defer skl.rwmu.Unlock()
   382  	}
   383  	return skl.impl.RemoveFirst(key)
   384  }
   385  
   386  func (skl *xSklDelegator[K, V]) LoadAll(key K) ([]SklElement[K, V], error) {
   387  	if skl.rwmu != nil {
   388  		skl.rwmu.RLock()
   389  		defer skl.rwmu.RUnlock()
   390  	}
   391  	return skl.impl.LoadAll(key)
   392  }
   393  
   394  func (skl *xSklDelegator[K, V]) LoadIfMatch(key K, matcher func(V) bool) ([]SklElement[K, V], error) {
   395  	if skl.rwmu != nil {
   396  		skl.rwmu.RLock()
   397  		defer skl.rwmu.RUnlock()
   398  	}
   399  	return skl.impl.LoadIfMatch(key, matcher)
   400  }
   401  
   402  func (skl *xSklDelegator[K, V]) RemoveAll(key K) ([]SklElement[K, V], error) {
   403  	if skl.rwmu != nil {
   404  		skl.rwmu.Lock()
   405  		defer skl.rwmu.Unlock()
   406  	}
   407  	return skl.impl.RemoveAll(key)
   408  }
   409  
   410  func (skl *xSklDelegator[K, V]) RemoveIfMatch(key K, matcher func(V) bool) ([]SklElement[K, V], error) {
   411  	if skl.rwmu != nil {
   412  		skl.rwmu.Lock()
   413  		defer skl.rwmu.Unlock()
   414  	}
   415  	return skl.impl.RemoveIfMatch(key, matcher)
   416  }
   417  
   418  func NewXSkl[K infra.OrderedKey, V any](typ SklType, opts ...SklOption[K, V]) (XSkipList[K, V], error) {
   419  	sklOpts := &sklOptions[K, V]{
   420  		sklType: typ,
   421  	}
   422  	var err error
   423  	for _, o := range opts {
   424  		err = multierr.Append(err, o(sklOpts))
   425  	}
   426  	if err != nil {
   427  		return nil, err
   428  	}
   429  
   430  	if sklOpts.randLevelGen == nil {
   431  		sklOpts.randLevelGen = randomLevelV2
   432  	}
   433  
   434  	switch typ {
   435  	case XComSkl:
   436  		if sklOpts.valComparator == nil {
   437  			return nil, errors.New("[x-skl] x-com-skl non-unique mode, the value comparator must be set")
   438  		}
   439  	case XConcSkl:
   440  		if sklOpts.concDataNodeMode == nil {
   441  			mode := rbtree // fallback to rbtree mode
   442  			sklOpts.concDataNodeMode = &mode
   443  		}
   444  		if sklOpts.concDataNodeMode != nil && *sklOpts.concDataNodeMode == unique {
   445  			return nil, fmt.Errorf("[x-skl] x-conc-skl init with the wrong mode: %s", unique)
   446  		}
   447  		if sklOpts.valComparator == nil {
   448  			return nil, errors.New("[x-skl] x-conc-skl non-unique data node mode, the value comparator must be set")
   449  		}
   450  		if sklOpts.concOptimisticLockVerGen == nil {
   451  			gen, _ := id.MonotonicNonZeroID() // fallback to monotonic non-zero id
   452  			sklOpts.concOptimisticLockVerGen = gen
   453  		}
   454  	default:
   455  		return nil, ErrXSklUnknownType
   456  	}
   457  
   458  	impl, err := sklFactory(sklOpts)
   459  	if err != nil {
   460  		return nil, err
   461  	}
   462  	d := &xSklDelegator[K, V]{
   463  		impl: impl,
   464  	}
   465  	if typ == XComSkl && sklOpts.comRWMutex != nil {
   466  		d.rwmu = sklOpts.comRWMutex
   467  	}
   468  	return d, nil
   469  }
   470  
   471  func sklFactory[K infra.OrderedKey, V any](opts *sklOptions[K, V]) (XSkipList[K, V], error) {
   472  	var impl XSkipList[K, V]
   473  	switch opts.sklType {
   474  	case XComSkl:
   475  		skl := &xComSkl[K, V]{
   476  			// Start from 1 means the x-com-skl cache levels at least a one level is fixed
   477  			levels:       1,
   478  			nodeLen:      0,
   479  			vcmp:         opts.valComparator,
   480  			rand:         opts.randLevelGen,
   481  			isKeyCmpDesc: opts.keyCmpDesc,
   482  		}
   483  		skl.head = genXComSklNode[K, V](*new(K), *new(V), sklMaxLevel)
   484  		skl.head.setBackward(nil)
   485  		skl.tail = nil
   486  		impl = skl
   487  	case XConcSkl:
   488  		skl := &xConcSkl[K, V]{
   489  			// Start from 1 means the x-conc-skl cache levels at least a one level is fixed
   490  			levels:  1,
   491  			nodeLen: 0,
   492  			head:    newXConcSklHead[K, V](),
   493  			vcmp:    opts.valComparator,
   494  			optVer:  opts.concOptimisticLockVerGen,
   495  			rand:    opts.randLevelGen,
   496  			flags:   0,
   497  		}
   498  		if opts.keyCmpDesc {
   499  			skl.flags = set(skl.flags, xConcSklKeyCmpFlagBit)
   500  		}
   501  		skl.flags = setBitsAs(skl.flags, xConcSklXNodeModeFlagBits, uint32(*opts.concDataNodeMode))
   502  		if *opts.concDataNodeMode == rbtree && opts.isConcRbtreeBorrowSucc {
   503  			skl.flags = set(skl.flags, xConcSklRbtreeRmBorrowFlagBit)
   504  		}
   505  		impl = skl
   506  	default:
   507  		return nil, errors.New("[x-skl] unknown skip list type")
   508  	}
   509  	return impl, nil
   510  }