summaryrefslogtreecommitdiff
path: root/lib/caching/cache.go
blob: 37565f98336aa30e2648bb45b4883aaaae2b0b8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// Copyright (C) 2023  Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later

package caching

import (
	"context"
)

// A Source is something that a Cache sits in front of.
type Source[K comparable, V any] interface {
	// Load updates a 'V' (which is reused accross the lifetime of
	// the cache, and may or may not be zero) to be set to the
	// value for the 'K'.
	Load(context.Context, K, *V)

	// Flush does whatever it needs to to ensure that if the
	// program exited right now, no one would be upset.  Flush
	// being called does not mean that the entry is being evicted
	// from the cache.
	Flush(context.Context, *V)
}

type Cache[K comparable, V any] interface {
	// Aquire loads the value for `k` (possibly from the cache),
	// records that value in to the cache, and increments the
	// cache entry's in-use counter preventing it from being
	// evicted.
	//
	// If the cache is at capacity and all entries are in-use,
	// then Aquire blocks until an entry becomes available (via
	// `Release`).
	Acquire(context.Context, K) *V

	// Release decrements the in-use counter for the cache entry
	// for `k`.  If the in-use counter drops to 0, then that entry
	// may be evicted.
	//
	// It is invalid (runtime-panic) to call Release for an entry
	// that does not have a positive in-use counter.
	Release(K)

	// Delete invalidates/removes an entry from the cache.  Blocks
	// until the in-user counter drops to 0.
	//
	// It is valid to call Delete on an entry that does not exist
	// in the cache.
	Delete(K)

	// Flush does whatever it needs to to ensure that if the
	// program exited right now, no one would be upset.  Flush
	// does not empty the cache.
	Flush(context.Context)
}

// SourceFunc implements Source.  Load calls the function, and Flush
// is a no-op.
type SourceFunc[K comparable, V any] func(context.Context, K, *V)

var _ Source[int, string] = SourceFunc[int, string](nil)

func (fn SourceFunc[K, V]) Load(ctx context.Context, k K, v *V) { fn(ctx, k, v) }
func (fn SourceFunc[K, V]) Flush(context.Context, *V)           {}