diff --git a/internal/utils/maps/map_fixed.go b/internal/utils/maps/map_fixed.go new file mode 100644 index 0000000..6c71a21 --- /dev/null +++ b/internal/utils/maps/map_fixed.go @@ -0,0 +1,78 @@ +// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package maputils + +import "sync" + +type KeyType interface { + string | int | int64 | int32 | uint64 | uint32 +} + +type ValueType interface { + any +} + +// FixedMap +// TODO 解决已存在元素不能按顺序弹出的问题 +type FixedMap[KeyT KeyType, ValueT ValueType] struct { + m map[KeyT]ValueT + keys []KeyT + + maxSize int + locker sync.RWMutex +} + +func NewFixedMap[KeyT KeyType, ValueT ValueType](maxSize int) *FixedMap[KeyT, ValueT] { + return &FixedMap[KeyT, ValueT]{ + maxSize: maxSize, + m: map[KeyT]ValueT{}, + } +} + +func (this *FixedMap[KeyT, ValueT]) Put(key KeyT, value ValueT) { + this.locker.Lock() + defer this.locker.Unlock() + + if this.maxSize <= 0 { + return + } + + _, exists := this.m[key] + this.m[key] = value + + if !exists { + this.keys = append(this.keys, key) + + if len(this.keys) > this.maxSize { + var firstKey = this.keys[0] + this.keys = this.keys[1:] + delete(this.m, firstKey) + } + } +} + +func (this *FixedMap[KeyT, ValueT]) Get(key KeyT) (value ValueT, ok bool) { + this.locker.RLock() + defer this.locker.RUnlock() + value, ok = this.m[key] + return +} + +func (this *FixedMap[KeyT, ValueT]) Has(key KeyT) bool { + this.locker.RLock() + defer this.locker.RUnlock() + _, ok := this.m[key] + return ok +} + +func (this *FixedMap[KeyT, ValueT]) Keys() []KeyT { + this.locker.RLock() + defer this.locker.RUnlock() + return this.keys +} + +func (this *FixedMap[KeyT, ValueT]) RawMap() map[KeyT]ValueT { + this.locker.RLock() + defer this.locker.RUnlock() + return this.m +} diff --git a/internal/utils/maps/map_fixed_test.go b/internal/utils/maps/map_fixed_test.go new file mode 100644 index 0000000..545263b --- /dev/null +++ b/internal/utils/maps/map_fixed_test.go @@ -0,0 +1,26 @@ +// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package maputils_test + +import ( + maputils "github.com/TeaOSLab/EdgeNode/internal/utils/maps" + "testing" +) + +func TestNewFixedMap(t *testing.T) { + var m = maputils.NewFixedMap[string, int](3) + m.Put("a", 1) + t.Log(m.RawMap()) + t.Log(m.Get("a")) + t.Log(m.Get("b")) + + m.Put("b", 2) + m.Put("c", 3) + t.Log(m.RawMap(), m.Keys()) + + m.Put("d", 4) + t.Log(m.RawMap(), m.Keys()) + + m.Put("b", 200) + t.Log(m.RawMap(), m.Keys()) +} diff --git a/internal/utils/sets/set_fixed.go b/internal/utils/sets/set_fixed.go index 9a1e189..71287b8 100644 --- a/internal/utils/sets/set_fixed.go +++ b/internal/utils/sets/set_fixed.go @@ -7,6 +7,8 @@ import ( "sync" ) +// FixedSet +// TODO 解决已存在元素不能按顺序弹出的问题 type FixedSet struct { maxSize int locker sync.RWMutex