-
Notifications
You must be signed in to change notification settings - Fork 9
Description
The async Waker system (and in particular RawWaker and the Wake trait) appears to lack a way to work with Rc/Arc instances not in the Global allocator. It's also onerous and intrusive to manually implement this through RawWaker because the allocator instance present in Rc/Arc is lost when using Arc::into_raw/from_raw. It feels like the only way to do this currently is to store the allocator in T itself, then launder Arc<T, A> through Arc<T, Global> as such:
struct Task<A> {
...
alloc: A,
}
impl<A: Allocator> Wake for Task<A> {
fn wake(self: Arc<Self>) {
let actual_arc = Arc::from_raw_in(Arc::into_raw(self), self.alloc.clone())
...
}
}
This is very fragile though as things can appear to work correctly without this hack, papered over by the fact that it's fairly unlikely that through the Waker machinery the ref count of the Arc drops to 0 and thus deallocate is called on the Global allocator instead of the correct one. But if it does happen, it would be undefined and likely crash (as I saw in practice when trying to generalized FuturesUnordered to use allocator-api).
This problem generalizes to LocalWaker/LocalWake as well.