//ref https://github.com/DeanThompson/syncmap/blob/master/syncmap.go
|
|
package shardmap
|
|
import (
|
"sync"
|
"fmt"
|
)
|
|
const (
|
DEF_SHARD_CNT = 32
|
|
BKDR_SEED = 131 // 31 131 1313 13131 131313 etc...
|
)
|
|
type shardItem struct {
|
sync.RWMutex
|
|
data map[string]interface{}
|
}
|
|
type ShardMap struct {
|
shardCnt uint8
|
shards []*shardItem
|
}
|
|
var Count = make(chan int)
|
|
type wfOp func(a, b string) float32
|
|
/**
|
* @param uint8, shardCnt must be pow of two
|
*/
|
func New(shardCnt uint8) *ShardMap {
|
if !isPowOfTwo(shardCnt) {
|
shardCnt = DEF_SHARD_CNT
|
}
|
|
s := &ShardMap{
|
shardCnt: shardCnt,
|
shards: make([]*shardItem, shardCnt),
|
}
|
|
for i, _ := range s.shards {
|
s.shards[i] = &shardItem{
|
data: make(map[string]interface{}),
|
}
|
}
|
|
return s
|
}
|
|
func (s *ShardMap) Get(key string) (interface{}, bool) {
|
si := s.locate(key)
|
|
si.RLock()
|
value, ok := si.data[key]
|
si.RUnlock()
|
return value, ok
|
}
|
|
func (s *ShardMap) Set(key string, value interface{}) {
|
si := s.locate(key)
|
|
si.Lock()
|
si.data[key] = value
|
si.Unlock()
|
}
|
|
func (s *ShardMap) Del(key string) {
|
si := s.locate(key)
|
|
si.Lock()
|
delete(si.data, key)
|
si.Unlock()
|
}
|
|
type kvItem struct {
|
key string
|
value interface{}
|
}
|
|
// modify by long.
|
func (s *ShardMap) Walk(wf wfOp, cfrom string) {
|
|
var wg sync.WaitGroup
|
var second float32
|
|
for _, si := range s.shards {
|
//fmt.Println(len(si.data))
|
wg.Add(1)
|
go func(s *shardItem, fw wfOp, cf string) {
|
defer wg.Done()
|
s.RLock()
|
for _, v := range s.data {
|
if cv, ok := v.(string); ok {
|
second = fw(cf,cv)
|
fmt.Println(second)
|
}
|
}
|
s.RUnlock()
|
}(si,wf, cfrom)
|
}
|
|
wg.Wait()
|
}
|
|
func (s * ShardMap)GetLen() int {
|
var slen int
|
for i:= 0 ; i<int(s.shardCnt); i++{
|
slen += len(s.shards[i].data)
|
}
|
return slen
|
}
|
|
func (s *ShardMap) locate(key string) *shardItem {
|
i := bkdrHash(key) & uint32(s.shardCnt-1)
|
|
return s.shards[i]
|
}
|
|
func isPowOfTwo(x uint8) bool {
|
return x != 0 && (x&(x-1) == 0)
|
}
|
|
//https://www.byvoid.com/blog/string-hash-compare/
|
func bkdrHash(str string) uint32 {
|
var h uint32
|
|
for _, c := range str {
|
h = h*BKDR_SEED + uint32(c)
|
}
|
|
return h
|
}
|