| 28 | next_cancellation_token_(0) {} |
| 29 | |
| 30 | void CancellationManager::StartCancel() { |
| 31 | gtl::FlatMap<CancellationToken, CancelCallback> callbacks_to_run; |
| 32 | { |
| 33 | mutex_lock l(mu_); |
| 34 | if (is_cancelled_.load(std::memory_order_relaxed) || is_cancelling_) { |
| 35 | return; |
| 36 | } |
| 37 | is_cancelling_ = true; |
| 38 | std::swap(callbacks_, callbacks_to_run); |
| 39 | } |
| 40 | // We call these callbacks without holding mu_, so that concurrent |
| 41 | // calls to DeregisterCallback, which can happen asynchronously, do |
| 42 | // not block. The callbacks remain valid because any concurrent call |
| 43 | // to DeregisterCallback will block until the |
| 44 | // cancelled_notification_ is notified. |
| 45 | for (auto key_and_value : callbacks_to_run) { |
| 46 | key_and_value.second(); |
| 47 | } |
| 48 | { |
| 49 | mutex_lock l(mu_); |
| 50 | is_cancelling_ = false; |
| 51 | is_cancelled_.store(true, std::memory_order_release); |
| 52 | } |
| 53 | cancelled_notification_.Notify(); |
| 54 | } |
| 55 | |
| 56 | CancellationToken CancellationManager::get_cancellation_token() { |
| 57 | mutex_lock l(mu_); |