| ... | @@ -2109,25 +2109,28 @@ fn await( | ... | @@ -2109,25 +2109,28 @@ fn await( |
| 2109 | .tag = .pending_canceled, | 2109 | .tag = .pending_canceled, |
| 2110 | .thread = .null, | 2110 | .thread = .null, |
| 2111 | }, .acq_rel); // acquire results if complete; release `future.awaiter` | 2111 | }, .acq_rel); // acquire results if complete; release `future.awaiter` |
| 2112 | switch (pre_cancel_status.tag) { | 2112 | const done_status = switch (pre_cancel_status.tag) { |
| 2113 | .pending => unreachable, // invalid state: we already awaited | 2113 | .pending => unreachable, // invalid state: we already awaited |
| 2114 | .pending_awaited => { | 2114 | .pending_awaited => done_status: { |
| 2115 | const working_thread = pre_cancel_status.thread.unpack(); | 2115 | const working_thread = pre_cancel_status.thread.unpack(); |
| 2116 | future.waitForCancelWithSignaling(t, &num_completed, @alignCast(working_thread)); | 2116 | future.waitForCancelWithSignaling(t, &num_completed, @alignCast(working_thread)); |
| | 2117 | break :done_status future.status.load(.monotonic); |
| 2117 | }, | 2118 | }, |
| 2118 | .pending_canceled => unreachable, // `await` raced with `cancel` | 2119 | .pending_canceled => unreachable, // `await` raced with `cancel` |
| 2119 | .done => { | 2120 | .done => done_status: { |
| 2120 | // The task just finished, but we still need to wait for the signal, because the | 2121 | // The task just finished, but we still need to wait for the signal, because the |
| 2121 | // task thread already figured out that they need to update `future.awaiter`. | 2122 | // task thread already figured out that they need to update `future.awaiter`. |
| 2122 | future.waitForCancelWithSignaling(t, &num_completed, null); | 2123 | future.waitForCancelWithSignaling(t, &num_completed, null); |
| | 2124 | // Also, we have clobbered `future.status.tag` to `.pending_canceled`, but that's |
| | 2125 | // not actually a problem for the logic below. |
| | 2126 | break :done_status pre_cancel_status; |
| 2123 | }, | 2127 | }, |
| 2124 | } | 2128 | }; |
| 2125 | // If the future did not acknowledge the cancelation, we need to mark it outstanding | 2129 | // If the future did not acknowledge the cancelation, we need to mark it outstanding |
| 2126 | // for us. Because `future.status.tag == .done`, the information about whether there | 2130 | // for us. Because `done_status.tag == .done`, the information about whether there |
| 2127 | // was an acknowledged cancelation is encoded in `future.status.thread`. | 2131 | // was an acknowledged cancelation is encoded in `done_status.thread`. |
| 2128 | const final_status = future.status.load(.monotonic); | 2132 | assert(done_status.tag == .done); |
| 2129 | assert(final_status.tag == .done); | 2133 | switch (done_status.thread) { |
| 2130 | switch (final_status.thread) { | | |
| 2131 | .null => recancelInner(), // cancelation was not acknowledged, so it's ours | 2134 | .null => recancelInner(), // cancelation was not acknowledged, so it's ours |
| 2132 | .all_ones => {}, // cancelation was acknowledged, so it was this task's job to propagate it | 2135 | .all_ones => {}, // cancelation was acknowledged, so it was this task's job to propagate it |
| 2133 | _ => unreachable, | 2136 | _ => unreachable, |