policylru

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 24, 2022 License: Apache-2.0 Imports: 1 Imported by: 1

README

policy-lru

A simple LRU cache in GoLang with custom evicton policies and Go generics support.

Use It If You Want

  1. A lightweight least recently used ("LRU") cache with no external dependencies.
  2. Go 1.18 generics.
  3. To define your own eviction policy, for example only evict from the cache when consumed memory or disk space exceeds some threshold.

Examples

Below is an example of the most basic LRU cache with a simple eviction policy based on a maximum number of keys. More examples are available in the API reference documentation.

package main

import (
	"fmt"
	"github.com/gogama/policy-lru"
)

func main() {
	lru := policylru.New[string, string](policylru.MaxCount[string, string](10))
	lru.Add("foo", "bar")
	value, ok := lru.Get("foo")
	fmt.Printf("In cache? %t. Value: %q.\n", ok, value)
}

Status

Go Report Card PkgGoDev

License

This project is licensed under the terms of the Apache License 2.0.

Acknowledgements

The code for this project is heavily based on the code from package lru from github.com/golang/groupcache. The borrowed code is licensed under the Apache License 2.0

Developer happiness on this project was boosted by JetBrains' generous donation of an open source license for their lovely GoLand IDE. ❤

Documentation

Overview

Package policylru provides a generic LRU cache that lets you decide your own eviction policy.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AddedFunc

type AddedFunc[Key, Value any] func(k Key, old, new Value, updated bool)

The AddedFunc type is an adapter that allows you to use a single ordinary add-handling function as a Handler without implementing the whole Handler interface.

If f is a function whose signature matches the Added method of a Handler[k, v], then AddedFunc[k, v](f) is a Handler[k, v] with a no-op Removed method and an Added method that calls f.

func (AddedFunc[Key, Value]) Added

func (f AddedFunc[Key, Value]) Added(k Key, old, new Value, updated bool)

func (AddedFunc[Key, Value]) Removed

func (f AddedFunc[Key, Value]) Removed(k Key, v Value)

type Cache

type Cache[Key comparable, Value any] struct {
	// Policy is the cache eviction policy. If Policy is nil, no element
	// will ever be evicted from the cache.
	Policy Policy[Key, Value]
	// Handler is the optional cache eviction handler.
	Handler Handler[Key, Value]
	// contains filtered or unexported fields
}

Cache is a Policy-driven LRU cache. It is not safe for concurrent access.

Example (WithMaxCount)

This example illustrates the most basic LRU cache where the eviction policy is based on limiting the number of keys in the cache.

package main

import (
	"fmt"

	policylru "github.com/gogama/policy-lru"
)

func main() {
	lru := policylru.New[string, string](policylru.MaxCount[string, string](10))
	lru.Add("foo", "bar")
	value, ok := lru.Get("foo")
	fmt.Printf("In cache? %t. Value: %q.\n", ok, value)
}
Output:

In cache? true. Value: "bar".
Example (WithMaxSizePolicy)

This example illustrates a more complex LRU cache where the eviction policy is based on the total aggregate size of the values in the cache.

package main

import (
	"fmt"

	policylru "github.com/gogama/policy-lru"
)

const maxSize = 100

type myValue struct {
	valueSize uint64
}

type myPolicy struct {
	totalSize uint64
}

func (p *myPolicy) Evict(_ string, _ myValue, _ int) bool {
	return p.totalSize > maxSize
}

func (p *myPolicy) Added(_ string, old, new myValue, _ bool) {
	p.totalSize -= old.valueSize
	p.totalSize += new.valueSize
}

func (p *myPolicy) Removed(k string, v myValue) {
	p.totalSize -= v.valueSize
	fmt.Printf("Removed %q with size %d, total size is now %d.\n", k, v.valueSize, p.totalSize)
}

