github.com/phuslu/lru@v1.0.16-0.20240421170520-46288a2fd47c/options.go (about)

     1  package lru
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"runtime"
     7  	"time"
     8  	"unsafe"
     9  )
    10  
    11  // Option is an interface for LRUCache and TTLCache configuration.
    12  type Option[K comparable, V any] interface {
    13  	applyToLRUCache(*LRUCache[K, V])
    14  	applyToTTLCache(*TTLCache[K, V])
    15  }
    16  
    17  // WithShards specifies the shards count of cache.
    18  func WithShards[K comparable, V any](count uint32) Option[K, V] {
    19  	return &shardsOption[K, V]{count: count}
    20  }
    21  
    22  type shardsOption[K comparable, V any] struct {
    23  	count uint32
    24  }
    25  
    26  func (o *shardsOption[K, V]) getcount(maxcount uint32) uint32 {
    27  	var shardcount uint32
    28  	if o.count == 0 {
    29  		shardcount = nextPowOf2(uint32(runtime.GOMAXPROCS(0) * 16))
    30  	} else {
    31  		shardcount = nextPowOf2(o.count)
    32  	}
    33  	if shardcount > maxcount {
    34  		shardcount = maxcount
    35  	}
    36  	return shardcount
    37  }
    38  
    39  func (o *shardsOption[K, V]) applyToLRUCache(c *LRUCache[K, V]) {
    40  	c.mask = o.getcount(uint32(len(c.shards))) - 1
    41  }
    42  
    43  func (o *shardsOption[K, V]) applyToTTLCache(c *TTLCache[K, V]) {
    44  	c.mask = o.getcount(uint32(len(c.shards))) - 1
    45  }
    46  
    47  // WithHasher specifies the hasher function of cache.
    48  func WithHasher[K comparable, V any](hasher func(key unsafe.Pointer, seed uintptr) (hash uintptr)) Option[K, V] {
    49  	return &hasherOption[K, V]{hasher: hasher}
    50  }
    51  
    52  type hasherOption[K comparable, V any] struct {
    53  	hasher func(key unsafe.Pointer, seed uintptr) (hash uintptr)
    54  }
    55  
    56  func (o *hasherOption[K, V]) applyToLRUCache(c *LRUCache[K, V]) {
    57  	c.hasher = o.hasher
    58  }
    59  
    60  func (o *hasherOption[K, V]) applyToTTLCache(c *TTLCache[K, V]) {
    61  	c.hasher = o.hasher
    62  }
    63  
    64  // WithSliding specifies that use sliding cache or not.
    65  func WithSliding[K comparable, V any](sliding bool) Option[K, V] {
    66  	return &slidingOption[K, V]{sliding: sliding}
    67  }
    68  
    69  type slidingOption[K comparable, V any] struct {
    70  	sliding bool
    71  }
    72  
    73  func (o *slidingOption[K, V]) applyToLRUCache(c *LRUCache[K, V]) {
    74  	panic("not_supported")
    75  }
    76  
    77  func (o *slidingOption[K, V]) applyToTTLCache(c *TTLCache[K, V]) {
    78  	for i := uint32(0); i <= c.mask; i++ {
    79  		c.shards[i].sliding = o.sliding
    80  	}
    81  }
    82  
    83  var ErrLoaderIsNil = errors.New("loader is nil")
    84  
    85  // WithLoader specifies that loader function of LoadingCache.
    86  func WithLoader[K comparable, V any, Loader ~func(ctx context.Context, key K) (value V, err error) | ~func(ctx context.Context, key K) (value V, ttl time.Duration, err error)](loader Loader) Option[K, V] {
    87  	return &loaderOption[K, V]{loader: loader}
    88  }
    89  
    90  type loaderOption[K comparable, V any] struct {
    91  	loader any
    92  }
    93  
    94  func (o *loaderOption[K, V]) applyToLRUCache(c *LRUCache[K, V]) {
    95  	loader, ok := o.loader.(func(ctx context.Context, key K) (value V, err error))
    96  	if !ok {
    97  		panic("not_supported")
    98  	}
    99  	c.loader = loader
   100  	c.group = singleflight_Group[K, V]{}
   101  }
   102  
   103  func (o *loaderOption[K, V]) applyToTTLCache(c *TTLCache[K, V]) {
   104  	loader, ok := o.loader.(func(ctx context.Context, key K) (value V, ttl time.Duration, err error))
   105  	if !ok {
   106  		panic("not_supported")
   107  	}
   108  	c.loader = loader
   109  	c.group = singleflight_Group[K, V]{}
   110  }
   111  
   112  func nextPowOf2(n uint32) uint32 {
   113  	k := uint32(1)
   114  	for k < n {
   115  		k = k * 2
   116  	}
   117  	return k
   118  }
   119  
   120  var isamd64 = runtime.GOARCH == "amd64"