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  }