1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- package utils
- import (
- "errors"
- "fmt"
- "reflect"
- "sync"
- "sync/atomic"
- )
- var _ ConcurrentMap = (*concurrentMap)(nil)
- type ConcurrentMap interface {
- i()
- Store(key, value interface{})
- Delete(key interface{})
- Range(f func(key, value interface{}) bool)
- Load(key interface{}) (value interface{}, ok bool)
- LoadOrStore(key, value interface{}) (actual interface{}, loaded bool)
- }
- type concurrentMap struct {
- m sync.Map
- keyType reflect.Type
- valueType reflect.Type
- counter int64
- }
- func NewConcurrentMap(keyType, valueType reflect.Type) (ConcurrentMap, error) {
- if keyType == nil {
- return nil, errors.New("nil key type")
- }
- if !keyType.Comparable() {
- return nil, fmt.Errorf("incomparable key type: %s", keyType)
- }
- if valueType == nil {
- return nil, errors.New("nil value type")
- }
- cMap := &concurrentMap{
- keyType: keyType,
- valueType: valueType,
- counter: 0,
- }
- return cMap, nil
- }
- func (cMap *concurrentMap) i() {}
- func (cMap *concurrentMap) Delete(key interface{}) {
- if reflect.TypeOf(key) != cMap.keyType {
- return
- }
- cMap.m.Delete(key)
- atomic.AddInt64(&cMap.counter, -1)
- }
- func (cMap *concurrentMap) Len() int64 {
- return cMap.counter
- }
- func (cMap *concurrentMap) Load(key interface{}) (value interface{}, ok bool) {
- if reflect.TypeOf(key) != cMap.keyType {
- return
- }
- return cMap.m.Load(key)
- }
- func (cMap *concurrentMap) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) {
- if reflect.TypeOf(key) != cMap.keyType {
- panic(fmt.Errorf("wrong key type: %v", reflect.TypeOf(key)))
- }
- if reflect.TypeOf(value) != cMap.valueType {
- panic(fmt.Errorf("wrong value type: %v", reflect.TypeOf(value)))
- }
- actual, loaded = cMap.m.LoadOrStore(key, value)
- return
- }
- func (cMap *concurrentMap) Range(f func(key, value interface{}) bool) {
- cMap.m.Range(f)
- }
- func (cMap *concurrentMap) Store(key, value interface{}) {
- if reflect.TypeOf(key) != cMap.keyType {
- panic(fmt.Errorf("wrong key type: %v", reflect.TypeOf(key)))
- }
- if reflect.TypeOf(value) != cMap.valueType {
- panic(fmt.Errorf("wrong value type: %v", reflect.TypeOf(value)))
- }
- if _, ok := cMap.m.Load(key); ok {
- cMap.Delete(key)
- }
- cMap.m.Store(key, value)
- atomic.AddInt64(&cMap.counter, 1)
- }
|