@@ -186,10 +186,12 @@ using PrepareAsyncFunction = std::unique_ptr<grpc::ClientAsyncResponseReader<Rep
186
186
// / `ClientCallManager` is used to manage outgoing gRPC requests and the lifecycles of
187
187
// / `ClientCall` objects.
188
188
// /
189
- // / It maintains a thread that keeps polling events from `CompletionQueue`, and post
190
- // / the callback function to the main event loop when a reply is received.
189
+ // / It maintains multiple threads that keep polling events from its corresponding
190
+ // / `CompletionQueue`, and post the callback function to the main event loop when a reply
191
+ // / is received.
191
192
// /
192
- // / Multiple clients can share one `ClientCallManager`.
193
+ // / Multiple clients can share one `ClientCallManager`, with responses delegated to one
194
+ // / completion queue in the round-robin style.
193
195
class ClientCallManager {
194
196
public:
195
197
// / Constructor.
@@ -210,7 +212,7 @@ class ClientCallManager {
210
212
// Start the polling threads.
211
213
cqs_.reserve (num_threads_);
212
214
for (int i = 0 ; i < num_threads_; i++) {
213
- cqs_.push_back (std::make_unique<grpc::CompletionQueue>());
215
+ cqs_.emplace_back (std::make_unique<grpc::CompletionQueue>());
214
216
polling_threads_.emplace_back (
215
217
&ClientCallManager::PollEventsFromCompletionQueue, this , i);
216
218
}
@@ -222,6 +224,7 @@ class ClientCallManager {
222
224
cq->Shutdown ();
223
225
}
224
226
for (auto &polling_thread : polling_threads_) {
227
+ RAY_CHECK (polling_thread.joinable ());
225
228
polling_thread.join ();
226
229
}
227
230
}
0 commit comments