2017-10-31 09:25:44 +00:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"sync/atomic"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var callStatePool sync.Pool
|
|
|
|
var zeroTime time.Time
|
|
|
|
|
|
|
|
type CallState struct {
|
2017-11-01 08:43:20 +00:00
|
|
|
ID uint64
|
2017-10-31 09:25:44 +00:00
|
|
|
Method string
|
|
|
|
Args interface{}
|
|
|
|
Result interface{}
|
|
|
|
Error error
|
|
|
|
DoneChan chan *CallState
|
|
|
|
|
2017-11-02 06:39:30 +00:00
|
|
|
hasResponse bool
|
|
|
|
canceled uint32
|
2017-10-31 09:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (cs *CallState) done() {
|
|
|
|
select {
|
|
|
|
case cs.DoneChan <- cs:
|
|
|
|
// 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 (cs *CallState) Cancel() {
|
|
|
|
atomic.StoreUint32(&cs.canceled, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cs *CallState) IsCanceled() bool {
|
|
|
|
return atomic.LoadUint32(&cs.canceled) != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func retainCallState() *CallState {
|
|
|
|
v := callStatePool.Get()
|
|
|
|
if v == nil {
|
|
|
|
return &CallState{}
|
|
|
|
}
|
|
|
|
return v.(*CallState)
|
|
|
|
}
|
|
|
|
|
|
|
|
func releaseCallState(cs *CallState) {
|
|
|
|
cs.Method = ""
|
|
|
|
cs.Args = nil
|
|
|
|
cs.Result = nil
|
|
|
|
cs.Error = nil
|
|
|
|
cs.DoneChan = nil
|
|
|
|
|
|
|
|
callStatePool.Put(cs)
|
|
|
|
}
|