github.com/zhongdalu/gf@v1.0.0/g/os/gcache/gcache_mem_cache_lru.go (about) 1 // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 7 package gcache 8 9 import ( 10 "github.com/zhongdalu/gf/g/container/glist" 11 "github.com/zhongdalu/gf/g/container/gmap" 12 "github.com/zhongdalu/gf/g/container/gtype" 13 "github.com/zhongdalu/gf/g/os/gtimer" 14 "time" 15 ) 16 17 // LRU cache object. 18 // It uses list.List from stdlib for its underlying doubly linked list. 19 type memCacheLru struct { 20 cache *memCache // Parent cache object. 21 data *gmap.Map // Key mapping to the item of the list. 22 list *glist.List // Key list. 23 rawList *glist.List // History for key adding. 24 closed *gtype.Bool // Closed or not. 25 } 26 27 // newMemCacheLru creates and returns a new LRU object. 28 func newMemCacheLru(cache *memCache) *memCacheLru { 29 lru := &memCacheLru{ 30 cache: cache, 31 data: gmap.New(), 32 list: glist.New(), 33 rawList: glist.New(), 34 closed: gtype.NewBool(), 35 } 36 gtimer.AddSingleton(time.Second, lru.SyncAndClear) 37 return lru 38 } 39 40 // Close closes the LRU object. 41 func (lru *memCacheLru) Close() { 42 lru.closed.Set(true) 43 } 44 45 // Remove deletes the <key> FROM <lru>. 46 func (lru *memCacheLru) Remove(key interface{}) { 47 if v := lru.data.Get(key); v != nil { 48 lru.data.Remove(key) 49 lru.list.Remove(v.(*glist.Element)) 50 } 51 } 52 53 // Size returns the size of <lru>. 54 func (lru *memCacheLru) Size() int { 55 return lru.data.Size() 56 } 57 58 // Push pushes <key> to the tail of <lru>. 59 func (lru *memCacheLru) Push(key interface{}) { 60 lru.rawList.PushBack(key) 61 } 62 63 // Pop deletes and returns the key from tail of <lru>. 64 func (lru *memCacheLru) Pop() interface{} { 65 if v := lru.list.PopBack(); v != nil { 66 lru.data.Remove(v) 67 return v 68 } 69 return nil 70 } 71 72 // Print is used for test only. 73 //func (lru *memCacheLru) Print() { 74 // for _, v := range lru.list.FrontAll() { 75 // fmt.Printf("%v ", v) 76 // } 77 // fmt.Println() 78 //} 79 80 // SyncAndClear synchronizes the keys from <rawList> to <list> and <data> 81 // using Least Recently Used algorithm. 82 func (lru *memCacheLru) SyncAndClear() { 83 if lru.closed.Val() { 84 gtimer.Exit() 85 return 86 } 87 // Data synchronization. 88 for { 89 if v := lru.rawList.PopFront(); v != nil { 90 // Deleting the key from list. 91 if v := lru.data.Get(v); v != nil { 92 lru.list.Remove(v.(*glist.Element)) 93 } 94 // Pushing key to the head of the list 95 // and setting its list item to hash table for quick indexing. 96 lru.data.Set(v, lru.list.PushFront(v)) 97 } else { 98 break 99 } 100 } 101 // Data cleaning up. 102 for i := lru.Size() - lru.cache.cap; i > 0; i-- { 103 if s := lru.Pop(); s != nil { 104 lru.cache.clearByKey(s, true) 105 } 106 } 107 }