aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/grpcpp/impl/codegen/call_op_set.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/grpcpp/impl/codegen/call_op_set.h')
-rw-r--r--include/grpcpp/impl/codegen/call_op_set.h66
1 files changed, 59 insertions, 7 deletions
diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h
index b4c34a01c9..1c75560c04 100644
--- a/include/grpcpp/impl/codegen/call_op_set.h
+++ b/include/grpcpp/impl/codegen/call_op_set.h
@@ -303,6 +303,18 @@ class CallOpSendMessage {
template <class M>
Status SendMessage(const M& message) GRPC_MUST_USE_RESULT;
+ /// Send \a message using \a options for the write. The \a options are cleared
+ /// after use. This form of SendMessage allows gRPC to reference \a message
+ /// beyond the lifetime of SendMessage.
+ template <class M>
+ Status SendMessagePtr(const M* message,
+ WriteOptions options) GRPC_MUST_USE_RESULT;
+
+ /// This form of SendMessage allows gRPC to reference \a message beyond the
+ /// lifetime of SendMessage.
+ template <class M>
+ Status SendMessagePtr(const M* message) GRPC_MUST_USE_RESULT;
+
protected:
void AddOp(grpc_op* ops, size_t* nops) {
if (!send_buf_.Valid() || hijacked_) return;
@@ -314,25 +326,47 @@ class CallOpSendMessage {
// Flags are per-message: clear them after use.
write_options_.Clear();
}
- void FinishOp(bool* status) { send_buf_.Clear(); }
+ void FinishOp(bool* status) {
+ if (!send_buf_.Valid()) {
+ return;
+ }
+ if (hijacked_ && failed_send_) {
+ // Hijacking interceptor failed this Op
+ *status = false;
+ } else if (!*status) {
+ // This Op was passed down to core and the Op failed
+ failed_send_ = true;
+ }
+ }
void SetInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
if (!send_buf_.Valid()) return;
interceptor_methods->AddInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_MESSAGE);
- interceptor_methods->SetSendMessage(&send_buf_);
+ interceptor_methods->SetSendMessage(&send_buf_, msg_, &failed_send_);
}
void SetFinishInterceptionHookPoint(
- InterceptorBatchMethodsImpl* interceptor_methods) {}
+ InterceptorBatchMethodsImpl* interceptor_methods) {
+ if (send_buf_.Valid()) {
+ interceptor_methods->AddInterceptionHookPoint(
+ experimental::InterceptionHookPoints::POST_SEND_MESSAGE);
+ }
+ send_buf_.Clear();
+ // The contents of the SendMessage value that was previously set
+ // has had its references stolen by core's operations
+ interceptor_methods->SetSendMessage(nullptr, nullptr, &failed_send_);
+ }
void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
hijacked_ = true;
}
private:
+ const void* msg_ = nullptr; // The original non-serialized message
bool hijacked_ = false;
+ bool failed_send_ = false;
ByteBuffer send_buf_;
WriteOptions write_options_;
};
@@ -358,6 +392,19 @@ Status CallOpSendMessage::SendMessage(const M& message) {
return SendMessage(message, WriteOptions());
}
+template <class M>
+Status CallOpSendMessage::SendMessagePtr(const M* message,
+ WriteOptions options) {
+ msg_ = message;
+ return SendMessage(*message, options);
+}
+
+template <class M>
+Status CallOpSendMessage::SendMessagePtr(const M* message) {
+ msg_ = message;
+ return SendMessage(*message, WriteOptions());
+}
+
template <class R>
class CallOpRecvMessage {
public:
@@ -406,14 +453,16 @@ class CallOpRecvMessage {
void SetInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
- interceptor_methods->SetRecvMessage(message_);
+ if (message_ == nullptr) return;
+ interceptor_methods->SetRecvMessage(message_, &got_message);
}
void SetFinishInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
- if (!got_message) return;
+ if (message_ == nullptr) return;
interceptor_methods->AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
+ if (!got_message) interceptor_methods->SetRecvMessage(nullptr, nullptr);
}
void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
hijacked_ = true;
@@ -501,20 +550,23 @@ class CallOpGenericRecvMessage {
void SetInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
- interceptor_methods->SetRecvMessage(message_);
+ if (!deserialize_) return;
+ interceptor_methods->SetRecvMessage(message_, &got_message);
}
void SetFinishInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
- if (!got_message) return;
+ if (!deserialize_) return;
interceptor_methods->AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
+ if (!got_message) interceptor_methods->SetRecvMessage(nullptr, nullptr);
}
void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
hijacked_ = true;
if (!deserialize_) return;
interceptor_methods->AddInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_RECV_MESSAGE);
+ got_message = true;
}
private: