| 216 | |
| 217 | struct Callback { |
| 218 | void operator()(const Result<T>& maybe_next) { |
| 219 | Future<V> sink; |
| 220 | bool end = !maybe_next.ok() || IsIterationEnd(*maybe_next); |
| 221 | bool should_purge = false; |
| 222 | bool should_trigger; |
| 223 | { |
| 224 | auto guard = state->mutex.Lock(); |
| 225 | // A MappedCallback may have purged or be purging the queue; |
| 226 | // we shouldn't do anything here. |
| 227 | if (state->finished) return; |
| 228 | if (end) { |
| 229 | should_purge = !state->finished; |
| 230 | state->finished = true; |
| 231 | } |
| 232 | sink = state->waiting_jobs.front(); |
| 233 | state->waiting_jobs.pop_front(); |
| 234 | should_trigger = !end && !state->waiting_jobs.empty(); |
| 235 | } |
| 236 | if (should_purge) { |
| 237 | state->Purge(); |
| 238 | } |
| 239 | if (should_trigger) { |
| 240 | state->source().AddCallback(Callback{state}); |
| 241 | } |
| 242 | if (maybe_next.ok()) { |
| 243 | const T& val = maybe_next.ValueUnsafe(); |
| 244 | if (IsIterationEnd(val)) { |
| 245 | sink.MarkFinished(IterationTraits<V>::End()); |
| 246 | } else { |
| 247 | Future<V> mapped_fut = state->map(val); |
| 248 | mapped_fut.AddCallback(MappedCallback{std::move(state), std::move(sink)}); |
| 249 | } |
| 250 | } else { |
| 251 | sink.MarkFinished(maybe_next.status()); |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | std::shared_ptr<State> state; |
| 256 | }; |
nothing calls this directly
no test coverage detected