forked from rsocket/rsocket-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChannelRequester.cpp
More file actions
134 lines (116 loc) · 3.38 KB
/
ChannelRequester.cpp
File metadata and controls
134 lines (116 loc) · 3.38 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2004-present Facebook. All Rights Reserved.
#include "rsocket/statemachine/ChannelRequester.h"
namespace rsocket {
using namespace yarpl;
using namespace yarpl::flowable;
void ChannelRequester::onSubscribe(
Reference<Subscription> subscription) noexcept {
CHECK(!requested_);
publisherSubscribe(std::move(subscription));
}
void ChannelRequester::onNext(Payload request) noexcept {
if (!requested_) {
requested_ = true;
size_t initialN =
initialResponseAllowance_.consumeUpTo(Frame_REQUEST_N::kMaxRequestN);
size_t remainingN = initialResponseAllowance_.consumeAll();
// Send as much as possible with the initial request.
CHECK_GE(Frame_REQUEST_N::kMaxRequestN, initialN);
newStream(
StreamType::CHANNEL,
static_cast<uint32_t>(initialN),
std::move(request),
false);
// We must inform ConsumerBase about an implicit allowance we have
// requested from the remote end.
ConsumerBase::addImplicitAllowance(initialN);
// Pump the remaining allowance into the ConsumerBase _after_ sending the
// initial request.
if (remainingN) {
ConsumerBase::generateRequest(remainingN);
}
return;
}
checkPublisherOnNext();
if (!publisherClosed()) {
writePayload(std::move(request), false);
}
}
// TODO: consolidate code in onCompleteImpl, onErrorImpl, cancelImpl
void ChannelRequester::onComplete() noexcept {
if (!requested_) {
closeStream(StreamCompletionSignal::CANCEL);
return;
}
if (!publisherClosed()) {
publisherComplete();
completeStream();
tryCompleteChannel();
}
}
void ChannelRequester::onError(folly::exception_wrapper ex) noexcept {
if (!requested_) {
closeStream(StreamCompletionSignal::CANCEL);
return;
}
if (!publisherClosed()) {
publisherComplete();
applicationError(ex.get_exception()->what());
tryCompleteChannel();
}
}
void ChannelRequester::request(int64_t n) noexcept {
if (!requested_) {
// The initial request has not been sent out yet, hence we must accumulate
// the unsynchronised allowance, portion of which will be sent out with
// the initial request frame, and the rest will be dispatched via
// ConsumerBase:request (ultimately by sending REQUEST_N frames).
initialResponseAllowance_.add(n);
return;
}
ConsumerBase::generateRequest(n);
}
void ChannelRequester::cancel() noexcept {
if (!requested_) {
closeStream(StreamCompletionSignal::CANCEL);
return;
}
cancelConsumer();
cancelStream();
tryCompleteChannel();
}
void ChannelRequester::endStream(StreamCompletionSignal signal) {
terminatePublisher();
ConsumerBase::endStream(signal);
}
void ChannelRequester::tryCompleteChannel() {
if (publisherClosed() && consumerClosed()) {
closeStream(StreamCompletionSignal::COMPLETE);
}
}
void ChannelRequester::handlePayload(
Payload&& payload,
bool complete,
bool next) {
CHECK(requested_);
processPayload(std::move(payload), next);
if (complete) {
completeConsumer();
tryCompleteChannel();
}
}
void ChannelRequester::handleError(folly::exception_wrapper ex) {
CHECK(requested_);
errorConsumer(std::move(ex));
tryCompleteChannel();
}
void ChannelRequester::handleRequestN(uint32_t n) {
CHECK(requested_);
PublisherBase::processRequestN(n);
}
void ChannelRequester::handleCancel() {
CHECK(requested_);
publisherComplete();
tryCompleteChannel();
}
}