| | 125 | |
| | 126 | What these functions do: basically the global data structure comprises a FIFO queue for each thread. The queue contains work-sharing records, one record for each work-sharing or barrier construct encountered. The record contains the basic information about the construct as provided by the arguments to the arrival function, as well as the distribution chosen for that thread. |
| | 127 | |
| | 128 | The constructs are a lot like MPI collective operations, and are modeled similarly. |
| | 129 | |
| | 130 | When a thread arrives at one of these constructs, it invokes the relevant arrival function. At this point you can determine whether this thread is the first to arrive at that construct. If its queue is empty, it is the first, otherwise it is now, and the oldest entry in its queue will be the entry corresponding to this construct. |
| | 131 | |
| | 132 | When a thread is the first thread to arrive at a construct, a distribution is chosen for every thread and a record is created and enqueued in each thread queue (including the caller). The distributions can be chosen nondeterministically, possibly with some restrictions to achieve some tractability/soundness compromise. The record for this thread is then dequeued and the iterator returned. |
| | 133 | |
| | 134 | If a thread is not the first to arrive, its record is dequeued and compared with the arguments given in the function call. They should match, and if they don't, an error is reported. This indicates that either threads encountered constructs in different orders or the loop parameters changed. |