* Attempt to read a tuple from one of our parallel workers. */
| 309 | * Attempt to read a tuple from one of our parallel workers. |
| 310 | */ |
| 311 | static MinimalTuple |
| 312 | gather_readnext(GatherState *gatherstate) |
| 313 | { |
| 314 | int nvisited = 0; |
| 315 | |
| 316 | for (;;) |
| 317 | { |
| 318 | TupleQueueReader *reader; |
| 319 | MinimalTuple tup; |
| 320 | bool readerdone; |
| 321 | |
| 322 | /* Check for async events, particularly messages from workers. */ |
| 323 | CHECK_FOR_INTERRUPTS(); |
| 324 | |
| 325 | /* |
| 326 | * Attempt to read a tuple, but don't block if none is available. |
| 327 | * |
| 328 | * Note that TupleQueueReaderNext will just return NULL for a worker |
| 329 | * which fails to initialize. We'll treat that worker as having |
| 330 | * produced no tuples; WaitForParallelWorkersToFinish will error out |
| 331 | * when we get there. |
| 332 | */ |
| 333 | Assert(gatherstate->nextreader < gatherstate->nreaders); |
| 334 | reader = gatherstate->reader[gatherstate->nextreader]; |
| 335 | tup = TupleQueueReaderNext(reader, true, &readerdone); |
| 336 | |
| 337 | /* |
| 338 | * If this reader is done, remove it from our working array of active |
| 339 | * readers. If all readers are done, we're outta here. |
| 340 | */ |
| 341 | if (readerdone) |
| 342 | { |
| 343 | Assert(!tup); |
| 344 | --gatherstate->nreaders; |
| 345 | if (gatherstate->nreaders == 0) |
| 346 | { |
| 347 | ExecShutdownGatherWorkers(gatherstate); |
| 348 | return NULL; |
| 349 | } |
| 350 | memmove(&gatherstate->reader[gatherstate->nextreader], |
| 351 | &gatherstate->reader[gatherstate->nextreader + 1], |
| 352 | sizeof(TupleQueueReader *) |
| 353 | * (gatherstate->nreaders - gatherstate->nextreader)); |
| 354 | if (gatherstate->nextreader >= gatherstate->nreaders) |
| 355 | gatherstate->nextreader = 0; |
| 356 | continue; |
| 357 | } |
| 358 | |
| 359 | /* If we got a tuple, return it. */ |
| 360 | if (tup) |
| 361 | return tup; |
| 362 | |
| 363 | /* |
| 364 | * Advance nextreader pointer in round-robin fashion. Note that we |
| 365 | * only reach this code if we weren't able to get a tuple from the |
| 366 | * current worker. We used to advance the nextreader pointer after |
| 367 | * every tuple, but it turns out to be much more efficient to keep |
| 368 | * reading from the same queue until that would require blocking. |
no test coverage detected