mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-02 03:17:37 +03:00
freelru: Fix GetAndRefreshOrAdd
This commit is contained in:
parent
be9840c70f
commit
4dabb9be97
5 changed files with 23 additions and 17 deletions
|
@ -51,7 +51,7 @@ func New(handler N.UDPConnectionHandlerEx, prepare PrepareFunc, timeout time.Dur
|
|||
}
|
||||
|
||||
func (s *Service) NewPacket(bufferSlices [][]byte, source M.Socksaddr, destination M.Socksaddr, userData any) {
|
||||
conn, loaded := s.cache.GetAndRefreshOrAdd(source.AddrPort(), func() (*natConn, bool) {
|
||||
conn, _, ok := s.cache.GetAndRefreshOrAdd(source.AddrPort(), func() (*natConn, bool) {
|
||||
ok, ctx, writer, onClose := s.prepare(source, destination, userData)
|
||||
if !ok {
|
||||
return nil, false
|
||||
|
@ -67,10 +67,8 @@ func (s *Service) NewPacket(bufferSlices [][]byte, source M.Socksaddr, destinati
|
|||
go s.handler.NewPacketConnectionEx(ctx, newConn, source, destination, onClose)
|
||||
return newConn, true
|
||||
})
|
||||
if !loaded {
|
||||
if conn == nil {
|
||||
return
|
||||
}
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
buffer := conn.readWaitOptions.NewPacketBuffer()
|
||||
for _, bufferSlice := range bufferSlices {
|
||||
|
|
|
@ -54,7 +54,7 @@ type Cache[K comparable, V comparable] interface {
|
|||
// The lifetime of the found cache item is refreshed, even if it was already expired.
|
||||
GetAndRefresh(key K) (V, bool)
|
||||
|
||||
GetAndRefreshOrAdd(key K, constructor func() (V, bool)) (V, bool)
|
||||
GetAndRefreshOrAdd(key K, constructor func() (V, bool)) (V, bool, bool)
|
||||
|
||||
// Peek looks up a key's value from the cache, without changing its recent-ness.
|
||||
// If the found entry is already expired, the evict function is called.
|
||||
|
|
|
@ -522,11 +522,15 @@ func (lru *LRU[K, V]) getAndRefresh(hash uint32, key K) (value V, ok bool) {
|
|||
return
|
||||
}
|
||||
|
||||
func (lru *LRU[K, V]) GetAndRefreshOrAdd(key K, constructor func() (V, bool)) (V, bool) {
|
||||
return lru.getAndRefreshOrAdd(lru.hash(key), key, constructor)
|
||||
func (lru *LRU[K, V]) GetAndRefreshOrAdd(key K, constructor func() (V, bool)) (V, bool, bool) {
|
||||
value, updated, ok := lru.getAndRefreshOrAdd(lru.hash(key), key, constructor)
|
||||
if !updated && ok {
|
||||
lru.PurgeExpired()
|
||||
}
|
||||
return value, updated, ok
|
||||
}
|
||||
|
||||
func (lru *LRU[K, V]) getAndRefreshOrAdd(hash uint32, key K, constructor func() (V, bool)) (value V, ok bool) {
|
||||
func (lru *LRU[K, V]) getAndRefreshOrAdd(hash uint32, key K, constructor func() (V, bool)) (value V, updated bool, ok bool) {
|
||||
if pos, ok := lru.findKeyNoExpire(hash, key); ok {
|
||||
if pos != lru.head {
|
||||
lru.unlinkElement(pos)
|
||||
|
@ -534,17 +538,15 @@ func (lru *LRU[K, V]) getAndRefreshOrAdd(hash uint32, key K, constructor func()
|
|||
}
|
||||
lru.metrics.Hits++
|
||||
lru.elements[pos].expire = expire(lru.lifetime)
|
||||
return lru.elements[pos].value, ok
|
||||
return lru.elements[pos].value, true, true
|
||||
}
|
||||
|
||||
lru.metrics.Misses++
|
||||
value, ok = constructor()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
lru.addWithLifetime(hash, key, value, lru.lifetime)
|
||||
lru.PurgeExpired()
|
||||
return value, false
|
||||
return value, false, true
|
||||
}
|
||||
|
||||
// Peek looks up a key's value from the cache, without changing its recent-ness.
|
||||
|
|
|
@ -201,14 +201,17 @@ func (lru *ShardedLRU[K, V]) GetAndRefresh(key K) (value V, ok bool) {
|
|||
return
|
||||
}
|
||||
|
||||
func (lru *ShardedLRU[K, V]) GetAndRefreshOrAdd(key K, constructor func() (V, bool)) (value V, updated bool) {
|
||||
func (lru *ShardedLRU[K, V]) GetAndRefreshOrAdd(key K, constructor func() (V, bool)) (value V, updated bool, ok bool) {
|
||||
hash := lru.hash(key)
|
||||
shard := (hash >> 16) & lru.mask
|
||||
|
||||
lru.mus[shard].Lock()
|
||||
value, updated = lru.lrus[shard].getAndRefreshOrAdd(hash, key, constructor)
|
||||
value, updated, ok = lru.lrus[shard].getAndRefreshOrAdd(hash, key, constructor)
|
||||
lru.mus[shard].Unlock()
|
||||
|
||||
if !updated && ok {
|
||||
lru.PurgeExpired()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -121,11 +121,14 @@ func (lru *SyncedLRU[K, V]) GetAndRefresh(key K) (value V, ok bool) {
|
|||
return
|
||||
}
|
||||
|
||||
func (lru *SyncedLRU[K, V]) GetAndRefreshOrAdd(key K, constructor func() (V, bool)) (value V, updated bool) {
|
||||
func (lru *SyncedLRU[K, V]) GetAndRefreshOrAdd(key K, constructor func() (V, bool)) (value V, updated bool, ok bool) {
|
||||
hash := lru.lru.hash(key)
|
||||
|
||||
lru.mu.Lock()
|
||||
value, updated = lru.lru.getAndRefreshOrAdd(hash, key, constructor)
|
||||
value, updated, ok = lru.lru.getAndRefreshOrAdd(hash, key, constructor)
|
||||
if !updated && ok {
|
||||
lru.lru.PurgeExpired()
|
||||
}
|
||||
lru.mu.Unlock()
|
||||
|
||||
return
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue