| 90 | } |
| 91 | |
| 92 | void AppendReal(FnOnce<Status()> task) override { |
| 93 | DCHECK(!finished_); |
| 94 | if (stop_token_.IsStopRequested()) { |
| 95 | UpdateStatus(stop_token_.Poll()); |
| 96 | return; |
| 97 | } |
| 98 | |
| 99 | // The hot path is unlocked thanks to atomics |
| 100 | // Only if an error occurs is the lock taken |
| 101 | if (ok_.load(std::memory_order_acquire)) { |
| 102 | nremaining_.fetch_add(1, std::memory_order_acquire); |
| 103 | |
| 104 | auto self = checked_pointer_cast<ThreadedTaskGroup>(shared_from_this()); |
| 105 | |
| 106 | auto callable = [self = std::move(self), task = std::move(task), |
| 107 | stop_token = stop_token_]() mutable { |
| 108 | if (self->ok_.load(std::memory_order_acquire)) { |
| 109 | Status st; |
| 110 | if (stop_token.IsStopRequested()) { |
| 111 | st = stop_token.Poll(); |
| 112 | } else { |
| 113 | // XXX what about exceptions? |
| 114 | st = std::move(task)(); |
| 115 | } |
| 116 | self->UpdateStatus(std::move(st)); |
| 117 | } |
| 118 | self->OneTaskDone(); |
| 119 | }; |
| 120 | auto st = executor_->Spawn(std::move(callable)); |
| 121 | bool spawn_successful = st.ok(); |
| 122 | UpdateStatus(std::move(st)); |
| 123 | if (!spawn_successful) { |
| 124 | OneTaskDone(); |
| 125 | } |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | Status current_status() override { |
| 130 | std::lock_guard<std::mutex> lock(mutex_); |
nothing calls this directly
no test coverage detected