synccache.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package lrucache
  2. import (
  3. "hash/crc32"
  4. "sync"
  5. "time"
  6. )
  7. // hashCode hashes a string to a unique hashcode.
  8. //
  9. // crc32 returns a uint32, but for our use we need
  10. // and non negative integer. Here we cast to an integer
  11. // and invert it if the result is negative.
  12. func hashCode(s string) (hc int) {
  13. hc = int(crc32.ChecksumIEEE([]byte(s)))
  14. if hc >= 0 {
  15. return hc
  16. }
  17. if -hc >= 0 {
  18. return -hc
  19. }
  20. // hc == MinInt
  21. return hc
  22. }
  23. // SyncCache - concurrent cache structure
  24. type SyncCache struct {
  25. locks []sync.Mutex
  26. caches []*LRUCache
  27. mask int
  28. timeout int64
  29. }
  30. type scValue struct {
  31. Value interface{}
  32. ts int64
  33. }
  34. func nextPowOf2(cap int) int {
  35. if cap < 2 {
  36. return 2
  37. }
  38. if cap&(cap-1) == 0 {
  39. return cap
  40. }
  41. cap |= cap >> 1
  42. cap |= cap >> 2
  43. cap |= cap >> 4
  44. cap |= cap >> 8
  45. cap |= cap >> 16
  46. return cap + 1
  47. }
  48. // NewSyncCache - create sync cache
  49. // `capacity` is lru cache length of each bucket
  50. // store `capacity * bucket` count of element in SyncCache at most
  51. // `timeout` is in seconds
  52. func NewSyncCache(capacity int, bucket int, timeout int64) *SyncCache {
  53. size := nextPowOf2(bucket)
  54. sc := SyncCache{make([]sync.Mutex, size), make([]*LRUCache, size), size - 1, timeout}
  55. for i := range sc.caches {
  56. sc.caches[i] = New(capacity)
  57. }
  58. return &sc
  59. }
  60. // Put - put a cache item into sync cache
  61. func (sc *SyncCache) Put(key string, value interface{}) {
  62. idx := hashCode(key) & sc.mask
  63. sc.locks[idx].Lock()
  64. sc.caches[idx].Put(key, &scValue{value, time.Now().Unix()})
  65. sc.locks[idx].Unlock()
  66. }
  67. // Get - get value of key from sync cache with result
  68. func (sc *SyncCache) Get(key string) (interface{}, bool) {
  69. idx := hashCode(key) & sc.mask
  70. sc.locks[idx].Lock()
  71. v, b := sc.caches[idx].Get(key)
  72. if !b {
  73. sc.locks[idx].Unlock()
  74. return nil, false
  75. }
  76. if time.Now().Unix()-v.(*scValue).ts >= sc.timeout {
  77. sc.caches[idx].Delete(key)
  78. sc.locks[idx].Unlock()
  79. return nil, false
  80. }
  81. sc.locks[idx].Unlock()
  82. return v.(*scValue).Value, b
  83. }
  84. // Delete - delete item by key from sync cache
  85. func (sc *SyncCache) Delete(key string) {
  86. idx := hashCode(key) & sc.mask
  87. sc.locks[idx].Lock()
  88. sc.caches[idx].Delete(key)
  89. sc.locks[idx].Unlock()
  90. }