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  }