| 428 | |
| 429 | template <typename T, typename O> |
| 430 | static void enable_cancellation( |
| 431 | const int_fd& fd, |
| 432 | const Future<T>& future, |
| 433 | const std::shared_ptr<O>& overlapped) |
| 434 | { |
| 435 | // We capture a `std::weak_ptr` in the `.onDiscard` callback, so that |
| 436 | // we can cancel the IO operation with the overlapped object if it still |
| 437 | // exists. The captured `shared_ptr` in the `.onAny` callback ensures that |
| 438 | // we keep the overlapped object alive until the IOCP callbacks are done. |
| 439 | auto overlapped_weak = std::weak_ptr<O>(overlapped); |
| 440 | |
| 441 | future.onDiscard([fd, overlapped_weak]() { |
| 442 | std::shared_ptr<O> cancel = overlapped_weak.lock(); |
| 443 | if (static_cast<bool>(cancel)) { |
| 444 | // We were able to get a reference to the overlapped object, so let's |
| 445 | // try to cancel the IO operation. Note that there is technically a |
| 446 | // race here. We could be between the IO completion event and deleting |
| 447 | // the overlapped object. In that case, this function will just no-op. |
| 448 | ::CancelIoEx(fd, &cancel->base.overlapped); |
| 449 | } |
| 450 | }); |
| 451 | |
| 452 | future.onAny([overlapped]() {}); |
| 453 | } |
| 454 | |
| 455 | |
| 456 | static Future<size_t> read_internal( |
no test coverage detected