| 34 | setCancelCallback([promise]() { |
| 35 | // This captures a strong ref reference, which will form a cycle. |
| 36 | // When this promise is fulfilled by upstream promise, |
| 37 | // the callback is removed, and the cycle will break |
| 38 | if (promise != nullptr) { |
| 39 | promise->cancel(); |
| 40 | } |
| 41 | }); |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | void ResolvablePromise::fulfill(Result<Value> result) { |
| 46 | std::unique_lock<Mutex> lock(_mutex); |
| 47 | if (!_result.empty()) { |
| 48 | // A producer may legitimately settle asynchronously after cancel() already recorded the |
| 49 | // synthetic canceled error; drop its result. Settling twice without a cancel is still a bug. |
| 50 | SC_ASSERT(_canceled, _result.description()); |
| 51 | return; |
| 52 | } |
| 53 | |
| 54 | _result = result; |
| 55 | // clear after move because moved-from function is in "valid but unspecified" state |
| 56 | auto callbacks = std::move(_callbacks); |
| 57 | _callbacks = {}; |
| 58 | auto cancelCallback = std::move(_cancelCallback); |
| 59 | _cancelCallback = {}; |
no test coverage detected