Skip to content

Commit

Permalink
Restrict generic key type to only those supported (#371)
Browse files Browse the repository at this point in the history
Without this, you can specify key types that aren't supported and then
have to deal with panics, rather than more pleasant compile-time
warnings.
  • Loading branch information
pete-woods authored Jan 16, 2024
1 parent e7380b4 commit dae2557
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 7 deletions.
8 changes: 5 additions & 3 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ func zeroValue[T any]() T {
return zero
}

type Key = z.Key

// Cache is a thread-safe implementation of a hashmap with a TinyLFU admission
// policy and a Sampled LFU eviction policy. You can use the same Cache instance
// from as many goroutines as you want.
type Cache[K any, V any] struct {
type Cache[K Key, V any] struct {
// storedItems is the central concurrent hashmap where key-value items are stored.
storedItems store[V]
// cachePolicy determines what gets let in to the cache and what gets kicked out.
Expand Down Expand Up @@ -84,7 +86,7 @@ type Cache[K any, V any] struct {
}

// Config is passed to NewCache for creating new Cache instances.
type Config[K any, V any] struct {
type Config[K Key, V any] struct {
// NumCounters determines the number of counters (keys) to keep that hold
// access frequency information. It's generally a good idea to have more
// counters than the max cache capacity, as this will improve eviction
Expand Down Expand Up @@ -162,7 +164,7 @@ type Item[V any] struct {
}

// NewCache returns a new Cache instance and any configuration errors, if any.
func NewCache[K any, V any](config *Config[K, V]) (*Cache[K, V], error) {
func NewCache[K Key, V any](config *Config[K, V]) (*Cache[K, V], error) {
switch {
case config.NumCounters == 0:
return nil, errors.New("NumCounters can't be zero")
Expand Down
9 changes: 5 additions & 4 deletions z/z.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,19 @@ import (
"github.com/cespare/xxhash/v2"
)

type Key interface {
uint64 | string | []byte | byte | int | int32 | uint32 | int64
}

// TODO: Figure out a way to re-use memhash for the second uint64 hash,
// we already know that appending bytes isn't reliable for generating a
// second hash (see Ristretto PR #88).
// We also know that while the Go runtime has a runtime memhash128
// function, it's not possible to use it to generate [2]uint64 or
// anything resembling a 128bit hash, even though that's exactly what
// we need in this situation.
func KeyToHash[K any](key K) (uint64, uint64) {
func KeyToHash[K Key](key K) (uint64, uint64) {
keyAsAny := any(key)
if keyAsAny == nil {
return 0, 0
}
switch k := keyAsAny.(type) {
case uint64:
return k, 0
Expand Down

0 comments on commit dae2557

Please sign in to comment.