github.com/searKing/golang/go@v1.2.117/sync/lru_pool.persist_resource.go (about) 1 // Copyright 2021 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package sync 6 7 import ( 8 "sync" 9 "time" 10 ) 11 12 // PersistResource wraps a resource, usually a persistent one 13 // (but may be used for non-keep-alive requests as well) 14 type PersistResource struct { 15 t *LruPool 16 cacheKey targetKey 17 object any 18 19 // Both guarded by LruPool.idleMu: 20 idleAt time.Time // time it last become idle 21 idleTimer *time.Timer // holding an AfterFunc to close it 22 23 mu sync.Mutex // guards following fields 24 closed error // set non-nil when resource is closed, before closech is closed 25 broken bool // an error has happened on this resource; marked broken so it's not reused. 26 reused bool // whether resource has had successful request/response and is being reused. 27 } // isBroken reports whether this resource is in a known broken state. 28 29 func (pc *PersistResource) Get() any { 30 if pc == nil { 31 return nil 32 } 33 return pc.object 34 } 35 36 func (pc *PersistResource) Put() { 37 if pc == nil { 38 return 39 } 40 pc.t.putOrCloseIdleResource(pc) 41 } 42 43 func (pc *PersistResource) isBroken() bool { 44 pc.mu.Lock() 45 b := pc.closed != nil 46 pc.mu.Unlock() 47 return b 48 } 49 50 // markReused marks this resource as having been successfully used for a 51 // request and response. 52 func (pc *PersistResource) markReused() { 53 pc.mu.Lock() 54 pc.reused = true 55 pc.mu.Unlock() 56 } 57 58 // close closes the underlying resource and closes 59 // the pc.closech channel. 60 // 61 // The provided err is only for testing and debugging; in normal 62 // circumstances it should never be seen by users. 63 func (pc *PersistResource) close(err error) { 64 pc.mu.Lock() 65 defer pc.mu.Unlock() 66 pc.closeLocked(err) 67 } 68 69 func (pc *PersistResource) closeLocked(err error) { 70 if err == nil { 71 panic("nil error") 72 } 73 pc.broken = true 74 if pc.closed == nil { 75 pc.closed = err 76 pc.t.decResourcesPerBucket(pc.cacheKey) 77 } 78 } 79 80 // closeResourceIfStillIdle closes the resource if it's still sitting idle. 81 // This is what's called by the PersistResource's idleTimer, and is run in its 82 // own goroutine. 83 func (pc *PersistResource) closeResourceIfStillIdle() { 84 t := pc.t 85 t.idleMu.Lock() 86 defer t.idleMu.Unlock() 87 if _, ok := t.idleLRU.m[pc]; !ok { 88 // Not idle. 89 return 90 } 91 t.removeIdleResourceLocked(pc) 92 pc.close(errIdleResourceTimeout) 93 }