cac
github.com/chai2010/cache
go get github.com/chai2010/cache
cac

github.com/chai2010/cache

LevelDB style LRU cache for Go, support non GC object.

by chai2010

v1.0.0 (see all)
go get github.com/chai2010/cache
Readme

LRU Cache

Build Status GoDoc

Install

  1. go get github.com/chai2010/cache
  2. go run hello.go

Example

Simple GC Object

This is a simple example:

package main

import (
    "fmt"

    "github.com/chai2010/cache"
)

func main() {
    c := cache.NewLRUCache(100)
    defer c.Close()

    c.Set("key1", "value1", 1)
    value1 := c.Value("key1").(string)
    fmt.Println("key1:", value1)

    c.Set("key2", "value2", 1)
    value2 := c.Value("key2", "null").(string)
    fmt.Println("key2:", value2)

    value3 := c.Value("key3", "null").(string)
    fmt.Println("key3:", value3)

    value4 := c.Value("key4") // value4 is nil
    fmt.Println("key4:", value4)

    fmt.Println("Done")
}

Output:

key1: value1
key2: value2
key3: null
key4: <nil>
Done

Non GC Object

Support non GC object, such as os.File or some cgo memory.

package main

import (
    "fmt"

    "github.com/chai2010/cache"
)

func main() {
    c := cache.NewLRUCache(10)
    defer c.Close()

    id0 := c.NewId()
    id1 := c.NewId()
    id2 := c.NewId()
    fmt.Println("id0:", id0)
    fmt.Println("id1:", id1)
    fmt.Println("id2:", id2)

    // add new
    v1 := "data:123"
    h1 := c.Insert("123", "data:123", len("data:123"), func(key string, value interface{}) {
        fmt.Printf("deleter(%q:%q)\n", key, value)
    })

    // fetch ok
    v2, h2, ok := c.Lookup("123")
    assert(ok)
    assert(h2 != nil)

    // remove
    c.Erase("123")

    // fetch failed
    _, h3, ok := c.Lookup("123")
    assert(!ok)
    assert(h3 == nil)

    // h1&h2 still valid!
    fmt.Printf("user1(%s)\n", v1)
    fmt.Printf("user2(%s)\n", v2.(string))

    // release h1
    // because the h2 handle the value, so the deleter is not ivoked!
    h1.Close()

    // invoke the deleter
    fmt.Println("invoke deleter(123) begin")
    h2.Close()
    fmt.Println("invoke deleter(123) end")

    // add new
    h4 := c.Insert("abc", "data:abc", len("data:abc"), func(key string, value interface{}) {
        fmt.Printf("deleter(%q:%q)\n", key, value)
    })
    // release h4
    // because the cache handle the value, so the deleter is not ivoked!
    h4.Close()

    // cache length
    length := c.Length()
    assert(length == 1)

    // cache size
    size := c.Size()
    assert(size == 8, "size:", size)

    // add h5
    // this will cause the capacity(10) overflow, so the h4 deleter will be invoked
    fmt.Println("invoke deleter(h4) begin")
    h5 := c.Insert("456", "data:456", len("data:456"), func(key string, value interface{}) {
        fmt.Printf("deleter(%q:%q)\n", key, value)
    })
    fmt.Println("invoke deleter(h4) end")

    // must release all handles
    h5.Close()

    // stats
    fmt.Println("StatsJSON:", c.StatsJSON())

    // done
    fmt.Println("Done")
}

func assert(v bool, a ...interface{}) {
    if !v {
        panic(fmt.Sprint(a...))
    }
}

Output:

id0: 1
id1: 2
id2: 3
user1(data:123)
user2(data:123)
invoke deleter(123) begin
deleter("123":"data:123")
invoke deleter(123) end
invoke deleter(h4) begin
deleter("abc":"data:abc")
invoke deleter(h4) end
StatsJSON: {
        "Length": 1,
        "Size": 8,
        "Capacity": 10,
        "OldestAccess": "2015-08-21 18:00:24.0119469 +0800 CST"
}
Done
deleter("456":"data:456")

BUGS

Report bugs to chaishushan@gmail.com.

Thanks!

GitHub Stars

11

LAST COMMIT

2yrs ago

MAINTAINERS

0

CONTRIBUTORS

1

OPEN ISSUES

0

OPEN PRs

0
VersionTagPublished
v1.0.1-0.20200705094526-abdf8bc5de98
1yr ago
v1.0.0
2yrs ago
No alternatives found
No tutorials found
Add a tutorial