package client import ( "sync" "sync/atomic" "time" ) type requestState struct { id uint64 method string params []interface{} result interface{} clientError *Error doneChan chan *requestState canceled atomic.Value } func (rs *requestState) done() { select { case rs.doneChan <- rs: default: } } func (rs *requestState) cancel() { rs.canceled.Store(true) } func (rs *requestState) isCanceled() bool { v := rs.canceled.Load() if nil == v { return false } vv := v.(bool) return vv } func (rs *requestState) setError(err error) { rs.clientError = newError(rs.method, rs.params, err) } var requestStatePool sync.Pool func retainRequestState() *requestState { v := requestStatePool.Get() if v == nil { return &requestState{} } return v.(*requestState) } func releaseRequestState(rs *requestState) { rs.id = 0 rs.method = "" rs.params = nil rs.result = nil rs.clientError = nil rs.doneChan = nil rs.canceled.Store(false) requestStatePool.Put(rs) } var timerPool sync.Pool func retainTimer(timeout time.Duration) *time.Timer { tv := timerPool.Get() if tv == nil { return time.NewTimer(timeout) } t := tv.(*time.Timer) if t.Reset(timeout) { panic("Client: Active timer trapped into retainTimer()") } return t } func releaseTimer(t *time.Timer) { if !t.Stop() { // Collect possibly added time from the channel // if timer has been stopped and nobody collected its' value. select { case <-t.C: default: } } timerPool.Put(t) }