|
|
|
@ -79,6 +79,9 @@ class ReaderInterface { |
|
|
|
|
public: |
|
|
|
|
virtual ~ReaderInterface() {} |
|
|
|
|
|
|
|
|
|
/// Upper bound on the next message size available for reading on this stream
|
|
|
|
|
virtual bool NextMessageSize(uint32_t* sz) = 0; |
|
|
|
|
|
|
|
|
|
/// Blocking read a message and parse to \a msg. Returns \a true on success.
|
|
|
|
|
/// This is thread-safe with respect to \a Write or \WritesDone methods on
|
|
|
|
|
/// the same stream. It should not be called concurrently with another \a
|
|
|
|
@ -157,6 +160,11 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface<R> { |
|
|
|
|
cq_.Pluck(&ops); /// status ignored
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool NextMessageSize(uint32_t* sz) GRPC_OVERRIDE { |
|
|
|
|
*sz = call_.max_message_size(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Read(R* msg) GRPC_OVERRIDE { |
|
|
|
|
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops; |
|
|
|
|
if (!context_->initial_metadata_received_) { |
|
|
|
@ -302,6 +310,11 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> { |
|
|
|
|
cq_.Pluck(&ops); // status ignored
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool NextMessageSize(uint32_t* sz) GRPC_OVERRIDE { |
|
|
|
|
*sz = call_.max_message_size(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Read(R* msg) GRPC_OVERRIDE { |
|
|
|
|
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops; |
|
|
|
|
if (!context_->initial_metadata_received_) { |
|
|
|
@ -369,6 +382,11 @@ class ServerReader GRPC_FINAL : public ServerReaderInterface<R> { |
|
|
|
|
call_->cq()->Pluck(&ops); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool NextMessageSize(uint32_t* sz) GRPC_OVERRIDE { |
|
|
|
|
*sz = call_->max_message_size(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Read(R* msg) GRPC_OVERRIDE { |
|
|
|
|
CallOpSet<CallOpRecvMessage<R>> ops; |
|
|
|
|
ops.RecvMessage(msg); |
|
|
|
@ -434,12 +452,15 @@ class ServerReaderWriterInterface : public ServerStreamingInterface, |
|
|
|
|
public WriterInterface<W>, |
|
|
|
|
public ReaderInterface<R> {}; |
|
|
|
|
|
|
|
|
|
// Actual implementation of bi-directional streaming
|
|
|
|
|
namespace internal { |
|
|
|
|
template <class W, class R> |
|
|
|
|
class ServerReaderWriter GRPC_FINAL : public ServerReaderWriterInterface<W, R> { |
|
|
|
|
class ServerReaderWriterBody GRPC_FINAL { |
|
|
|
|
public: |
|
|
|
|
ServerReaderWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {} |
|
|
|
|
ServerReaderWriterBody(Call* call, ServerContext* ctx) |
|
|
|
|
: call_(call), ctx_(ctx) {} |
|
|
|
|
|
|
|
|
|
void SendInitialMetadata() GRPC_OVERRIDE { |
|
|
|
|
void SendInitialMetadata() { |
|
|
|
|
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); |
|
|
|
|
|
|
|
|
|
CallOpSet<CallOpSendInitialMetadata> ops; |
|
|
|
@ -453,15 +474,19 @@ class ServerReaderWriter GRPC_FINAL : public ServerReaderWriterInterface<W, R> { |
|
|
|
|
call_->cq()->Pluck(&ops); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Read(R* msg) GRPC_OVERRIDE { |
|
|
|
|
bool NextMessageSize(uint32_t* sz) { |
|
|
|
|
*sz = call_->max_message_size(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Read(R* msg) { |
|
|
|
|
CallOpSet<CallOpRecvMessage<R>> ops; |
|
|
|
|
ops.RecvMessage(msg); |
|
|
|
|
call_->PerformOps(&ops); |
|
|
|
|
return call_->cq()->Pluck(&ops) && ops.got_message; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
using WriterInterface<W>::Write; |
|
|
|
|
bool Write(const W& msg, const WriteOptions& options) GRPC_OVERRIDE { |
|
|
|
|
bool Write(const W& msg, const WriteOptions& options) { |
|
|
|
|
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> ops; |
|
|
|
|
if (!ops.SendMessage(msg, options).ok()) { |
|
|
|
|
return false; |
|
|
|
@ -482,6 +507,76 @@ class ServerReaderWriter GRPC_FINAL : public ServerReaderWriterInterface<W, R> { |
|
|
|
|
Call* const call_; |
|
|
|
|
ServerContext* const ctx_; |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// class to represent the user API for a bidirectional streaming call
|
|
|
|
|
template <class W, class R> |
|
|
|
|
class ServerReaderWriter GRPC_FINAL : public ServerReaderWriterInterface<W, R> { |
|
|
|
|
public: |
|
|
|
|
ServerReaderWriter(Call* call, ServerContext* ctx) : body_(call, ctx) {} |
|
|
|
|
|
|
|
|
|
void SendInitialMetadata() GRPC_OVERRIDE { body_.SendInitialMetadata(); } |
|
|
|
|
|
|
|
|
|
bool NextMessageSize(uint32_t* sz) GRPC_OVERRIDE { |
|
|
|
|
return body_.NextMessageSize(sz); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Read(R* msg) GRPC_OVERRIDE { return body_.Read(msg); } |
|
|
|
|
|
|
|
|
|
using WriterInterface<W>::Write; |
|
|
|
|
bool Write(const W& msg, const WriteOptions& options) GRPC_OVERRIDE { |
|
|
|
|
return body_.Write(msg, options); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
internal::ServerReaderWriterBody<W, R> body_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/// A class to represent a flow-controlled unary call. This is something
|
|
|
|
|
/// of a hybrid between conventional unary and streaming. This is invoked
|
|
|
|
|
/// through a unary call on the client side, but the server responds to it
|
|
|
|
|
/// as though it were a single-ping-pong streaming call. The server can use
|
|
|
|
|
/// the \a NextMessageSize method to determine an upper-bound on the size of
|
|
|
|
|
/// the message.
|
|
|
|
|
/// A key difference relative to streaming: ServerUnaryStreamer
|
|
|
|
|
/// must have exactly 1 Read and exactly 1 Write, in that order, to function
|
|
|
|
|
/// correctly. Otherwise, the RPC is in error.
|
|
|
|
|
template <class RequestType, class ResponseType> |
|
|
|
|
class ServerUnaryStreamer GRPC_FINAL |
|
|
|
|
: public ServerReaderWriterInterface<ResponseType, RequestType> { |
|
|
|
|
public: |
|
|
|
|
ServerUnaryStreamer(Call* call, ServerContext* ctx) |
|
|
|
|
: body_(call, ctx), read_done_(false), write_done_(false) {} |
|
|
|
|
|
|
|
|
|
void SendInitialMetadata() GRPC_OVERRIDE { body_.SendInitialMetadata(); } |
|
|
|
|
|
|
|
|
|
bool NextMessageSize(uint32_t* sz) GRPC_OVERRIDE { |
|
|
|
|
return body_.NextMessageSize(sz); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Read(RequestType* request) GRPC_OVERRIDE { |
|
|
|
|
if (read_done_) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
read_done_ = true; |
|
|
|
|
return body_.Read(request); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
using WriterInterface<ResponseType>::Write; |
|
|
|
|
bool Write(const ResponseType& response, |
|
|
|
|
const WriteOptions& options) GRPC_OVERRIDE { |
|
|
|
|
if (write_done_ || !read_done_) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
write_done_ = true; |
|
|
|
|
return body_.Write(response, options); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
internal::ServerReaderWriterBody<ResponseType, RequestType> body_; |
|
|
|
|
bool read_done_; |
|
|
|
|
bool write_done_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
} // namespace grpc
|
|
|
|
|
|
|
|
|
|