vRp.CD2g_test/utils/synchronization/map_segment.go

260 lines
5.6 KiB
Go

package synchronization
import (
"encoding/json"
"github.com/kercylan98/minotaur/utils/hash"
"sync"
)
func NewMapSegment[Key comparable, value any](segmentCount int) *MapSegment[Key, value] {
ms := &MapSegment[Key, value]{
segments: map[int]*Map[Key, value]{},
cache: map[Key]int{},
consistency: hash.NewConsistency(segmentCount),
}
for i := 0; i < segmentCount; i++ {
ms.consistency.AddNode(i)
ms.segments[i] = NewMap[Key, value]()
}
return ms
}
// MapSegment 基于分段锁实现的并发安全的字典数据结构map
type MapSegment[Key comparable, Value any] struct {
segments map[int]*Map[Key, Value]
cache map[Key]int
consistency *hash.Consistency
lock sync.RWMutex
}
func (slf *MapSegment[Key, Value]) Atom(handle func(m hash.Map[Key, Value])) {
panic("this function is currently not supported")
}
func (slf *MapSegment[Key, Value]) Set(key Key, value Value) {
slf.lock.RLock()
s, exist := slf.cache[key]
slf.lock.RUnlock()
if !exist {
s = slf.consistency.PickNode(key)
slf.lock.Lock()
slf.cache[key] = s
slf.lock.Unlock()
}
slf.segments[s].Set(key, value)
}
func (slf *MapSegment[Key, Value]) Get(key Key) (value Value) {
slf.lock.RLock()
s, exist := slf.cache[key]
slf.lock.RUnlock()
if !exist {
return value
}
return slf.segments[s].Get(key)
}
// AtomGetSet 原子方式获取一个值并在之后进行赋值
func (slf *MapSegment[Key, Value]) AtomGetSet(key Key, handle func(value Value, exist bool) (newValue Value, isSet bool)) {
var value Value
slf.lock.RLock()
s, exist := slf.cache[key]
slf.lock.RUnlock()
if !exist {
if newValue, isSet := handle(value, exist); isSet {
slf.Set(key, newValue)
}
return
}
slf.segments[s].AtomGetSet(key, handle)
}
func (slf *MapSegment[Key, Value]) Exist(key Key) bool {
slf.lock.RLock()
_, exist := slf.cache[key]
slf.lock.RUnlock()
return exist
}
func (slf *MapSegment[Key, Value]) GetExist(key Key) (value Value, exist bool) {
slf.lock.RLock()
s, exist := slf.cache[key]
slf.lock.RUnlock()
if !exist {
return value, false
}
return slf.segments[s].GetExist(key)
}
func (slf *MapSegment[Key, Value]) Delete(key Key) {
slf.lock.Lock()
s, exist := slf.cache[key]
delete(slf.cache, key)
slf.lock.Unlock()
if exist {
slf.segments[s].Delete(key)
}
}
func (slf *MapSegment[Key, Value]) DeleteGet(key Key) (value Value) {
slf.lock.Lock()
s, exist := slf.cache[key]
delete(slf.cache, key)
slf.lock.Unlock()
if exist {
return slf.segments[s].DeleteGet(key)
}
return
}
func (slf *MapSegment[Key, Value]) DeleteGetExist(key Key) (value Value, exist bool) {
slf.lock.Lock()
s, exist := slf.cache[key]
delete(slf.cache, key)
slf.lock.Unlock()
if exist {
return slf.segments[s].DeleteGetExist(key)
}
return value, exist
}
func (slf *MapSegment[Key, Value]) DeleteExist(key Key) bool {
slf.lock.Lock()
s, exist := slf.cache[key]
delete(slf.cache, key)
slf.lock.Unlock()
if exist {
return slf.segments[s].DeleteExist(key)
}
return false
}
func (slf *MapSegment[Key, Value]) Clear() {
slf.lock.Lock()
for k := range slf.cache {
delete(slf.cache, k)
}
for _, m := range slf.segments {
m.Clear()
}
slf.lock.Unlock()
}
func (slf *MapSegment[Key, Value]) ClearHandle(handle func(key Key, value Value)) {
slf.lock.Lock()
for k := range slf.cache {
delete(slf.cache, k)
}
for _, m := range slf.segments {
m.ClearHandle(handle)
}
slf.lock.Unlock()
}
func (slf *MapSegment[Key, Value]) Range(handle func(key Key, value Value)) {
for _, m := range slf.segments {
m.Range(handle)
}
}
func (slf *MapSegment[Key, Value]) RangeSkip(handle func(key Key, value Value) bool) {
for _, m := range slf.segments {
m.RangeSkip(handle)
}
}
func (slf *MapSegment[Key, Value]) RangeBreakout(handle func(key Key, value Value) bool) {
for _, m := range slf.segments {
if m.rangeBreakout(handle) {
break
}
}
}
func (slf *MapSegment[Key, Value]) RangeFree(handle func(key Key, value Value, skip func(), breakout func())) {
for _, m := range slf.segments {
if m.rangeFree(handle) {
break
}
}
}
func (slf *MapSegment[Key, Value]) Keys() []Key {
var s = make([]Key, 0, len(slf.cache))
slf.lock.RLock()
for k, _ := range slf.cache {
s = append(s, k)
}
defer slf.lock.RUnlock()
return s
}
func (slf *MapSegment[Key, Value]) Slice() []Value {
slf.lock.RLock()
var s = make([]Value, 0, len(slf.cache))
slf.lock.RUnlock()
for _, m := range slf.segments {
s = append(s, m.Slice()...)
}
return s
}
func (slf *MapSegment[Key, Value]) Map() map[Key]Value {
slf.lock.RLock()
var s = map[Key]Value{}
slf.lock.RUnlock()
for _, m := range slf.segments {
for k, v := range m.Map() {
s[k] = v
}
}
return s
}
func (slf *MapSegment[Key, Value]) Size() int {
slf.lock.RLock()
defer slf.lock.RUnlock()
return len(slf.cache)
}
// GetOne 获取一个
func (slf *MapSegment[Key, Value]) GetOne() (value Value) {
for k, s := range slf.cache {
return slf.segments[s].Get(k)
}
return value
}
func (slf *MapSegment[Key, Value]) MarshalJSON() ([]byte, error) {
var ms struct {
Segments map[int]*Map[Key, Value]
Cache map[Key]int
SegmentCount int
}
ms.Segments = slf.segments
ms.Cache = slf.cache
ms.SegmentCount = len(slf.segments)
return json.Marshal(ms)
}
func (slf *MapSegment[Key, Value]) UnmarshalJSON(bytes []byte) error {
var ms struct {
Segments map[int]*Map[Key, Value]
Cache map[Key]int
SegmentCount int
}
if err := json.Unmarshal(bytes, &ms); err != nil {
return err
}
slf.lock.Lock()
slf.consistency = hash.NewConsistency(ms.SegmentCount)
for i := 0; i < ms.SegmentCount; i++ {
slf.consistency.AddNode(i)
}
slf.segments = ms.Segments
slf.cache = ms.Cache
slf.lock.Unlock()
return nil
}