package client import ( "sync" "sync/atomic" "time" ) var zeroTime time.Time type RequestState struct { ID uint64 Method string Args interface{} Result interface{} Error error DoneChan chan *RequestState hasResponse bool canceled uint32 } func (rs *RequestState) Done() { select { case rs.DoneChan <- rs: // ok default: // We don't want to block here. It is the caller's responsibility to make // sure the channel has enough buffer space. See comment in Go(). // if debugLog { // log.Println("rpc: discarding Call reply due to insufficient Done chan capacity") // } } } // Cancel cancels async call. // // Canceled call isn't sent to the server unless it is already sent there. // Canceled call may successfully complete if it has been already sent // to the server before Cancel call. // // It is safe calling this function multiple times from concurrently // running goroutines. func (rs *RequestState) Cancel() { atomic.StoreUint32(&rs.canceled, 1) } func (rs *RequestState) IsCanceled() bool { return atomic.LoadUint32(&rs.canceled) != 0 } var requestStatePool sync.Pool func retainRequestState() *RequestState { v := requestStatePool.Get() if v == nil { return &RequestState{} } return v.(*RequestState) } func releaseCallState(rs *RequestState) { rs.Method = "" rs.Args = nil rs.Result = nil rs.Error = nil rs.DoneChan = nil requestStatePool.Put(rs) }