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  }