OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * |
| 3 * Copyright 2015-2016, Google Inc. |
| 4 * All rights reserved. |
| 5 * |
| 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions are |
| 8 * met: |
| 9 * |
| 10 * * Redistributions of source code must retain the above copyright |
| 11 * notice, this list of conditions and the following disclaimer. |
| 12 * * Redistributions in binary form must reproduce the above |
| 13 * copyright notice, this list of conditions and the following disclaimer |
| 14 * in the documentation and/or other materials provided with the |
| 15 * distribution. |
| 16 * * Neither the name of Google Inc. nor the names of its |
| 17 * contributors may be used to endorse or promote products derived from |
| 18 * this software without specific prior written permission. |
| 19 * |
| 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 * |
| 32 */ |
| 33 |
| 34 #ifndef GRPCXX_IMPL_CODEGEN_CALL_H |
| 35 #define GRPCXX_IMPL_CODEGEN_CALL_H |
| 36 |
| 37 #include <functional> |
| 38 #include <memory> |
| 39 #include <map> |
| 40 #include <cstring> |
| 41 |
| 42 #include <grpc/impl/codegen/alloc.h> |
| 43 #include <grpc/impl/codegen/grpc_types.h> |
| 44 #include <grpc++/impl/codegen/client_context.h> |
| 45 #include <grpc++/impl/codegen/call_hook.h> |
| 46 #include <grpc++/impl/codegen/completion_queue_tag.h> |
| 47 #include <grpc++/impl/codegen/serialization_traits.h> |
| 48 #include <grpc++/impl/codegen/config.h> |
| 49 #include <grpc++/impl/codegen/status.h> |
| 50 |
| 51 struct grpc_byte_buffer; |
| 52 |
| 53 namespace grpc { |
| 54 |
| 55 class ByteBuffer; |
| 56 class Call; |
| 57 class CallHook; |
| 58 class CompletionQueue; |
| 59 |
| 60 void FillMetadataMap( |
| 61 grpc_metadata_array* arr, |
| 62 std::multimap<grpc::string_ref, grpc::string_ref>* metadata); |
| 63 grpc_metadata* FillMetadataArray( |
| 64 const std::multimap<grpc::string, grpc::string>& metadata); |
| 65 |
| 66 /// Per-message write options. |
| 67 class WriteOptions { |
| 68 public: |
| 69 WriteOptions() : flags_(0) {} |
| 70 WriteOptions(const WriteOptions& other) : flags_(other.flags_) {} |
| 71 |
| 72 /// Clear all flags. |
| 73 inline void Clear() { flags_ = 0; } |
| 74 |
| 75 /// Returns raw flags bitset. |
| 76 inline uint32_t flags() const { return flags_; } |
| 77 |
| 78 /// Sets flag for the disabling of compression for the next message write. |
| 79 /// |
| 80 /// \sa GRPC_WRITE_NO_COMPRESS |
| 81 inline WriteOptions& set_no_compression() { |
| 82 SetBit(GRPC_WRITE_NO_COMPRESS); |
| 83 return *this; |
| 84 } |
| 85 |
| 86 /// Clears flag for the disabling of compression for the next message write. |
| 87 /// |
| 88 /// \sa GRPC_WRITE_NO_COMPRESS |
| 89 inline WriteOptions& clear_no_compression() { |
| 90 ClearBit(GRPC_WRITE_NO_COMPRESS); |
| 91 return *this; |
| 92 } |
| 93 |
| 94 /// Get value for the flag indicating whether compression for the next |
| 95 /// message write is forcefully disabled. |
| 96 /// |
| 97 /// \sa GRPC_WRITE_NO_COMPRESS |
| 98 inline bool get_no_compression() const { |
| 99 return GetBit(GRPC_WRITE_NO_COMPRESS); |
| 100 } |
| 101 |
| 102 /// Sets flag indicating that the write may be buffered and need not go out on |
| 103 /// the wire immediately. |
| 104 /// |
| 105 /// \sa GRPC_WRITE_BUFFER_HINT |
| 106 inline WriteOptions& set_buffer_hint() { |
| 107 SetBit(GRPC_WRITE_BUFFER_HINT); |
| 108 return *this; |
| 109 } |
| 110 |
| 111 /// Clears flag indicating that the write may be buffered and need not go out |
| 112 /// on the wire immediately. |
| 113 /// |
| 114 /// \sa GRPC_WRITE_BUFFER_HINT |
| 115 inline WriteOptions& clear_buffer_hint() { |
| 116 ClearBit(GRPC_WRITE_BUFFER_HINT); |
| 117 return *this; |
| 118 } |
| 119 |
| 120 /// Get value for the flag indicating that the write may be buffered and need |
| 121 /// not go out on the wire immediately. |
| 122 /// |
| 123 /// \sa GRPC_WRITE_BUFFER_HINT |
| 124 inline bool get_buffer_hint() const { return GetBit(GRPC_WRITE_BUFFER_HINT); } |
| 125 |
| 126 WriteOptions& operator=(const WriteOptions& rhs) { |
| 127 flags_ = rhs.flags_; |
| 128 return *this; |
| 129 } |
| 130 |
| 131 private: |
| 132 void SetBit(const uint32_t mask) { flags_ |= mask; } |
| 133 |
| 134 void ClearBit(const uint32_t mask) { flags_ &= ~mask; } |
| 135 |
| 136 bool GetBit(const uint32_t mask) const { return (flags_ & mask) != 0; } |
| 137 |
| 138 uint32_t flags_; |
| 139 }; |
| 140 |
| 141 /// Default argument for CallOpSet. I is unused by the class, but can be |
| 142 /// used for generating multiple names for the same thing. |
| 143 template <int I> |
| 144 class CallNoOp { |
| 145 protected: |
| 146 void AddOp(grpc_op* ops, size_t* nops) {} |
| 147 void FinishOp(bool* status, int max_message_size) {} |
| 148 }; |
| 149 |
| 150 class CallOpSendInitialMetadata { |
| 151 public: |
| 152 CallOpSendInitialMetadata() : send_(false) {} |
| 153 |
| 154 void SendInitialMetadata( |
| 155 const std::multimap<grpc::string, grpc::string>& metadata) { |
| 156 send_ = true; |
| 157 initial_metadata_count_ = metadata.size(); |
| 158 initial_metadata_ = FillMetadataArray(metadata); |
| 159 } |
| 160 |
| 161 protected: |
| 162 void AddOp(grpc_op* ops, size_t* nops) { |
| 163 if (!send_) return; |
| 164 grpc_op* op = &ops[(*nops)++]; |
| 165 op->op = GRPC_OP_SEND_INITIAL_METADATA; |
| 166 op->flags = 0; |
| 167 op->reserved = NULL; |
| 168 op->data.send_initial_metadata.count = initial_metadata_count_; |
| 169 op->data.send_initial_metadata.metadata = initial_metadata_; |
| 170 } |
| 171 void FinishOp(bool* status, int max_message_size) { |
| 172 if (!send_) return; |
| 173 gpr_free(initial_metadata_); |
| 174 send_ = false; |
| 175 } |
| 176 |
| 177 bool send_; |
| 178 size_t initial_metadata_count_; |
| 179 grpc_metadata* initial_metadata_; |
| 180 }; |
| 181 |
| 182 class CallOpSendMessage { |
| 183 public: |
| 184 CallOpSendMessage() : send_buf_(nullptr), own_buf_(false) {} |
| 185 |
| 186 /// Send \a message using \a options for the write. The \a options are cleared |
| 187 /// after use. |
| 188 template <class M> |
| 189 Status SendMessage(const M& message, |
| 190 const WriteOptions& options) GRPC_MUST_USE_RESULT; |
| 191 |
| 192 template <class M> |
| 193 Status SendMessage(const M& message) GRPC_MUST_USE_RESULT; |
| 194 |
| 195 protected: |
| 196 void AddOp(grpc_op* ops, size_t* nops) { |
| 197 if (send_buf_ == nullptr) return; |
| 198 grpc_op* op = &ops[(*nops)++]; |
| 199 op->op = GRPC_OP_SEND_MESSAGE; |
| 200 op->flags = write_options_.flags(); |
| 201 op->reserved = NULL; |
| 202 op->data.send_message = send_buf_; |
| 203 // Flags are per-message: clear them after use. |
| 204 write_options_.Clear(); |
| 205 } |
| 206 void FinishOp(bool* status, int max_message_size) { |
| 207 if (own_buf_) grpc_byte_buffer_destroy(send_buf_); |
| 208 send_buf_ = nullptr; |
| 209 } |
| 210 |
| 211 private: |
| 212 grpc_byte_buffer* send_buf_; |
| 213 WriteOptions write_options_; |
| 214 bool own_buf_; |
| 215 }; |
| 216 |
| 217 template <class M> |
| 218 Status CallOpSendMessage::SendMessage(const M& message, |
| 219 const WriteOptions& options) { |
| 220 write_options_ = options; |
| 221 return SerializationTraits<M>::Serialize(message, &send_buf_, &own_buf_); |
| 222 } |
| 223 |
| 224 template <class M> |
| 225 Status CallOpSendMessage::SendMessage(const M& message) { |
| 226 return SendMessage(message, WriteOptions()); |
| 227 } |
| 228 |
| 229 template <class R> |
| 230 class CallOpRecvMessage { |
| 231 public: |
| 232 CallOpRecvMessage() : got_message(false), message_(nullptr) {} |
| 233 |
| 234 void RecvMessage(R* message) { message_ = message; } |
| 235 |
| 236 bool got_message; |
| 237 |
| 238 protected: |
| 239 void AddOp(grpc_op* ops, size_t* nops) { |
| 240 if (message_ == nullptr) return; |
| 241 grpc_op* op = &ops[(*nops)++]; |
| 242 op->op = GRPC_OP_RECV_MESSAGE; |
| 243 op->flags = 0; |
| 244 op->reserved = NULL; |
| 245 op->data.recv_message = &recv_buf_; |
| 246 } |
| 247 |
| 248 void FinishOp(bool* status, int max_message_size) { |
| 249 if (message_ == nullptr) return; |
| 250 if (recv_buf_) { |
| 251 if (*status) { |
| 252 got_message = true; |
| 253 *status = SerializationTraits<R>::Deserialize(recv_buf_, message_, |
| 254 max_message_size).ok(); |
| 255 } else { |
| 256 got_message = false; |
| 257 grpc_byte_buffer_destroy(recv_buf_); |
| 258 } |
| 259 } else { |
| 260 got_message = false; |
| 261 *status = false; |
| 262 } |
| 263 message_ = nullptr; |
| 264 } |
| 265 |
| 266 private: |
| 267 R* message_; |
| 268 grpc_byte_buffer* recv_buf_; |
| 269 }; |
| 270 |
| 271 namespace CallOpGenericRecvMessageHelper { |
| 272 class DeserializeFunc { |
| 273 public: |
| 274 virtual Status Deserialize(grpc_byte_buffer* buf, int max_message_size) = 0; |
| 275 virtual ~DeserializeFunc() {} |
| 276 }; |
| 277 |
| 278 template <class R> |
| 279 class DeserializeFuncType GRPC_FINAL : public DeserializeFunc { |
| 280 public: |
| 281 DeserializeFuncType(R* message) : message_(message) {} |
| 282 Status Deserialize(grpc_byte_buffer* buf, |
| 283 int max_message_size) GRPC_OVERRIDE { |
| 284 return SerializationTraits<R>::Deserialize(buf, message_, max_message_size); |
| 285 } |
| 286 |
| 287 ~DeserializeFuncType() override {} |
| 288 |
| 289 private: |
| 290 R* message_; // Not a managed pointer because management is external to this |
| 291 }; |
| 292 } // namespace CallOpGenericRecvMessageHelper |
| 293 |
| 294 class CallOpGenericRecvMessage { |
| 295 public: |
| 296 CallOpGenericRecvMessage() : got_message(false) {} |
| 297 |
| 298 template <class R> |
| 299 void RecvMessage(R* message) { |
| 300 deserialize_.reset( |
| 301 new CallOpGenericRecvMessageHelper::DeserializeFuncType<R>(message)); |
| 302 } |
| 303 |
| 304 bool got_message; |
| 305 |
| 306 protected: |
| 307 void AddOp(grpc_op* ops, size_t* nops) { |
| 308 if (!deserialize_) return; |
| 309 grpc_op* op = &ops[(*nops)++]; |
| 310 op->op = GRPC_OP_RECV_MESSAGE; |
| 311 op->flags = 0; |
| 312 op->reserved = NULL; |
| 313 op->data.recv_message = &recv_buf_; |
| 314 } |
| 315 |
| 316 void FinishOp(bool* status, int max_message_size) { |
| 317 if (!deserialize_) return; |
| 318 if (recv_buf_) { |
| 319 if (*status) { |
| 320 got_message = true; |
| 321 *status = deserialize_->Deserialize(recv_buf_, max_message_size).ok(); |
| 322 } else { |
| 323 got_message = false; |
| 324 grpc_byte_buffer_destroy(recv_buf_); |
| 325 } |
| 326 } else { |
| 327 got_message = false; |
| 328 *status = false; |
| 329 } |
| 330 deserialize_.reset(); |
| 331 } |
| 332 |
| 333 private: |
| 334 std::unique_ptr<CallOpGenericRecvMessageHelper::DeserializeFunc> deserialize_; |
| 335 grpc_byte_buffer* recv_buf_; |
| 336 }; |
| 337 |
| 338 class CallOpClientSendClose { |
| 339 public: |
| 340 CallOpClientSendClose() : send_(false) {} |
| 341 |
| 342 void ClientSendClose() { send_ = true; } |
| 343 |
| 344 protected: |
| 345 void AddOp(grpc_op* ops, size_t* nops) { |
| 346 if (!send_) return; |
| 347 grpc_op* op = &ops[(*nops)++]; |
| 348 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; |
| 349 op->flags = 0; |
| 350 op->reserved = NULL; |
| 351 } |
| 352 void FinishOp(bool* status, int max_message_size) { send_ = false; } |
| 353 |
| 354 private: |
| 355 bool send_; |
| 356 }; |
| 357 |
| 358 class CallOpServerSendStatus { |
| 359 public: |
| 360 CallOpServerSendStatus() : send_status_available_(false) {} |
| 361 |
| 362 void ServerSendStatus( |
| 363 const std::multimap<grpc::string, grpc::string>& trailing_metadata, |
| 364 const Status& status) { |
| 365 trailing_metadata_count_ = trailing_metadata.size(); |
| 366 trailing_metadata_ = FillMetadataArray(trailing_metadata); |
| 367 send_status_available_ = true; |
| 368 send_status_code_ = static_cast<grpc_status_code>(status.error_code()); |
| 369 send_status_details_ = status.error_message(); |
| 370 } |
| 371 |
| 372 protected: |
| 373 void AddOp(grpc_op* ops, size_t* nops) { |
| 374 if (!send_status_available_) return; |
| 375 grpc_op* op = &ops[(*nops)++]; |
| 376 op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; |
| 377 op->data.send_status_from_server.trailing_metadata_count = |
| 378 trailing_metadata_count_; |
| 379 op->data.send_status_from_server.trailing_metadata = trailing_metadata_; |
| 380 op->data.send_status_from_server.status = send_status_code_; |
| 381 op->data.send_status_from_server.status_details = |
| 382 send_status_details_.empty() ? nullptr : send_status_details_.c_str(); |
| 383 op->flags = 0; |
| 384 op->reserved = NULL; |
| 385 } |
| 386 |
| 387 void FinishOp(bool* status, int max_message_size) { |
| 388 if (!send_status_available_) return; |
| 389 gpr_free(trailing_metadata_); |
| 390 send_status_available_ = false; |
| 391 } |
| 392 |
| 393 private: |
| 394 bool send_status_available_; |
| 395 grpc_status_code send_status_code_; |
| 396 grpc::string send_status_details_; |
| 397 size_t trailing_metadata_count_; |
| 398 grpc_metadata* trailing_metadata_; |
| 399 }; |
| 400 |
| 401 class CallOpRecvInitialMetadata { |
| 402 public: |
| 403 CallOpRecvInitialMetadata() : recv_initial_metadata_(nullptr) {} |
| 404 |
| 405 void RecvInitialMetadata(ClientContext* context) { |
| 406 context->initial_metadata_received_ = true; |
| 407 recv_initial_metadata_ = &context->recv_initial_metadata_; |
| 408 } |
| 409 |
| 410 protected: |
| 411 void AddOp(grpc_op* ops, size_t* nops) { |
| 412 if (!recv_initial_metadata_) return; |
| 413 memset(&recv_initial_metadata_arr_, 0, sizeof(recv_initial_metadata_arr_)); |
| 414 grpc_op* op = &ops[(*nops)++]; |
| 415 op->op = GRPC_OP_RECV_INITIAL_METADATA; |
| 416 op->data.recv_initial_metadata = &recv_initial_metadata_arr_; |
| 417 op->flags = 0; |
| 418 op->reserved = NULL; |
| 419 } |
| 420 void FinishOp(bool* status, int max_message_size) { |
| 421 if (recv_initial_metadata_ == nullptr) return; |
| 422 FillMetadataMap(&recv_initial_metadata_arr_, recv_initial_metadata_); |
| 423 recv_initial_metadata_ = nullptr; |
| 424 } |
| 425 |
| 426 private: |
| 427 std::multimap<grpc::string_ref, grpc::string_ref>* recv_initial_metadata_; |
| 428 grpc_metadata_array recv_initial_metadata_arr_; |
| 429 }; |
| 430 |
| 431 class CallOpClientRecvStatus { |
| 432 public: |
| 433 CallOpClientRecvStatus() : recv_status_(nullptr) {} |
| 434 |
| 435 void ClientRecvStatus(ClientContext* context, Status* status) { |
| 436 recv_trailing_metadata_ = &context->trailing_metadata_; |
| 437 recv_status_ = status; |
| 438 } |
| 439 |
| 440 protected: |
| 441 void AddOp(grpc_op* ops, size_t* nops) { |
| 442 if (recv_status_ == nullptr) return; |
| 443 memset(&recv_trailing_metadata_arr_, 0, |
| 444 sizeof(recv_trailing_metadata_arr_)); |
| 445 status_details_ = nullptr; |
| 446 status_details_capacity_ = 0; |
| 447 grpc_op* op = &ops[(*nops)++]; |
| 448 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; |
| 449 op->data.recv_status_on_client.trailing_metadata = |
| 450 &recv_trailing_metadata_arr_; |
| 451 op->data.recv_status_on_client.status = &status_code_; |
| 452 op->data.recv_status_on_client.status_details = &status_details_; |
| 453 op->data.recv_status_on_client.status_details_capacity = |
| 454 &status_details_capacity_; |
| 455 op->flags = 0; |
| 456 op->reserved = NULL; |
| 457 } |
| 458 |
| 459 void FinishOp(bool* status, int max_message_size) { |
| 460 if (recv_status_ == nullptr) return; |
| 461 FillMetadataMap(&recv_trailing_metadata_arr_, recv_trailing_metadata_); |
| 462 *recv_status_ = Status( |
| 463 static_cast<StatusCode>(status_code_), |
| 464 status_details_ ? grpc::string(status_details_) : grpc::string()); |
| 465 gpr_free(status_details_); |
| 466 recv_status_ = nullptr; |
| 467 } |
| 468 |
| 469 private: |
| 470 std::multimap<grpc::string_ref, grpc::string_ref>* recv_trailing_metadata_; |
| 471 Status* recv_status_; |
| 472 grpc_metadata_array recv_trailing_metadata_arr_; |
| 473 grpc_status_code status_code_; |
| 474 char* status_details_; |
| 475 size_t status_details_capacity_; |
| 476 }; |
| 477 |
| 478 /// An abstract collection of CallOpSet's, to be used whenever |
| 479 /// CallOpSet objects must be thought of as a group. Each member |
| 480 /// of the group should have a shared_ptr back to the collection, |
| 481 /// as will the object that instantiates the collection, allowing |
| 482 /// for automatic ref-counting. In practice, any actual use should |
| 483 /// derive from this base class. This is specifically necessary if |
| 484 /// some of the CallOpSet's in the collection are "Sneaky" and don't |
| 485 /// report back to the C++ layer CQ operations |
| 486 class CallOpSetCollectionInterface |
| 487 : public std::enable_shared_from_this<CallOpSetCollectionInterface> {}; |
| 488 |
| 489 /// An abstract collection of call ops, used to generate the |
| 490 /// grpc_call_op structure to pass down to the lower layers, |
| 491 /// and as it is-a CompletionQueueTag, also massages the final |
| 492 /// completion into the correct form for consumption in the C++ |
| 493 /// API. |
| 494 class CallOpSetInterface : public CompletionQueueTag { |
| 495 public: |
| 496 CallOpSetInterface() : max_message_size_(0) {} |
| 497 /// Fills in grpc_op, starting from ops[*nops] and moving |
| 498 /// upwards. |
| 499 virtual void FillOps(grpc_op* ops, size_t* nops) = 0; |
| 500 |
| 501 void set_max_message_size(int max_message_size) { |
| 502 max_message_size_ = max_message_size; |
| 503 } |
| 504 |
| 505 /// Mark this as belonging to a collection if needed |
| 506 void SetCollection(std::shared_ptr<CallOpSetCollectionInterface> collection) { |
| 507 collection_ = collection; |
| 508 } |
| 509 |
| 510 protected: |
| 511 int max_message_size_; |
| 512 std::shared_ptr<CallOpSetCollectionInterface> collection_; |
| 513 }; |
| 514 |
| 515 /// Primary implementaiton of CallOpSetInterface. |
| 516 /// Since we cannot use variadic templates, we declare slots up to |
| 517 /// the maximum count of ops we'll need in a set. We leverage the |
| 518 /// empty base class optimization to slim this class (especially |
| 519 /// when there are many unused slots used). To avoid duplicate base classes, |
| 520 /// the template parmeter for CallNoOp is varied by argument position. |
| 521 template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>, |
| 522 class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>, |
| 523 class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>> |
| 524 class CallOpSet : public CallOpSetInterface, |
| 525 public Op1, |
| 526 public Op2, |
| 527 public Op3, |
| 528 public Op4, |
| 529 public Op5, |
| 530 public Op6 { |
| 531 public: |
| 532 CallOpSet() : return_tag_(this) {} |
| 533 void FillOps(grpc_op* ops, size_t* nops) GRPC_OVERRIDE { |
| 534 this->Op1::AddOp(ops, nops); |
| 535 this->Op2::AddOp(ops, nops); |
| 536 this->Op3::AddOp(ops, nops); |
| 537 this->Op4::AddOp(ops, nops); |
| 538 this->Op5::AddOp(ops, nops); |
| 539 this->Op6::AddOp(ops, nops); |
| 540 } |
| 541 |
| 542 bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE { |
| 543 this->Op1::FinishOp(status, max_message_size_); |
| 544 this->Op2::FinishOp(status, max_message_size_); |
| 545 this->Op3::FinishOp(status, max_message_size_); |
| 546 this->Op4::FinishOp(status, max_message_size_); |
| 547 this->Op5::FinishOp(status, max_message_size_); |
| 548 this->Op6::FinishOp(status, max_message_size_); |
| 549 *tag = return_tag_; |
| 550 collection_.reset(); // drop the ref at this point |
| 551 return true; |
| 552 } |
| 553 |
| 554 void set_output_tag(void* return_tag) { return_tag_ = return_tag; } |
| 555 |
| 556 private: |
| 557 void* return_tag_; |
| 558 }; |
| 559 |
| 560 /// A CallOpSet that does not post completions to the completion queue. |
| 561 /// |
| 562 /// Allows hiding some completions that the C core must generate from |
| 563 /// C++ users. |
| 564 template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>, |
| 565 class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>, |
| 566 class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>> |
| 567 class SneakyCallOpSet : public CallOpSet<Op1, Op2, Op3, Op4, Op5, Op6> { |
| 568 public: |
| 569 bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE { |
| 570 typedef CallOpSet<Op1, Op2, Op3, Op4, Op5, Op6> Base; |
| 571 return Base::FinalizeResult(tag, status) && false; |
| 572 } |
| 573 }; |
| 574 |
| 575 // Straightforward wrapping of the C call object |
| 576 class Call GRPC_FINAL { |
| 577 public: |
| 578 /* call is owned by the caller */ |
| 579 Call(grpc_call* call, CallHook* call_hook_, CompletionQueue* cq); |
| 580 Call(grpc_call* call, CallHook* call_hook_, CompletionQueue* cq, |
| 581 int max_message_size); |
| 582 |
| 583 void PerformOps(CallOpSetInterface* ops); |
| 584 |
| 585 grpc_call* call() { return call_; } |
| 586 CompletionQueue* cq() { return cq_; } |
| 587 |
| 588 int max_message_size() { return max_message_size_; } |
| 589 |
| 590 private: |
| 591 CallHook* call_hook_; |
| 592 CompletionQueue* cq_; |
| 593 grpc_call* call_; |
| 594 int max_message_size_; |
| 595 }; |
| 596 |
| 597 } // namespace grpc |
| 598 |
| 599 #endif // GRPCXX_IMPL_CODEGEN_CALL_H |
OLD | NEW |