func main() {
	policy := &myPolicy{}
	lru := policylru.NewWithHandler[string, myValue](policy, policy)
	lru.Add("foo", myValue{10})
	lru.Add("bar", myValue{90})
	lru.Add("baz", myValue{1})
	lru.Add("qux", myValue{9})
}
Output:

Removed "foo" with size 10, total size is now 91.

func New

func New[Key comparable, Value any](policy Policy[Key, Value]) *Cache[Key, Value]

New creates a new policy-driven Cache.

If policy is nil, the cache has no limit, and it is assumed that eviction is handled by the caller.

func NewWithHandler

func NewWithHandler[Key comparable, Value any](policy Policy[Key, Value], handler Handler[Key, Value]) *Cache[Key, Value]

NewWithHandler creates a new policy-driven Cache with a removal event handler.

If policy is nil, the cache has no limit, and it is assumed that eviction is handled by the caller. If handler is nil, removal events will not be generated.

func (*Cache[Key, Value]) Add

func (c *Cache[Key, Value]) Add(k Key, v Value)

Add adds a value to the cache.

func (*Cache[Key, Value]) Clear

func (c *Cache[Key, Value]) Clear()

Clear purges all stored items from the cache.

func (*Cache[Key, Value]) Evict

func (c *Cache[Key, Value]) Evict() (n int)

Evict continuously removes the oldest item from cache as long as the eviction policy returns true for that item. This process ends when the policy returns false for the oldest item or the cache is empty.

The value returned is the number of items removed.

func (*Cache[Key, Value]) Get

func (c *Cache[Key, Value]) Get(k Key) (v Value, hit bool)

Get looks up a key's value from the cache.

func (*Cache[Key, Value]) Len

func (c *Cache[Key, Value]) Len() int

Len returns the number of items in the cache.

func (*Cache[Key, Value]) Remove

func (c *Cache[Key, Value]) Remove(k Key) (removed bool)

Remove removes the provided key from the cache.

type Handler

type Handler[Key, Value any] interface {
	// Added is called after an element is added to the cache.
	Added(k Key, old, new Value, update bool)
	// Removed is called after an element is removed from the cache.
	//
	// Removal can happen either by operation of the eviction policy or
	// by a direct call to the Cache's Remove method.
	Removed(k Key, v Value)
}

Handler can optionally be used to handle cache removal events.

type Policy

type Policy[Key, Value any] interface {
	// Evict decides whether a given cache entry should be evicted
	// from the cache based on the entry's key and value, and the
	// current number of items in the cache.
	//
	// Immediately after Evict returns true, the specified cache entry
	// will be deleted from the Cache which called Evict.
	Evict(k Key, v Value, n int) bool
}

Policy represents a cache eviction policy.

func MaxCount

func MaxCount[Key, Value any](n int) Policy[Key, Value]

MaxCount returns a Policy that evicts the oldest key from the Cache whenever the total number of keys in the cash exceeds the given maximum count.

type PolicyFunc

type PolicyFunc[Key, Value any] func(k Key, v Value, n int) bool

The PolicyFunc type is an adapter that allows you to use an ordinary function as a Policy without implementing the Policy interface.

If f is a function a signature matching that of PolicyFunc, then PolicyFunc[k, v](f) is a Policy that calls f.

func (PolicyFunc[Key, Value]) Evict

func (f PolicyFunc[Key, Value]) Evict(k Key, v Value, n int) bool

type RemovedFunc

type RemovedFunc[Key, Value any] func(k Key, v Value)

The RemovedFunc type is an adapter that allows you to use a single ordinary remove-handling function as a Handler without implementing the whole Handler interface.

If f is a function whose signature matches the Removed method of a Handler[k, v], then RemovedFunc[k, v](f) is a Handler[k, v] with a no-op Added method and a Removed method that calls f.

func (RemovedFunc[Key, Value]) Added

func (f RemovedFunc[Key, Value]) Added(_ Key, _, _ Value, _ bool)

func (RemovedFunc[Key, Value]) Removed

func (f RemovedFunc[Key, Value]) Removed(k Key, v Value)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL