github.com/wangyougui/gf/v2@v2.6.5/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/wangyougui/gf. 6 7 package gcache 8 9 import ( 10 "context" 11 12 "github.com/wangyougui/gf/v2/container/glist" 13 "github.com/wangyougui/gf/v2/container/gmap" 14 "github.com/wangyougui/gf/v2/container/gtype" 15 "github.com/wangyougui/gf/v2/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 return lru 38 } 39 40 // Close closes the LRU object. 41 func (lru *adapterMemoryLru) Close() { 42 lru.closed.Set(true) 43 } 44 45 // Remove deletes the `key` FROM `lru`. 46 func (lru *adapterMemoryLru) 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 *adapterMemoryLru) Size() int { 55 return lru.data.Size() 56 } 57 58 // Push pushes `key` to the tail of `lru`. 59 func (lru *adapterMemoryLru) Push(key interface{}) { 60 lru.rawList.PushBack(key) 61 } 62 63 // Pop deletes and returns the key from tail of `lru`. 64 func (lru *adapterMemoryLru) 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 // SyncAndClear synchronizes the keys from `rawList` to `list` and `data` 73 // using Least Recently Used algorithm. 74 func (lru *adapterMemoryLru) SyncAndClear(ctx context.Context) { 75 if lru.closed.Val() { 76 gtimer.Exit() 77 return 78 } 79 // Data synchronization. 80 var alreadyExistItem interface{} 81 for { 82 if rawListItem := lru.rawList.PopFront(); rawListItem != nil { 83 // Deleting the key from list. 84 if alreadyExistItem = lru.data.Get(rawListItem); alreadyExistItem != nil { 85 lru.list.Remove(alreadyExistItem.(*glist.Element)) 86 } 87 // Pushing key to the head of the list 88 // and setting its list item to hash table for quick indexing. 89 lru.data.Set(rawListItem, lru.list.PushFront(rawListItem)) 90 } else { 91 break 92 } 93 } 94 // Data cleaning up. 95 for clearLength := lru.Size() - lru.cache.cap; clearLength > 0; clearLength-- { 96 if topKey := lru.Pop(); topKey != nil { 97 lru.cache.clearByKey(topKey, true) 98 } 99 } 100 }