memcache.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package cache
  2. import (
  3. "container/list"
  4. "sync"
  5. "sync/atomic"
  6. )
  7. // An AtomicInt is an int64 to be accessed atomically.
  8. type AtomicInt int64
  9. // MemCache is an LRU cache. It is safe for concurrent access.
  10. type MemCache struct {
  11. hits, gets AtomicInt
  12. mutex sync.RWMutex
  13. maxItemSize int
  14. cacheList *list.List
  15. cache map[interface{}]*list.Element
  16. }
  17. type entry struct {
  18. key interface{}
  19. value interface{}
  20. }
  21. // NewMemCache If maxItemSize is zero, the cache has no limit.
  22. //if maxItemSize is not zero, when cache's size beyond maxItemSize,start to swap
  23. func NewMemCache(maxItemSize int) *MemCache {
  24. return &MemCache{
  25. maxItemSize: maxItemSize,
  26. cacheList: list.New(),
  27. cache: make(map[interface{}]*list.Element),
  28. }
  29. }
  30. // Status return the status of cache
  31. func (c *MemCache) Status() *CacheStatus {
  32. c.mutex.RLock()
  33. defer c.mutex.RUnlock()
  34. return &CacheStatus{
  35. MaxItemSize: c.maxItemSize,
  36. CurrentSize: c.cacheList.Len(),
  37. Gets: c.gets.Get(),
  38. Hits: c.hits.Get(),
  39. }
  40. }
  41. //Get value with key
  42. func (c *MemCache) Get(key string) (interface{}, bool) {
  43. c.mutex.RLock()
  44. defer c.mutex.RUnlock()
  45. c.gets.Add(1)
  46. if ele, hit := c.cache[key]; hit {
  47. c.hits.Add(1)
  48. return ele.Value.(*entry).value, true
  49. }
  50. return nil, false
  51. }
  52. //Set a value with key
  53. func (c *MemCache) Set(key string, value interface{}) {
  54. c.mutex.Lock()
  55. defer c.mutex.Unlock()
  56. if c.cache == nil {
  57. c.cache = make(map[interface{}]*list.Element)
  58. c.cacheList = list.New()
  59. }
  60. if ele, ok := c.cache[key]; ok {
  61. c.cacheList.MoveToFront(ele)
  62. ele.Value.(*entry).value = value
  63. return
  64. }
  65. ele := c.cacheList.PushFront(&entry{key: key, value: value})
  66. c.cache[key] = ele
  67. if c.maxItemSize != 0 && c.cacheList.Len() > c.maxItemSize {
  68. c.RemoveOldest()
  69. }
  70. }
  71. // Delete a value with key
  72. func (c *MemCache) Delete(key string) {
  73. c.mutex.Lock()
  74. defer c.mutex.Unlock()
  75. if c.cache == nil {
  76. return
  77. }
  78. if ele, ok := c.cache[key]; ok {
  79. c.cacheList.Remove(ele)
  80. key := ele.Value.(*entry).key
  81. delete(c.cache, key)
  82. return
  83. }
  84. }
  85. // RemoveOldest remove oldest key
  86. func (c *MemCache) RemoveOldest() {
  87. if c.cache == nil {
  88. return
  89. }
  90. ele := c.cacheList.Back()
  91. if ele != nil {
  92. c.cacheList.Remove(ele)
  93. key := ele.Value.(*entry).key
  94. delete(c.cache, key)
  95. }
  96. }
  97. // Add atomically adds n to i.
  98. func (i *AtomicInt) Add(n int64) {
  99. atomic.AddInt64((*int64)(i), n)
  100. }
  101. // Get atomically gets the value of i.
  102. func (i *AtomicInt) Get() int64 {
  103. return atomic.LoadInt64((*int64)(i))
  104. }