cachemap.go.tmp 5.0 KB

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