go.temporal.io/server@v1.23.0/common/cache/simple.go (about) 1 // The MIT License (MIT) 2 // 3 // Copyright (c) 2017-2020 Uber Technologies Inc. 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 // 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 // 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 // SOFTWARE. 22 23 package cache 24 25 import ( 26 "container/list" 27 "sync" 28 "time" 29 ) 30 31 var ( 32 // DummyCreateTime is the create time used by all entries in the cache. 33 DummyCreateTime = time.Time{} 34 ) 35 36 type ( 37 simple struct { 38 sync.RWMutex 39 accessMap map[interface{}]*list.Element 40 iterateList *list.List 41 rmFunc RemovedFunc 42 } 43 44 simpleItr struct { 45 simple *simple 46 nextItem *list.Element 47 } 48 49 simpleEntry struct { 50 key interface{} 51 value interface{} 52 } 53 ) 54 55 // Close closes the iterator 56 func (it *simpleItr) Close() { 57 it.simple.RUnlock() 58 } 59 60 // HasNext return true if there is more items to be returned 61 func (it *simpleItr) HasNext() bool { 62 return it.nextItem != nil 63 } 64 65 // Next returns the next item 66 func (it *simpleItr) Next() Entry { 67 if it.nextItem == nil { 68 panic("Simple cache iterator Next called when there is no next item") 69 } 70 71 entry := it.nextItem.Value.(*simpleEntry) 72 it.nextItem = it.nextItem.Next() 73 // make a copy of the entry so there will be no concurrent access to this entry 74 entry = &simpleEntry{ 75 key: entry.key, 76 value: entry.value, 77 } 78 return entry 79 } 80 81 func (e *simpleEntry) Key() interface{} { 82 return e.key 83 } 84 85 func (e *simpleEntry) Value() interface{} { 86 return e.value 87 } 88 89 // CreateTime is not implemented for simple cache entries 90 func (e *simpleEntry) CreateTime() time.Time { 91 return DummyCreateTime 92 } 93 94 // NewSimple creates a new simple cache with given options. 95 // Simple cache will never evict entries and it will never reorder the elements. 96 // Simple cache also does not have the concept of pinning that LRU cache has. 97 // Internally simple cache uses a RWMutex instead of the exclusive Mutex that LRU cache uses. 98 // The RWMutex makes simple cache readable by many threads without introducing lock contention. 99 func NewSimple(opts *SimpleOptions) Cache { 100 if opts == nil { 101 opts = &SimpleOptions{} 102 } 103 return &simple{ 104 iterateList: list.New(), 105 accessMap: make(map[interface{}]*list.Element), 106 rmFunc: opts.RemovedFunc, 107 } 108 } 109 110 // Get retrieves the value stored under the given key 111 func (c *simple) Get(key interface{}) interface{} { 112 c.RLock() 113 defer c.RUnlock() 114 115 element := c.accessMap[key] 116 if element == nil { 117 return nil 118 } 119 return element.Value.(*simpleEntry).Value() 120 } 121 122 // Put puts a new value associated with a given key, returning the existing value (if present). 123 func (c *simple) Put(key interface{}, value interface{}) interface{} { 124 c.Lock() 125 defer c.Unlock() 126 existing := c.putInternal(key, value, true) 127 return existing 128 } 129 130 // PutIfNotExist puts a value associated with a given key if it does not exist 131 func (c *simple) PutIfNotExist(key interface{}, value interface{}) (interface{}, error) { 132 c.Lock() 133 defer c.Unlock() 134 existing := c.putInternal(key, value, false) 135 if existing == nil { 136 // This is a new value 137 return value, nil 138 } 139 return existing, nil 140 } 141 142 // Delete deletes a key, value pair associated with a key 143 func (c *simple) Delete(key interface{}) { 144 c.Lock() 145 defer c.Unlock() 146 147 element := c.accessMap[key] 148 if element == nil { 149 return 150 } 151 entry := c.iterateList.Remove(element).(*simpleEntry) 152 if c.rmFunc != nil { 153 go c.rmFunc(entry.value) 154 } 155 delete(c.accessMap, entry.key) 156 } 157 158 // Release does nothing for simple cache 159 func (c *simple) Release(_ interface{}) {} 160 161 // Size returns the number of entries currently in the cache 162 func (c *simple) Size() int { 163 c.RLock() 164 defer c.RUnlock() 165 166 return len(c.accessMap) 167 } 168 169 func (c *simple) Iterator() Iterator { 170 c.RLock() 171 iterator := &simpleItr{ 172 simple: c, 173 nextItem: c.iterateList.Front(), 174 } 175 return iterator 176 } 177 178 func (c *simple) putInternal(key interface{}, value interface{}, allowUpdate bool) interface{} { 179 elt := c.accessMap[key] 180 if elt != nil { 181 entry := elt.Value.(*simpleEntry) 182 existing := entry.value 183 if allowUpdate { 184 entry.value = value 185 } 186 return existing 187 } 188 entry := &simpleEntry{ 189 key: key, 190 value: value, 191 } 192 c.accessMap[key] = c.iterateList.PushFront(entry) 193 return nil 194 }