cachemap.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. package cache
  2. import (
  3. "runtime"
  4. "sync"
  5. "time"
  6. )
  7. type CallCreate func(key interface{}) (value interface{}, created bool)
  8. type CallCreateNew func(key interface{}) (rKey, value interface{}, created bool)
  9. type CallCheck func(key, value interface{}, exists bool) (rKey, rValue interface{}, created bool)
  10. func NewMap(liveDuration time.Duration, maxSize int) *CacheMap {
  11. res := &CacheMap{&cacheMap{
  12. locker: new(sync.RWMutex),
  13. items: make(map[interface{}]*cacheMapItem),
  14. liveDuration: liveDuration,
  15. maxSize: maxSize,
  16. stopCleanerChan: make(chan byte),
  17. }}
  18. runtime.SetFinalizer(res, destroyCacheMap)
  19. return res
  20. }
  21. type CacheMap struct {
  22. *cacheMap
  23. }
  24. type cacheMapItem struct {
  25. value interface{}
  26. expire int64
  27. }
  28. type cacheMap struct {
  29. locker *sync.RWMutex
  30. items map[interface{}]*cacheMapItem
  31. liveDuration time.Duration
  32. maxSize int
  33. cleanerWork bool
  34. stopCleanerChan chan byte
  35. cleanedEventChan chan map[interface{}]interface{}
  36. }
  37. func (s *cacheMap) CleanEvent() (eventChan <-chan map[interface{}]interface{}) {
  38. s.locker.Lock()
  39. if s.cleanedEventChan == nil {
  40. s.cleanedEventChan = make(chan map[interface{}]interface{})
  41. }
  42. eventChan = s.cleanedEventChan
  43. s.locker.Unlock()
  44. return
  45. }
  46. func (s *cacheMap) runCleaner() {
  47. ticker := time.NewTicker(s.liveDuration / 2)
  48. for {
  49. select {
  50. case <-ticker.C:
  51. {
  52. now := time.Now().UnixNano()
  53. s.locker.Lock()
  54. cleaned := make(map[interface{}]interface{})
  55. for key, val := range s.items {
  56. if now > val.expire {
  57. cleaned[key] = val.value
  58. delete(s.items, key)
  59. }
  60. }
  61. if len(cleaned) > 0 {
  62. s.cleanedEventChan <- cleaned
  63. }
  64. if len(s.items) == 0 {
  65. s.cleanerWork = false
  66. ticker.Stop()
  67. s.locker.Unlock()
  68. return
  69. }
  70. s.locker.Unlock()
  71. }
  72. case <-s.stopCleanerChan:
  73. {
  74. s.cleanerWork = false
  75. ticker.Stop()
  76. return
  77. }
  78. }
  79. }
  80. }
  81. func (s *cacheMap) delete(key interface{}) {
  82. delete(s.items, key)
  83. if len(s.items) == 0 && s.cleanerWork {
  84. s.stopCleanerChan <- 0
  85. }
  86. }
  87. // Delete removes cached object
  88. func (s *cacheMap) Delete(key interface{}) {
  89. s.locker.Lock()
  90. s.delete(key)
  91. s.locker.Unlock()
  92. }
  93. func (s *cacheMap) set(key, value interface{}) {
  94. s.items[key] = &cacheMapItem{
  95. value: value,
  96. expire: time.Now().Add(s.liveDuration).UnixNano(),
  97. }
  98. if !s.cleanerWork {
  99. s.cleanerWork = true
  100. go s.runCleaner()
  101. }
  102. }
  103. func (s *cacheMap) Set(key, value interface{}) {
  104. s.locker.Lock()
  105. s.set(key, value)
  106. s.locker.Unlock()
  107. }
  108. func (s *cacheMap) SetMulti(m map[interface{}]interface{}) {
  109. s.locker.Lock()
  110. for key, val := range m {
  111. s.set(key, val)
  112. }
  113. s.locker.Unlock()
  114. }
  115. func (s *CacheMap) DeleteMulti(keys []interface{}) {
  116. s.locker.Lock()
  117. for _, key := range keys {
  118. delete(s.items, key)
  119. }
  120. s.locker.Unlock()
  121. }
  122. func (s *cacheMap) get(key interface{}) (res interface{}, check bool) {
  123. var item *cacheMapItem
  124. if item, check = s.items[key]; check {
  125. res = item.value
  126. }
  127. return
  128. }
  129. func (s *cacheMap) Get(key interface{}) (res interface{}, check bool) {
  130. s.locker.RLock()
  131. res, check = s.get(key)
  132. s.locker.RUnlock()
  133. return
  134. }
  135. func (s *cacheMap) GetCreate(key interface{}, mCreate CallCreate) (val interface{}, check bool) {
  136. if val, check = s.Get(key); !check {
  137. s.locker.Lock()
  138. if val, check = s.get(key); check {
  139. s.locker.Unlock()
  140. return
  141. }
  142. if val, check = mCreate(key); check {
  143. s.set(key, val)
  144. }
  145. s.locker.Unlock()
  146. }
  147. return
  148. }
  149. func (s *cacheMap) GetCreateNew(key interface{}, mCreateNew CallCreateNew) (rKey, val interface{}, check bool) {
  150. rKey = key
  151. if val, check = s.Get(key); !check {
  152. s.locker.Lock()
  153. if val, check = s.get(key); check {
  154. s.locker.Unlock()
  155. return
  156. }
  157. if rKey, val, check = mCreateNew(key); check {
  158. s.set(rKey, val)
  159. }
  160. s.locker.Unlock()
  161. }
  162. return
  163. }
  164. func (s *cacheMap) GetCheck(key interface{}, mCheck CallCheck) (res interface{}, check bool) {
  165. s.locker.Lock()
  166. res, check = s.get(key)
  167. if rKey, rVal, rCheck := mCheck(key, res, check); rCheck {
  168. s.set(rKey, rVal)
  169. key, res, check = rKey, rVal, true
  170. }
  171. s.locker.Unlock()
  172. return
  173. }
  174. // Each implements a map bypass for each key using the callback function. If the callback function returns false, then the cycle stops
  175. func (s *cacheMap) Each(callback func(interface{}, interface{}) bool) {
  176. s.locker.RLock()
  177. for key, val := range s.items {
  178. if !callback(key, val.value) {
  179. s.locker.RUnlock()
  180. return
  181. }
  182. }
  183. s.locker.RUnlock()
  184. }
  185. func (s *cacheMap) Len() (res int) {
  186. s.locker.RLock()
  187. res = len(s.items)
  188. s.locker.RUnlock()
  189. return
  190. }
  191. func (s *cacheMap) Keys() (res []interface{}) {
  192. s.locker.RLock()
  193. res = make([]interface{}, 0, len(s.items))
  194. for key := range s.items {
  195. res = append(res, key)
  196. }
  197. s.locker.RUnlock()
  198. return
  199. }
  200. func (s *cacheMap) Clear() {
  201. s.locker.Lock()
  202. s.items = make(map[interface{}]*cacheMapItem)
  203. s.locker.Unlock()
  204. }
  205. // for garbage collector
  206. func destroyCacheMap(m *CacheMap) {
  207. close(m.stopCleanerChan)
  208. close(m.cleanedEventChan)
  209. }