github.com/artisanhe/tools@v1.0.1-0.20210607022958-19a8fef2eb04/catgo/cat-go/cat/ccmap.go (about) 1 package cat 2 3 import ( 4 "sync" 5 ) 6 7 type ccMap struct { 8 count uint32 9 buckets []ccMapBucket 10 hasher ccMapHasher 11 } 12 13 type ccMapBucket struct { 14 mu sync.Mutex 15 data map[string]interface{} 16 } 17 18 type ccMapHasher func(name string) uint32 19 20 type ccMapCreator func(name string) interface{} 21 22 type ccMapComputer func(interface{}) error 23 24 func hasher(name string) uint32 { 25 var h uint32 = 0 26 if len(name) > 0 { 27 for i := 0; i < len(name); i++ { 28 h = 31*h + uint32(name[i]) 29 } 30 } 31 return h 32 } 33 34 func newCCMap(count int) *ccMap { 35 var ccmap = &ccMap{ 36 count: uint32(count), 37 buckets: make([]ccMapBucket, count), 38 hasher: hasher, 39 } 40 for i := 0; i < count; i++ { 41 ccmap.buckets[i] = ccMapBucket{ 42 mu: sync.Mutex{}, 43 data: make(map[string]interface{}), 44 } 45 } 46 return ccmap 47 } 48 49 func (p *ccMap) compute(key string, creator ccMapCreator, computer ccMapComputer) (err error) { 50 hash := p.hasher(key) 51 slot := hash % p.count 52 bucket := p.buckets[slot] 53 54 bucket.mu.Lock() 55 defer bucket.mu.Unlock() 56 57 return bucket.compute(key, creator, computer) 58 } 59 60 func (p *ccMapBucket) compute(key string, creator ccMapCreator, computer ccMapComputer) (err error) { 61 var item interface{} 62 var ok bool 63 64 if item, ok = p.data[key]; !ok { 65 p.data[key] = creator(key) 66 item = p.data[key] 67 } 68 err = computer(item) 69 return 70 }