github.com/duomi520/utils@v0.0.0-20240430123446-e03a4cddd6ec/cache.go (about)

     1  package utils
     2  
     3  import (
     4  	"sync/atomic"
     5  )
     6  
     7  type Cell struct {
     8  	wyhash uint64
     9  	fnv1a  uint64
    10  	out    any
    11  }
    12  
    13  // IdempotentCache 幂等函数缓存,幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数
    14  type IdempotentCache[T string | []byte] struct {
    15  	//缓存的大小,使用2的power次方作为大小。
    16  	power uint64
    17  	size  uint64
    18  	//用于hash的种子
    19  	seed uint64
    20  	buf  []atomic.Value
    21  	do   func(T) any
    22  }
    23  
    24  // Init 初始化 power表示缓存大小的指数,seed表示hash的种子,do表示要缓存的幂等函数
    25  func (ic *IdempotentCache[T]) Init(power, seed uint64, do func(T) any) {
    26  	ic.power = power
    27  	ic.size = 2 ^ power
    28  	ic.seed = seed
    29  	ic.buf = make([]atomic.Value, 2^power)
    30  	ic.do = do
    31  }
    32  
    33  // Get 用于获取缓存中的结果
    34  func (ic *IdempotentCache[T]) Get(in T) any {
    35  	h := Hash64WY(in, ic.seed)
    36  	f := Hash64FNV1A(in)
    37  	//取余
    38  	index := h & (ic.size - 1)
    39  	v := ic.buf[index].Load()
    40  	if v != nil {
    41  		cell := v.(Cell)
    42  		if cell.wyhash == h && cell.fnv1a == f {
    43  			return cell.out
    44  		}
    45  	}
    46  	c := Cell{wyhash: h, fnv1a: f, out: ic.do(in)}
    47  	ic.buf[index].Store(c)
    48  	return c.out
    49  }
    50  
    51  // https://github.com/cespare/xxhash