github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/objcache/impl.go (about)

     1  /*
     2   * Copyright (c) 2023-present Sigma-Soft, Ltd.
     3   * @author: Nikolay Nikitin
     4   *
     5   * This source code is licensed under the MIT license found in the
     6   * LICENSE file in the root directory of this source tree.
     7   */
     8  
     9  package objcache
    10  
    11  import (
    12  	lru "github.com/hashicorp/golang-lru/v2"
    13  )
    14  
    15  // internally used interface
    16  type refCounter interface {
    17  	tryAddRef() bool
    18  	Release()
    19  }
    20  
    21  // LRU cache implemented by hashicorp LRU cache
    22  type cache[K comparable, V any] struct {
    23  	lru *lru.Cache[K, V]
    24  }
    25  
    26  func (c *cache[K, V]) Get(key K) (value V, ok bool) {
    27  	value, ok = c.lru.Get(key)
    28  	if ok {
    29  		if ref, auto := any(value).(refCounter); auto {
    30  			ok = ref.tryAddRef()
    31  		}
    32  	}
    33  	return value, ok
    34  }
    35  
    36  func (c *cache[K, V]) Put(key K, value V) {
    37  	// The problem of the twice put (value won’t be freed) is solved by convention (*DO NOT PUT SAME VALUE TWICE*)
    38  	// if old, exists := c.lru.Peek(key); exists && (any(old) == any(value)) { return }
    39  
    40  	if ref, auto := any(value).(refCounter); auto {
    41  		if !ref.tryAddRef() {
    42  			// notest: looks like value right now released
    43  			return
    44  		}
    45  	}
    46  	_ = c.lru.Add(key, value)
    47  }
    48  
    49  func (c *cache[K, V]) evicted(_ K, value V) {
    50  	if ref, ok := any(value).(refCounter); ok {
    51  		ref.Release()
    52  	}
    53  }