71 lines
1.4 KiB
Go
71 lines
1.4 KiB
Go
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)
|
|
}
|