97 lines
1.5 KiB
Go
97 lines
1.5 KiB
Go
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) {
|
|
if nil == err {
|
|
return
|
|
}
|
|
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)
|
|
}
|