server.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  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. #include <grpc++/server.h>
  34. #include <utility>
  35. #include <grpc/grpc.h>
  36. #include <grpc/support/alloc.h>
  37. #include <grpc/support/log.h>
  38. #include <grpc++/completion_queue.h>
  39. #include <grpc++/generic/async_generic_service.h>
  40. #include <grpc++/impl/rpc_service_method.h>
  41. #include <grpc++/impl/service_type.h>
  42. #include <grpc++/server_context.h>
  43. #include <grpc++/security/server_credentials.h>
  44. #include <grpc++/support/time.h>
  45. #include "src/core/profiling/timers.h"
  46. #include "src/cpp/server/thread_pool_interface.h"
  47. namespace grpc {
  48. class DefaultGlobalCallbacks GRPC_FINAL : public Server::GlobalCallbacks {
  49. public:
  50. ~DefaultGlobalCallbacks() GRPC_OVERRIDE {}
  51. void PreSynchronousRequest(ServerContext* context) GRPC_OVERRIDE {}
  52. void PostSynchronousRequest(ServerContext* context) GRPC_OVERRIDE {}
  53. };
  54. static std::shared_ptr<Server::GlobalCallbacks> g_callbacks = nullptr;
  55. static gpr_once g_once_init_callbacks = GPR_ONCE_INIT;
  56. static void InitGlobalCallbacks() {
  57. if (g_callbacks == nullptr) {
  58. g_callbacks.reset(new DefaultGlobalCallbacks());
  59. }
  60. }
  61. class Server::UnimplementedAsyncRequestContext {
  62. protected:
  63. UnimplementedAsyncRequestContext() : generic_stream_(&server_context_) {}
  64. GenericServerContext server_context_;
  65. GenericServerAsyncReaderWriter generic_stream_;
  66. };
  67. class Server::UnimplementedAsyncRequest GRPC_FINAL
  68. : public UnimplementedAsyncRequestContext,
  69. public GenericAsyncRequest {
  70. public:
  71. UnimplementedAsyncRequest(Server* server, ServerCompletionQueue* cq)
  72. : GenericAsyncRequest(server, &server_context_, &generic_stream_, cq, cq,
  73. NULL, false),
  74. server_(server),
  75. cq_(cq) {}
  76. bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE;
  77. ServerContext* context() { return &server_context_; }
  78. GenericServerAsyncReaderWriter* stream() { return &generic_stream_; }
  79. private:
  80. Server* const server_;
  81. ServerCompletionQueue* const cq_;
  82. };
  83. typedef SneakyCallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus>
  84. UnimplementedAsyncResponseOp;
  85. class Server::UnimplementedAsyncResponse GRPC_FINAL
  86. : public UnimplementedAsyncResponseOp {
  87. public:
  88. UnimplementedAsyncResponse(UnimplementedAsyncRequest* request);
  89. ~UnimplementedAsyncResponse() { delete request_; }
  90. bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
  91. bool r = UnimplementedAsyncResponseOp::FinalizeResult(tag, status);
  92. delete this;
  93. return r;
  94. }
  95. private:
  96. UnimplementedAsyncRequest* const request_;
  97. };
  98. class Server::ShutdownRequest GRPC_FINAL : public CompletionQueueTag {
  99. public:
  100. bool FinalizeResult(void** tag, bool* status) {
  101. delete this;
  102. return false;
  103. }
  104. };
  105. class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
  106. public:
  107. SyncRequest(RpcServiceMethod* method, void* tag)
  108. : method_(method),
  109. tag_(tag),
  110. in_flight_(false),
  111. has_request_payload_(method->method_type() == RpcMethod::NORMAL_RPC ||
  112. method->method_type() ==
  113. RpcMethod::SERVER_STREAMING),
  114. call_details_(nullptr),
  115. cq_(nullptr) {
  116. grpc_metadata_array_init(&request_metadata_);
  117. }
  118. ~SyncRequest() {
  119. if (call_details_) {
  120. delete call_details_;
  121. }
  122. grpc_metadata_array_destroy(&request_metadata_);
  123. }
  124. static SyncRequest* Wait(CompletionQueue* cq, bool* ok) {
  125. void* tag = nullptr;
  126. *ok = false;
  127. if (!cq->Next(&tag, ok)) {
  128. return nullptr;
  129. }
  130. auto* mrd = static_cast<SyncRequest*>(tag);
  131. GPR_ASSERT(mrd->in_flight_);
  132. return mrd;
  133. }
  134. static bool AsyncWait(CompletionQueue* cq, SyncRequest** req, bool* ok,
  135. gpr_timespec deadline) {
  136. void* tag = nullptr;
  137. *ok = false;
  138. switch (cq->AsyncNext(&tag, ok, deadline)) {
  139. case CompletionQueue::TIMEOUT:
  140. *req = nullptr;
  141. return true;
  142. case CompletionQueue::SHUTDOWN:
  143. *req = nullptr;
  144. return false;
  145. case CompletionQueue::GOT_EVENT:
  146. *req = static_cast<SyncRequest*>(tag);
  147. GPR_ASSERT((*req)->in_flight_);
  148. return true;
  149. }
  150. GPR_UNREACHABLE_CODE(return false);
  151. }
  152. void SetupRequest() { cq_ = grpc_completion_queue_create(nullptr); }
  153. void TeardownRequest() {
  154. grpc_completion_queue_destroy(cq_);
  155. cq_ = nullptr;
  156. }
  157. void Request(grpc_server* server, grpc_completion_queue* notify_cq) {
  158. GPR_ASSERT(cq_ && !in_flight_);
  159. in_flight_ = true;
  160. if (tag_) {
  161. GPR_ASSERT(GRPC_CALL_OK ==
  162. grpc_server_request_registered_call(
  163. server, tag_, &call_, &deadline_, &request_metadata_,
  164. has_request_payload_ ? &request_payload_ : nullptr, cq_,
  165. notify_cq, this));
  166. } else {
  167. if (!call_details_) {
  168. call_details_ = new grpc_call_details;
  169. grpc_call_details_init(call_details_);
  170. }
  171. GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
  172. server, &call_, call_details_,
  173. &request_metadata_, cq_, notify_cq, this));
  174. }
  175. }
  176. bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
  177. if (!*status) {
  178. grpc_completion_queue_destroy(cq_);
  179. }
  180. if (call_details_) {
  181. deadline_ = call_details_->deadline;
  182. grpc_call_details_destroy(call_details_);
  183. grpc_call_details_init(call_details_);
  184. }
  185. return true;
  186. }
  187. class CallData GRPC_FINAL {
  188. public:
  189. explicit CallData(Server* server, SyncRequest* mrd)
  190. : cq_(mrd->cq_),
  191. call_(mrd->call_, server, &cq_, server->max_message_size_),
  192. ctx_(mrd->deadline_, mrd->request_metadata_.metadata,
  193. mrd->request_metadata_.count),
  194. has_request_payload_(mrd->has_request_payload_),
  195. request_payload_(mrd->request_payload_),
  196. method_(mrd->method_) {
  197. ctx_.set_call(mrd->call_);
  198. ctx_.cq_ = &cq_;
  199. GPR_ASSERT(mrd->in_flight_);
  200. mrd->in_flight_ = false;
  201. mrd->request_metadata_.count = 0;
  202. }
  203. ~CallData() {
  204. if (has_request_payload_ && request_payload_) {
  205. grpc_byte_buffer_destroy(request_payload_);
  206. }
  207. }
  208. void Run(std::shared_ptr<GlobalCallbacks> global_callbacks) {
  209. ctx_.BeginCompletionOp(&call_);
  210. global_callbacks->PreSynchronousRequest(&ctx_);
  211. method_->handler()->RunHandler(MethodHandler::HandlerParameter(
  212. &call_, &ctx_, request_payload_, call_.max_message_size()));
  213. global_callbacks->PostSynchronousRequest(&ctx_);
  214. request_payload_ = nullptr;
  215. void* ignored_tag;
  216. bool ignored_ok;
  217. cq_.Shutdown();
  218. GPR_ASSERT(cq_.Next(&ignored_tag, &ignored_ok) == false);
  219. }
  220. private:
  221. CompletionQueue cq_;
  222. Call call_;
  223. ServerContext ctx_;
  224. const bool has_request_payload_;
  225. grpc_byte_buffer* request_payload_;
  226. RpcServiceMethod* const method_;
  227. };
  228. private:
  229. RpcServiceMethod* const method_;
  230. void* const tag_;
  231. bool in_flight_;
  232. const bool has_request_payload_;
  233. grpc_call* call_;
  234. grpc_call_details* call_details_;
  235. gpr_timespec deadline_;
  236. grpc_metadata_array request_metadata_;
  237. grpc_byte_buffer* request_payload_;
  238. grpc_completion_queue* cq_;
  239. };
  240. static grpc_server* CreateServer(const ChannelArguments& args) {
  241. grpc_channel_args channel_args;
  242. args.SetChannelArgs(&channel_args);
  243. return grpc_server_create(&channel_args, nullptr);
  244. }
  245. Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
  246. int max_message_size, const ChannelArguments& args)
  247. : max_message_size_(max_message_size),
  248. started_(false),
  249. shutdown_(false),
  250. num_running_cb_(0),
  251. sync_methods_(new std::list<SyncRequest>),
  252. has_generic_service_(false),
  253. server_(CreateServer(args)),
  254. thread_pool_(thread_pool),
  255. thread_pool_owned_(thread_pool_owned) {
  256. gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
  257. global_callbacks_ = g_callbacks;
  258. grpc_server_register_completion_queue(server_, cq_.cq(), nullptr);
  259. }
  260. Server::~Server() {
  261. {
  262. grpc::unique_lock<grpc::mutex> lock(mu_);
  263. if (started_ && !shutdown_) {
  264. lock.unlock();
  265. Shutdown();
  266. }
  267. }
  268. void* got_tag;
  269. bool ok;
  270. GPR_ASSERT(!cq_.Next(&got_tag, &ok));
  271. grpc_server_destroy(server_);
  272. if (thread_pool_owned_) {
  273. delete thread_pool_;
  274. }
  275. delete sync_methods_;
  276. }
  277. void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) {
  278. GPR_ASSERT(g_callbacks == nullptr);
  279. GPR_ASSERT(callbacks != nullptr);
  280. g_callbacks.reset(callbacks);
  281. }
  282. bool Server::RegisterService(const grpc::string* host, RpcService* service) {
  283. for (int i = 0; i < service->GetMethodCount(); ++i) {
  284. RpcServiceMethod* method = service->GetMethod(i);
  285. void* tag = grpc_server_register_method(server_, method->name(),
  286. host ? host->c_str() : nullptr);
  287. if (!tag) {
  288. gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
  289. method->name());
  290. return false;
  291. }
  292. sync_methods_->emplace_back(method, tag);
  293. }
  294. return true;
  295. }
  296. bool Server::RegisterAsyncService(const grpc::string* host,
  297. AsynchronousService* service) {
  298. GPR_ASSERT(service->server_ == nullptr &&
  299. "Can only register an asynchronous service against one server.");
  300. service->server_ = this;
  301. service->request_args_ = new void* [service->method_count_];
  302. for (size_t i = 0; i < service->method_count_; ++i) {
  303. void* tag = grpc_server_register_method(server_, service->method_names_[i],
  304. host ? host->c_str() : nullptr);
  305. if (!tag) {
  306. gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
  307. service->method_names_[i]);
  308. return false;
  309. }
  310. service->request_args_[i] = tag;
  311. }
  312. return true;
  313. }
  314. void Server::RegisterAsyncGenericService(AsyncGenericService* service) {
  315. GPR_ASSERT(service->server_ == nullptr &&
  316. "Can only register an async generic service against one server.");
  317. service->server_ = this;
  318. has_generic_service_ = true;
  319. }
  320. int Server::AddListeningPort(const grpc::string& addr,
  321. ServerCredentials* creds) {
  322. GPR_ASSERT(!started_);
  323. return creds->AddPortToServer(addr, server_);
  324. }
  325. bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
  326. GPR_ASSERT(!started_);
  327. started_ = true;
  328. grpc_server_start(server_);
  329. if (!has_generic_service_) {
  330. if (!sync_methods_->empty()) {
  331. unknown_method_.reset(new RpcServiceMethod(
  332. "unknown", RpcMethod::BIDI_STREAMING, new UnknownMethodHandler));
  333. // Use of emplace_back with just constructor arguments is not accepted
  334. // here by gcc-4.4 because it can't match the anonymous nullptr with a
  335. // proper constructor implicitly. Construct the object and use push_back.
  336. sync_methods_->push_back(SyncRequest(unknown_method_.get(), nullptr));
  337. }
  338. for (size_t i = 0; i < num_cqs; i++) {
  339. new UnimplementedAsyncRequest(this, cqs[i]);
  340. }
  341. }
  342. // Start processing rpcs.
  343. if (!sync_methods_->empty()) {
  344. for (auto m = sync_methods_->begin(); m != sync_methods_->end(); m++) {
  345. m->SetupRequest();
  346. m->Request(server_, cq_.cq());
  347. }
  348. ScheduleCallback();
  349. }
  350. return true;
  351. }
  352. void Server::ShutdownInternal(gpr_timespec deadline) {
  353. grpc::unique_lock<grpc::mutex> lock(mu_);
  354. if (started_ && !shutdown_) {
  355. shutdown_ = true;
  356. grpc_server_shutdown_and_notify(server_, cq_.cq(), new ShutdownRequest());
  357. cq_.Shutdown();
  358. lock.unlock();
  359. // Spin, eating requests until the completion queue is completely shutdown.
  360. // If the deadline expires then cancel anything that's pending and keep
  361. // spinning forever until the work is actually drained.
  362. // Since nothing else needs to touch state guarded by mu_, holding it
  363. // through this loop is fine.
  364. SyncRequest* request;
  365. bool ok;
  366. while (SyncRequest::AsyncWait(&cq_, &request, &ok, deadline)) {
  367. if (request == NULL) { // deadline expired
  368. grpc_server_cancel_all_calls(server_);
  369. deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
  370. } else if (ok) {
  371. SyncRequest::CallData call_data(this, request);
  372. }
  373. }
  374. lock.lock();
  375. // Wait for running callbacks to finish.
  376. while (num_running_cb_ != 0) {
  377. callback_cv_.wait(lock);
  378. }
  379. }
  380. }
  381. void Server::Wait() {
  382. grpc::unique_lock<grpc::mutex> lock(mu_);
  383. while (num_running_cb_ != 0) {
  384. callback_cv_.wait(lock);
  385. }
  386. }
  387. void Server::PerformOpsOnCall(CallOpSetInterface* ops, Call* call) {
  388. static const size_t MAX_OPS = 8;
  389. size_t nops = 0;
  390. grpc_op cops[MAX_OPS];
  391. ops->FillOps(cops, &nops);
  392. auto result = grpc_call_start_batch(call->call(), cops, nops, ops, nullptr);
  393. GPR_ASSERT(GRPC_CALL_OK == result);
  394. }
  395. Server::BaseAsyncRequest::BaseAsyncRequest(
  396. Server* server, ServerContext* context,
  397. ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag,
  398. bool delete_on_finalize)
  399. : server_(server),
  400. context_(context),
  401. stream_(stream),
  402. call_cq_(call_cq),
  403. tag_(tag),
  404. delete_on_finalize_(delete_on_finalize),
  405. call_(nullptr) {
  406. memset(&initial_metadata_array_, 0, sizeof(initial_metadata_array_));
  407. }
  408. Server::BaseAsyncRequest::~BaseAsyncRequest() {}
  409. bool Server::BaseAsyncRequest::FinalizeResult(void** tag, bool* status) {
  410. if (*status) {
  411. for (size_t i = 0; i < initial_metadata_array_.count; i++) {
  412. context_->client_metadata_.insert(
  413. std::pair<grpc::string_ref, grpc::string_ref>(
  414. initial_metadata_array_.metadata[i].key,
  415. grpc::string_ref(
  416. initial_metadata_array_.metadata[i].value,
  417. initial_metadata_array_.metadata[i].value_length)));
  418. }
  419. }
  420. grpc_metadata_array_destroy(&initial_metadata_array_);
  421. context_->set_call(call_);
  422. context_->cq_ = call_cq_;
  423. Call call(call_, server_, call_cq_, server_->max_message_size_);
  424. if (*status && call_) {
  425. context_->BeginCompletionOp(&call);
  426. }
  427. // just the pointers inside call are copied here
  428. stream_->BindCall(&call);
  429. *tag = tag_;
  430. if (delete_on_finalize_) {
  431. delete this;
  432. }
  433. return true;
  434. }
  435. Server::RegisteredAsyncRequest::RegisteredAsyncRequest(
  436. Server* server, ServerContext* context,
  437. ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag)
  438. : BaseAsyncRequest(server, context, stream, call_cq, tag, true) {}
  439. void Server::RegisteredAsyncRequest::IssueRequest(
  440. void* registered_method, grpc_byte_buffer** payload,
  441. ServerCompletionQueue* notification_cq) {
  442. grpc_server_request_registered_call(
  443. server_->server_, registered_method, &call_, &context_->deadline_,
  444. &initial_metadata_array_, payload, call_cq_->cq(), notification_cq->cq(),
  445. this);
  446. }
  447. Server::GenericAsyncRequest::GenericAsyncRequest(
  448. Server* server, GenericServerContext* context,
  449. ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
  450. ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize)
  451. : BaseAsyncRequest(server, context, stream, call_cq, tag,
  452. delete_on_finalize) {
  453. grpc_call_details_init(&call_details_);
  454. GPR_ASSERT(notification_cq);
  455. GPR_ASSERT(call_cq);
  456. grpc_server_request_call(server->server_, &call_, &call_details_,
  457. &initial_metadata_array_, call_cq->cq(),
  458. notification_cq->cq(), this);
  459. }
  460. bool Server::GenericAsyncRequest::FinalizeResult(void** tag, bool* status) {
  461. // TODO(yangg) remove the copy here.
  462. if (*status) {
  463. static_cast<GenericServerContext*>(context_)->method_ =
  464. call_details_.method;
  465. static_cast<GenericServerContext*>(context_)->host_ = call_details_.host;
  466. }
  467. gpr_free(call_details_.method);
  468. gpr_free(call_details_.host);
  469. return BaseAsyncRequest::FinalizeResult(tag, status);
  470. }
  471. bool Server::UnimplementedAsyncRequest::FinalizeResult(void** tag,
  472. bool* status) {
  473. if (GenericAsyncRequest::FinalizeResult(tag, status) && *status) {
  474. new UnimplementedAsyncRequest(server_, cq_);
  475. new UnimplementedAsyncResponse(this);
  476. } else {
  477. delete this;
  478. }
  479. return false;
  480. }
  481. Server::UnimplementedAsyncResponse::UnimplementedAsyncResponse(
  482. UnimplementedAsyncRequest* request)
  483. : request_(request) {
  484. Status status(StatusCode::UNIMPLEMENTED, "");
  485. UnknownMethodHandler::FillOps(request_->context(), this);
  486. request_->stream()->call_.PerformOps(this);
  487. }
  488. void Server::ScheduleCallback() {
  489. {
  490. grpc::unique_lock<grpc::mutex> lock(mu_);
  491. num_running_cb_++;
  492. }
  493. thread_pool_->Add(std::bind(&Server::RunRpc, this));
  494. }
  495. void Server::RunRpc() {
  496. // Wait for one more incoming rpc.
  497. bool ok;
  498. GPR_TIMER_SCOPE("Server::RunRpc", 0);
  499. auto* mrd = SyncRequest::Wait(&cq_, &ok);
  500. if (mrd) {
  501. ScheduleCallback();
  502. if (ok) {
  503. SyncRequest::CallData cd(this, mrd);
  504. {
  505. mrd->SetupRequest();
  506. grpc::unique_lock<grpc::mutex> lock(mu_);
  507. if (!shutdown_) {
  508. mrd->Request(server_, cq_.cq());
  509. } else {
  510. // destroy the structure that was created
  511. mrd->TeardownRequest();
  512. }
  513. }
  514. GPR_TIMER_SCOPE("cd.Run()", 0);
  515. cd.Run(global_callbacks_);
  516. }
  517. }
  518. {
  519. grpc::unique_lock<grpc::mutex> lock(mu_);
  520. num_running_cb_--;
  521. if (shutdown_) {
  522. callback_cv_.notify_all();
  523. }
  524. }
  525. }
  526. } // namespace grpc