github.com/QuangTung97/bigcache@v0.1.0/bigcache.go (about)

     1  package bigcache
     2  
     3  import (
     4  	"github.com/QuangTung97/bigcache/memhash"
     5  	"math/bits"
     6  )
     7  
     8  // Cache ...
     9  type Cache struct {
    10  	segments []segment
    11  
    12  	segmentMask  uint64
    13  	segmentShift int
    14  }
    15  
    16  // New ...
    17  func New(numSegments int, segmentSize int) *Cache {
    18  	if numSegments < 1 {
    19  		panic("numSegments must not be < 1")
    20  	}
    21  	numSegments = nextPowerOfTwo(numSegments)
    22  
    23  	segments := make([]segment, numSegments)
    24  	for i := range segments {
    25  		initSegment(&segments[i], segmentSize)
    26  	}
    27  
    28  	mask, shift := computeSegmentMask(numSegments)
    29  	return &Cache{
    30  		segments:     segments,
    31  		segmentMask:  mask,
    32  		segmentShift: shift,
    33  	}
    34  }
    35  
    36  func (c *Cache) getSegment(key []byte) (*segment, uint64) {
    37  	hash := memhash.Hash(key)
    38  	index := getSegmentIndex(c.segmentMask, c.segmentShift, hash)
    39  	return &c.segments[index], hash
    40  }
    41  
    42  // Put ...
    43  func (c *Cache) Put(key []byte, value []byte) {
    44  	seg, hash := c.getSegment(key)
    45  
    46  	seg.mu.Lock()
    47  	seg.put(uint32(hash), key, value)
    48  	seg.mu.Unlock()
    49  }
    50  
    51  // Get ...
    52  func (c *Cache) Get(key []byte, value []byte) (int, bool) {
    53  	seg, hash := c.getSegment(key)
    54  
    55  	seg.mu.Lock()
    56  	n, ok := seg.get(uint32(hash), key, value)
    57  	seg.mu.Unlock()
    58  
    59  	return n, ok
    60  }
    61  
    62  // Delete ...
    63  func (c *Cache) Delete(key []byte) bool {
    64  	seg, hash := c.getSegment(key)
    65  
    66  	seg.mu.Lock()
    67  	affected := seg.delete(uint32(hash), key)
    68  	seg.mu.Unlock()
    69  
    70  	return affected
    71  }
    72  
    73  // GetHitCount ...
    74  func (c *Cache) GetHitCount() uint64 {
    75  	count := uint64(0)
    76  	for i := range c.segments {
    77  		count += c.segments[i].getHitCount()
    78  	}
    79  	return count
    80  }
    81  
    82  // GetAccessCount ...
    83  func (c *Cache) GetAccessCount() uint64 {
    84  	count := uint64(0)
    85  	for i := range c.segments {
    86  		count += c.segments[i].getAccessCount()
    87  	}
    88  	return count
    89  }
    90  
    91  // GetTotal ...
    92  func (c *Cache) GetTotal() uint64 {
    93  	count := uint64(0)
    94  	for i := range c.segments {
    95  		count += c.segments[i].getTotal()
    96  	}
    97  	return count
    98  }
    99  
   100  func nextPowerOfTwo(n int) int {
   101  	num := uint32(n)
   102  	return 1 << bits.Len32(num-1)
   103  }
   104  
   105  func computeSegmentMask(n int) (uint64, int) {
   106  	shift := 64 - bits.Len64(uint64(n-1))
   107  	return ^uint64(0) << shift, shift
   108  }
   109  
   110  func getSegmentIndex(mask uint64, shift int, hash uint64) int {
   111  	return int((hash & mask) >> shift)
   112  }