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