* shareinput_writer_waitdone * * Called by the writer (producer) to wait for the "done" notification from * all readers (consumers). * * This is a blocking operation. */
| 1025 | * This is a blocking operation. |
| 1026 | */ |
| 1027 | static void |
| 1028 | shareinput_writer_waitdone(shareinput_Xslice_reference *ref, int nconsumers) |
| 1029 | { |
| 1030 | shareinput_Xslice_state *state = ref->xslice_state; |
| 1031 | |
| 1032 | int ready = pg_atomic_read_u32(&state->ready); |
| 1033 | if (!ready) |
| 1034 | elog(ERROR, "shareinput_writer_waitdone() called without creating the tuplestore"); |
| 1035 | |
| 1036 | ConditionVariablePrepareToSleep(&state->ready_done_cv); |
| 1037 | for (;;) |
| 1038 | { |
| 1039 | /* |
| 1040 | * set state->ndone via pg_atomic_add_fetch_u32() in shareinput_reader_notifydone() |
| 1041 | * it acts as a memory barrier, so always get the latest value here |
| 1042 | */ |
| 1043 | int ndone = pg_atomic_read_u32(&state->ndone); |
| 1044 | if (ndone < nconsumers) |
| 1045 | { |
| 1046 | elog((Debug_shareinput_xslice ? LOG : DEBUG1), "SISC WRITER (shareid=%d, slice=%d): waiting for DONE message from %d / %d readers", |
| 1047 | ref->share_id, currentSliceId, nconsumers - ndone, nconsumers); |
| 1048 | |
| 1049 | ConditionVariableSleep(&state->ready_done_cv, WAIT_EVENT_SHAREINPUT_SCAN); |
| 1050 | |
| 1051 | continue; |
| 1052 | } |
| 1053 | ConditionVariableCancelSleep(); |
| 1054 | if (ndone > nconsumers) |
| 1055 | elog(WARNING, "%d sharers of ShareInputScan reported to be done, but only %d were expected", |
| 1056 | ndone, nconsumers); |
| 1057 | break; |
| 1058 | } |
| 1059 | |
| 1060 | elog((Debug_shareinput_xslice ? LOG : DEBUG1), "SISC WRITER (shareid=%d, slice=%d): got DONE message from %d readers", |
| 1061 | ref->share_id, currentSliceId, nconsumers); |
| 1062 | |
| 1063 | /* it's all done now */ |
| 1064 | } |
no test coverage detected