MCPcopy Create free account
hub / github.com/apache/arrow / operator()

Method operator()

cpp/src/arrow/util/async_generator.h:1276–1379  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1274 : state(std::move(state)), index(index), recursive(recursive) {}
1275
1276 void operator()(const Result<T>& maybe_next_ref) {
1277 // An item has been delivered by one of the inner subscriptions
1278 Future<T> next_fut;
1279 const Result<T>* maybe_next = &maybe_next_ref;
1280
1281 // When an item is delivered (and the caller has asked for it) we grab the
1282 // next item from the inner subscription. To avoid this behavior leading to an
1283 // infinite loop (this can happen if the caller's callback asks for the next item)
1284 // we use a while loop.
1285 while (true) {
1286 Future<T> sink;
1287 bool sub_finished = maybe_next->ok() && IsIterationEnd(**maybe_next);
1288 bool pull_next_sub = false;
1289 bool was_broken = false;
1290 bool should_mark_gen_complete = false;
1291 bool should_mark_final_error = false;
1292 {
1293 auto guard = state->mutex.Lock();
1294 if (state->broken) {
1295 // We've errored out previously so ignore the result. If anyone was waiting
1296 // for this they will get IterationEnd when we purge
1297 was_broken = true;
1298 } else {
1299 if (!sub_finished) {
1300 // There is a result to deliver. Either we can deliver it now or we will
1301 // queue it up
1302 if (state->waiting_jobs.empty()) {
1303 state->delivered_jobs.push_back(std::make_shared<DeliveredJob>(
1304 state->active_subscriptions[index], *maybe_next, index));
1305 } else {
1306 sink = std::move(*state->waiting_jobs.front());
1307 state->waiting_jobs.pop_front();
1308 }
1309 }
1310
1311 // If this is the first error then we transition the state to a broken state
1312 if (!maybe_next->ok()) {
1313 should_mark_final_error = true;
1314 state->SignalErrorUnlocked(guard);
1315 }
1316 }
1317
1318 // If we finished this inner subscription then we need to grab a new inner
1319 // subscription to take its spot. If we can't (because we're broken or
1320 // exhausted) then we aren't going to be starting any new futures and so
1321 // the number of running subscriptions drops.
1322 pull_next_sub = sub_finished && !state->source_exhausted && !was_broken;
1323 if (sub_finished && !pull_next_sub) {
1324 state->num_running_subscriptions--;
1325 }
1326 // There are three situations we won't pull again. If an error occurred or we
1327 // are already finished or if no one was waiting for our result and so we queued
1328 // it up. We will decrement outstanding_requests and possibly mark the
1329 // generator completed.
1330 if (state->broken || (!sink.is_valid() && !sub_finished) ||
1331 (sub_finished && state->source_exhausted)) {
1332 if (state->MarkTaskFinishedUnlocked(guard)) {
1333 should_mark_gen_complete = true;

Callers

nothing calls this directly

Calls 15

IsIterationEndFunction · 0.85
InnerCallbackClass · 0.85
push_backMethod · 0.80
SignalErrorUnlockedMethod · 0.80
MarkFinalErrorMethod · 0.80
MarkFinishedAndPurgeMethod · 0.80
PullSourceMethod · 0.80
okMethod · 0.45
LockMethod · 0.45
emptyMethod · 0.45
is_validMethod · 0.45

Tested by

no test coverage detected