123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- package cache
- import (
- "container/list"
- "sync"
- "sync/atomic"
- )
- // An AtomicInt is an int64 to be accessed atomically.
- type AtomicInt int64
- // MemCache is an LRU cache. It is safe for concurrent access.
- type MemCache struct {
- hits, gets AtomicInt
- mutex sync.RWMutex
- maxItemSize int
- cacheList *list.List
- cache map[interface{}]*list.Element
- }
- type entry struct {
- key interface{}
- value interface{}
- }
- // NewMemCache If maxItemSize is zero, the cache has no limit.
- //if maxItemSize is not zero, when cache's size beyond maxItemSize,start to swap
- func NewMemCache(maxItemSize int) *MemCache {
- return &MemCache{
- maxItemSize: maxItemSize,
- cacheList: list.New(),
- cache: make(map[interface{}]*list.Element),
- }
- }
- // Status return the status of cache
- func (c *MemCache) Status() *CacheStatus {
- c.mutex.RLock()
- defer c.mutex.RUnlock()
- return &CacheStatus{
- MaxItemSize: c.maxItemSize,
- CurrentSize: c.cacheList.Len(),
- Gets: c.gets.Get(),
- Hits: c.hits.Get(),
- }
- }
- //Get value with key
- func (c *MemCache) Get(key string) (interface{}, bool) {
- c.mutex.RLock()
- defer c.mutex.RUnlock()
- c.gets.Add(1)
- if ele, hit := c.cache[key]; hit {
- c.hits.Add(1)
- return ele.Value.(*entry).value, true
- }
- return nil, false
- }
- //Set a value with key
- func (c *MemCache) Set(key string, value interface{}) {
- c.mutex.Lock()
- defer c.mutex.Unlock()
- if c.cache == nil {
- c.cache = make(map[interface{}]*list.Element)
- c.cacheList = list.New()
- }
- if ele, ok := c.cache[key]; ok {
- c.cacheList.MoveToFront(ele)
- ele.Value.(*entry).value = value
- return
- }
- ele := c.cacheList.PushFront(&entry{key: key, value: value})
- c.cache[key] = ele
- if c.maxItemSize != 0 && c.cacheList.Len() > c.maxItemSize {
- c.RemoveOldest()
- }
- }
- // Delete a value with key
- func (c *MemCache) Delete(key string) {
- c.mutex.Lock()
- defer c.mutex.Unlock()
- if c.cache == nil {
- return
- }
- if ele, ok := c.cache[key]; ok {
- c.cacheList.Remove(ele)
- key := ele.Value.(*entry).key
- delete(c.cache, key)
- return
- }
- }
- // RemoveOldest remove oldest key
- func (c *MemCache) RemoveOldest() {
- if c.cache == nil {
- return
- }
- ele := c.cacheList.Back()
- if ele != nil {
- c.cacheList.Remove(ele)
- key := ele.Value.(*entry).key
- delete(c.cache, key)
- }
- }
- // Add atomically adds n to i.
- func (i *AtomicInt) Add(n int64) {
- atomic.AddInt64((*int64)(i), n)
- }
- // Get atomically gets the value of i.
- func (i *AtomicInt) Get() int64 {
- return atomic.LoadInt64((*int64)(i))
- }
|