MCPcopy Create free account
hub / github.com/apache/brpc / OnSubDoneRun

Method OnSubDoneRun

src/brpc/parallel_channel.cpp:215–305  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

213 }
214
215 void OnSubDoneRun(SubDone* fin) {
216 if (fin != NULL) {
217 // [ called from SubDone::Run() ]
218
219 int error_code = fin->cntl.ErrorCode();
220 // EPCHANFINISH is not an error of sub calls.
221 bool fail = 0 != error_code && EPCHANFINISH != error_code;
222 bool cancel =
223 // Count failed sub calls, if `fail_limit' is reached, cancel others.
224 (fail && _current_fail.fetch_add(1, butil::memory_order_relaxed) + 1
225 == _fail_limit) ||
226 // Count successful sub calls, if `success_limit' is reached, cancel others.
227 (0 == error_code &&
228 _current_success.fetch_add(1, butil::memory_order_relaxed) + 1
229 == _success_limit);
230
231 if (cancel) {
232 // Only cancel once by `fail_limit' or `success_limit'.
233 for (int i = 0; i < _ndone; ++i) {
234 SubDone* sd = sub_done(i);
235 if (fin != sd) {
236 bthread_id_error(
237 sd->cntl.call_id(), fail ? ECANCELED : EPCHANFINISH);
238 }
239 }
240 }
241 // NOTE: Don't access any member after the fetch_add because
242 // another thread may already go down and Destroy()-ed this object.
243 const uint32_t saved_ndone = _ndone;
244 const CallId saved_cid = _cntl->_correlation_id;
245 // Add 1 to finished sub calls.
246 // The release fence is matched with acquire fence below to
247 // guarantee visibilities of all other variables.
248 const uint32_t val =
249 _current_done.fetch_add(1, butil::memory_order_release);
250 // Lower 31 bits are number of finished sub calls. If caller is not
251 // the last call that finishes, return.
252 if ((val & 0x7fffffff) + 1 != saved_ndone) {
253 return;
254 }
255 // If _cntl->call_id() is still there, stop it by sending a special
256 // error(which will be cleared) and return.
257 if (!(val & 0x80000000)) {
258 bthread_id_error(saved_cid, EPCHANFINISH);
259 return;
260 }
261 } else {
262 // [ Called from this->Run() ]
263
264 // We may cancel sub calls even if all sub calls finish because
265 // of reading the value relaxly (and CPU cache is not sync yet).
266 // It's OK and we have to, because sub_done can't be accessed
267 // after fetch_or.
268 uint32_t val = _current_done.load(butil::memory_order_relaxed);
269 // Lower 31 bits are number of finished sub calls. Cancel sub calls
270 // if not all of them finish.
271 if ((val & 0x7fffffff) != (uint32_t)_ndone) {
272 for (int i = 0; i < _ndone; ++i) {

Callers 1

RunMethod · 0.80

Calls 8

atomic_thread_fenceFunction · 0.85
bthread_start_backgroundFunction · 0.85
ErrorCodeMethod · 0.80
fetch_addMethod · 0.80
call_idMethod · 0.80
fetch_orMethod · 0.80
loadMethod · 0.45

Tested by

no test coverage detected