github.com/LagrangeDev/LagrangeGo@v0.0.0-20240512064304-ad4a85e10cb4/client/internal/cache/base.go (about) 1 package cache 2 3 import ( 4 "reflect" 5 "unsafe" 6 7 "github.com/LagrangeDev/LagrangeGo/client/entity" 8 "github.com/RomiChan/syncx" 9 ) 10 11 type cacheType uint32 12 13 const ( 14 cacheTypeCache cacheType = 1 << iota 15 cacheTypeFriend 16 cacheTypeGroupInfo 17 cacheTypeGroupMember 18 ) 19 20 func typenameof[T any]() string { 21 return reflect.ValueOf((*T)(nil)).Type().String() 22 } 23 24 var cacheTypesMap = map[string]cacheType{ 25 typenameof[Cache](): cacheTypeCache, 26 typenameof[entity.Friend](): cacheTypeFriend, 27 typenameof[entity.Group](): cacheTypeGroupInfo, 28 typenameof[entity.GroupMember](): cacheTypeGroupMember, 29 } 30 31 type Cache struct { 32 m syncx.Map[uint64, unsafe.Pointer] 33 refreshed syncx.Map[cacheType, struct{}] 34 } 35 36 func hasRefreshed[T any](c *Cache) bool { 37 typ := cacheTypesMap[reflect.ValueOf((*T)(nil)).Type().String()] 38 if typ == 0 { 39 return false 40 } 41 _, ok := c.refreshed.Load(typ) 42 return ok 43 } 44 45 func refreshAllCacheOf[T any](c *Cache, newcache map[uint32]*T) { 46 typstr := reflect.ValueOf((*T)(nil)).Type().String() 47 typ := cacheTypesMap[typstr] 48 if typ == 0 { 49 return 50 } 51 c.refreshed.Store(typ, struct{}{}) 52 key := uint64(typ) << 32 53 dellst := make([]uint64, 0, 64) 54 c.m.Range(func(k uint64, v unsafe.Pointer) bool { 55 if k&key != 0 { 56 if _, ok := newcache[uint32(k)]; !ok { 57 dellst = append(dellst, k) 58 } 59 } 60 return true 61 }) 62 for k, v := range newcache { 63 c.m.Store(key|uint64(k), unsafe.Pointer(v)) 64 } 65 for _, k := range dellst { 66 c.m.Delete(k) 67 } 68 } 69 70 func setCacheOf[T any](c *Cache, k uint32, v *T) { 71 typstr := reflect.ValueOf(v).Type().String() 72 typ := cacheTypesMap[typstr] 73 if typ == 0 { 74 return 75 } 76 key := uint64(typ)<<32 | uint64(k) 77 c.m.Store(key, unsafe.Pointer(v)) 78 } 79 80 func getCacheOf[T any](c *Cache, k uint32) (v *T, ok bool) { 81 typstr := reflect.ValueOf(v).Type().String() 82 typ := cacheTypesMap[typstr] 83 if typ == 0 { 84 return 85 } 86 key := uint64(typ)<<32 | uint64(k) 87 unsafev, ok := c.m.Load(key) 88 if ok { 89 v = (*T)(unsafev) 90 } 91 return 92 } 93 94 func rangeCacheOf[T any](c *Cache, iter func(k uint32, v *T) bool) { 95 typ := cacheTypesMap[reflect.ValueOf((*T)(nil)).Type().String()] 96 if typ == 0 { 97 return 98 } 99 key := uint64(typ) << 32 100 c.m.Range(func(k uint64, v unsafe.Pointer) bool { 101 if k&key != 0 { 102 return iter(uint32(k), (*T)(v)) 103 } 104 return true 105 }) 106 }