-
-
Notifications
You must be signed in to change notification settings - Fork 111
/
request.go
99 lines (87 loc) · 2.32 KB
/
request.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package capnp
import (
"context"
"errors"
)
// A Request is a method call to be sent. Create one with NewReqeust, and send it with
// Request.Send().
type Request struct {
method Method
args Struct
client Client
releaseResponse ReleaseFunc
future *Future
}
// NewRequest creates a new request calling the specified method on the specified client.
// argsSize is the size of the arguments struct.
func NewRequest(client Client, method Method, argsSize ObjectSize) (*Request, error) {
_, seg := NewMultiSegmentMessage(nil)
args, err := NewStruct(seg, argsSize)
if err != nil {
return nil, err
}
return &Request{
method: method,
args: args,
client: client,
}, nil
}
// Args returns the arguments struct for this request. The arguments must not
// be accessed after the request is sent.
func (r *Request) Args() Struct {
return r.args
}
func (r *Request) getSend() Send {
return Send{
Method: r.method,
PlaceArgs: func(args Struct) error {
err := args.CopyFrom(r.args)
r.releaseArgs()
return err
},
ArgsSize: r.args.Size(),
}
}
// Send sends the request, returning a future for its results.
func (r *Request) Send(ctx context.Context) *Future {
if r.future != nil {
return ErrorAnswer(r.method, errors.New("sent the same request twice")).Future()
}
ans, rel := r.client.SendCall(ctx, r.getSend())
r.releaseResponse = rel
r.future = ans.Future()
return r.future
}
// SendStream is to send as Client.SendStreamCall is to Client.SendCall
func (r *Request) SendStream(ctx context.Context) error {
if r.future != nil {
return errors.New("sent the same request twice")
}
return r.client.SendStreamCall(ctx, r.getSend())
}
// Future returns a future for the requests results. Returns nil if
// called before the request is sent.
func (r *Request) Future() *Future {
return r.future
}
// Release resources associated with the request. In particular:
//
// - Release the arguments if they have not yet been released.
// - If the request has been sent, wait for the result and release
// the results.
func (r *Request) Release() {
r.releaseArgs()
rel := r.releaseResponse
if rel != nil {
r.releaseResponse = nil
r.future = nil
rel()
}
}
func (r *Request) releaseArgs() {
if !r.args.IsValid() {
msg := r.args.Message()
r.args = Struct{}
msg.Release()
}
}