Polls the future. # Safety `this` must be a pointer produced by `Arc::into_raw` on an `Arc `. This call takes ownership of exactly one strong reference count for that allocation, consuming it via `Arc::from_raw` internally. The caller must hold "ownership" of one such strong reference.
(this: NonNull<()>, worker: &Worker)
| 698 | // after creating it. |
| 699 | state: AtomicU32::new(WOKEN), |
| 700 | scheduler, |
| 701 | }) |
| 702 | } |
| 703 | |
| 704 | /// Converts an `Arc<ScopeFutureJob>` into a job ref that can be queued on a |
| 705 | /// thread pool. The ref-count is not decremented, ensuring that the job |
| 706 | /// remains alive while this job ref exists. |
| 707 | /// |
| 708 | /// Forgetting this job ref will cause a memory leak. |
| 709 | fn into_job_ref(self: Arc<Self>) -> JobRef { |
| 710 | // SAFETY: Pointers created by `Arc::into_raw` are never null. |
| 711 | let job_pointer = unsafe { |
| 712 | NonNull::new_unchecked(Arc::into_raw(self).cast_mut().cast()) |
| 713 | }; |
| 714 | |
| 715 | // SAFETY: `JobRef::new` requires us to show that `execute` will only be |
| 716 | // called on the resulting `JobRef` where it is sound to call `poll` on |
| 717 | // `job_pointer`. |
| 718 | // |
| 719 | // `Poll` has two obligations: |
| 720 | // |
| 721 | // * `job_pointer` must have been produced by `Arc::into_raw` on an |
| 722 | // `Arc<Self>`. |
| 723 | // |
| 724 | // We produced `job_pointer` this way just above. |
| 725 | // |
| 726 | // * We must hold ownership of exactly one strong reference count for |
| 727 | // the allocation. |
| 728 | // |
| 729 | // We start with an `Arc<Self>`, so we must own a strong reference. |
| 730 | // Calling `Arc::into_raw` transfers the strong count of `self` onto |
| 731 | // `job_pointer` without decrementing it. Therefore, when `execute` |
| 732 | // is called, there will still be a strong reference for it to |
| 733 | // consume. |
| 734 | // |
| 735 | // `JobRef::new` also requires that `poll` not unwind. See the |
| 736 | // doc-comment for `poll` for an argument as to why this is the case. |
| 737 | unsafe { JobRef::new(job_pointer, Self::poll) } |
| 738 | } |
| 739 | |
| 740 | /// Schedules this job to be polled, by converting it into a `JobRef` and |
| 741 | /// handing that to the job's own `scheduler`. The `worker` param should be |
| 742 | /// the same as calling `Worker::with_current`. |
| 743 | fn schedule(self: Arc<Self>, worker: Option<&Worker>) { |
| 744 | // Clone a strong reference so the allocation, and therefore the |
| 745 | // `scheduler` field, stays alive for the entire `schedule` call. |
| 746 | // |
| 747 | // `into_job_ref` consumes `self` via `Arc::into_raw`, moving our strong |
| 748 | // reference into the `JobRef` *without* decrementing the count. The act |
| 749 | // of calling `schedule` enqueues that `JobRef`, after which another |
| 750 | // worker may execute and drop it before `schedule` returns. Holding |
| 751 | // `this` keeps an independent strong reference alive until the end of |
| 752 | // this function, so borrowing `this.scheduler` across the call cannot |
| 753 | // dangle. |
| 754 | let this = Arc::clone(&self); |
| 755 | let job_ref = self.into_job_ref(); |
| 756 | this.scheduler.schedule(job_ref, worker); |
| 757 | } |
no test coverage detected