101 lines
1.7 KiB
Go
101 lines
1.7 KiB
Go
package concurrent
|
|
|
|
import (
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
"github.com/cespare/xxhash"
|
|
)
|
|
|
|
type bucket struct {
|
|
mux sync.RWMutex
|
|
values map[string]interface{}
|
|
}
|
|
|
|
func (b *bucket) Get(k string) (interface{}, bool) {
|
|
b.mux.RLock()
|
|
v, ok := b.values[k]
|
|
b.mux.RUnlock()
|
|
return v, ok
|
|
}
|
|
|
|
func (b *bucket) Set(k string, v interface{}) bool {
|
|
b.mux.Lock()
|
|
_, exsist := b.values[k]
|
|
b.values[k] = v
|
|
b.mux.Unlock()
|
|
return !exsist
|
|
}
|
|
|
|
func (b *bucket) Delete(k string) bool {
|
|
b.mux.Lock()
|
|
_, exsist := b.values[k]
|
|
delete(b.values, k)
|
|
b.mux.Unlock()
|
|
return exsist
|
|
}
|
|
|
|
func (b *bucket) forEach(f func(k string, v interface{}) bool) bool {
|
|
success := false
|
|
b.mux.RLock()
|
|
for k, v := range b.values {
|
|
success = f(k, v)
|
|
if !success {
|
|
break
|
|
}
|
|
}
|
|
b.mux.RUnlock()
|
|
return success
|
|
}
|
|
|
|
type Map struct {
|
|
size int64
|
|
buckets []*bucket
|
|
}
|
|
|
|
func (m *Map) Get(k string) (interface{}, bool) {
|
|
i := hash(k) % uint64(len(m.buckets))
|
|
return m.buckets[i].Get(k)
|
|
}
|
|
|
|
func (m *Map) Set(k string, v interface{}) {
|
|
i := hash(k) % uint64(len(m.buckets))
|
|
if m.buckets[i].Set(k, v) {
|
|
atomic.AddInt64(&m.size, 1)
|
|
}
|
|
}
|
|
|
|
func (m *Map) Delete(k string) {
|
|
i := hash(k) % uint64(len(m.buckets))
|
|
if m.buckets[i].Delete(k) {
|
|
atomic.AddInt64(&m.size, -1)
|
|
}
|
|
}
|
|
|
|
func (m *Map) Size() int64 {
|
|
return atomic.LoadInt64(&m.size)
|
|
}
|
|
|
|
func (m *Map) ForEach(f func(k string, v interface{}) bool) {
|
|
for _, b := range m.buckets {
|
|
if !b.forEach(f) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func NewMap(bucketNum int) *Map {
|
|
if bucketNum <= 0 {
|
|
bucketNum = 64
|
|
}
|
|
m := &Map{buckets: make([]*bucket, bucketNum)}
|
|
for i := 0; i < bucketNum; i++ {
|
|
m.buckets[i] = &bucket{values: map[string]interface{}{}}
|
|
}
|
|
return m
|
|
}
|
|
|
|
func hash(k string) uint64 {
|
|
return xxhash.Sum64String(k)
|
|
}
|