gdbclient/internal/graphsonv3/resultfuture.go (58 lines of code) (raw):
/*
* (C) 2019-present Alibaba Group Holding Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/**
* @author : Liu Jianping
* @date : 2019/11/27
*/
package graphsonv3
import (
"sync/atomic"
"time"
)
type ResponseFuture struct {
originalRequest *Request
response *Response
signalChan chan struct{}
isCompleted uint32
_callback func() bool
}
func NewResponseFuture(request *Request, cb func() bool) *ResponseFuture {
return &ResponseFuture{
originalRequest: request,
signalChan: make(chan struct{}, 1),
isCompleted: 0,
_callback: cb}
}
func (r *ResponseFuture) Complete(response *Response) {
if atomic.CompareAndSwapUint32(&r.isCompleted, 0, 1) {
defer close(r.signalChan)
if response != nil {
r.response = response
}
_ = r._callback != nil && r._callback()
r.signalChan <- struct{}{}
}
}
func (r *ResponseFuture) Request() *Request {
return r.originalRequest
}
func (r *ResponseFuture) IsCompleted() bool {
return atomic.LoadUint32(&r.isCompleted) == 1
}
func (r *ResponseFuture) FixResponse(fn func(response *Response)) {
if r.response == nil {
r.response = &Response{RequestID: r.originalRequest.RequestID}
}
fn(r.response)
}
func (r *ResponseFuture) Get() *Response {
if atomic.LoadUint32(&r.isCompleted) == 0 {
<-r.signalChan
}
return r.response
}
func (r *ResponseFuture) GetOrTimeout(timeout time.Duration) (*Response, bool) {
if atomic.LoadUint32(&r.isCompleted) == 1 {
return r.response, false
}
select {
case <-time.After(timeout):
return nil, true
case <-r.signalChan:
return r.response, false
}
}