github.com/abemedia/go-don@v0.2.2-0.20240329015135-be88e32bb73b/pool.go (about)

     1  package don
     2  
     3  import (
     4  	"reflect"
     5  	"sync"
     6  )
     7  
     8  type pool[T any] interface {
     9  	Get() *T
    10  	Put(x *T)
    11  }
    12  
    13  type requestPool[T any] struct {
    14  	pool  sync.Pool
    15  	reset func(*T)
    16  }
    17  
    18  func newRequestPool[T any](zero T) pool[T] {
    19  	typ := reflect.TypeOf(zero)
    20  	if typ == nil {
    21  		return &fakePool[T]{&zero}
    22  	}
    23  
    24  	p := &requestPool[T]{}
    25  
    26  	if typ.Kind() != reflect.Pointer {
    27  		p.pool.New = func() any {
    28  			return new(T)
    29  		}
    30  		p.reset = func(v *T) {
    31  			*v = zero
    32  		}
    33  	} else {
    34  		rtype := dataOf(typ)
    35  		elem := typ.Elem()
    36  		elemrtype := dataOf(elem)
    37  		zero := dataOf(reflect.New(elem).Elem().Interface())
    38  
    39  		p.pool.New = func() any {
    40  			v := packEface(rtype, unsafe_New(elemrtype)).(T) //nolint:forcetypeassert
    41  			return &v
    42  		}
    43  		p.reset = func(v *T) {
    44  			typedmemmove(elemrtype, dataOf(*v), zero)
    45  		}
    46  	}
    47  
    48  	return p
    49  }
    50  
    51  func (p *requestPool[T]) Get() *T {
    52  	return p.pool.Get().(*T) //nolint:forcetypeassert
    53  }
    54  
    55  func (p *requestPool[T]) Put(v *T) {
    56  	p.reset(v)
    57  	p.pool.Put(v)
    58  }
    59  
    60  type fakePool[T any] struct{ v *T }
    61  
    62  func (p *fakePool[T]) Get() *T { return p.v }
    63  
    64  func (p *fakePool[T]) Put(*T) {}