rodrimati1992 / abi_stable_crates

Rust-to-Rust ffi,ffi-safe equivalents of std types,and creating libraries loaded at startup.
Apache License 2.0
528 stars 30 forks source link

StableAbi and Futures #72

Open mineichen opened 2 years ago

mineichen commented 2 years ago

First of all, thank you for your significant contribution to have a stable rust ABI. I found almost everything I needed except for working with futures. There is however another crate named asyncFfi, which provides #[repr(C)] alternative to future-structs.

I tried to have a NewType MyFuture(async_ffi::FfiFuture) which manually implements StableAbi, but I struggled to implement LAYOUT for it and I don't know if this is even possible. This leads to the following questions:

  1. Would you consider to have a feature-flag for this library, so FfiFuture implements StableAbi?
  2. Would it be possible to create a procedural macro to easily generate StableAbi-Implementations for any #[repr(C)] structs?
  3. If both 1+2 are not feasible: Is there another way to use FfiFuture in a StableAbi-struct?
marioortizmanero commented 2 years ago

I already worked on this myself, it's just that it hasn't been upstreamed yet: https://github.com/oxalica/async-ffi/pull/10. But it should work perfectly.

Anyway, it would be nice to have official support, or at least some docs point to this crate. Otherwise I wouldn't have known about it.

marioortizmanero commented 2 years ago

Update: stable_abi support has been merged into master and will most likely be available in its next version.

afranchuk commented 2 years ago

@marioortizmanero cool. I solved the problem a different way (in private code), simply using sabi_trait to create abi-stable versions of BoxFuture/LocalBoxFuture, with appropriate wrappers for Context and Poll. That's not too tricky to pull off, though since they are called very often I am curious what the performance implications are of using a vtable as is done with the sabi_trait (one extra redirection but probably hot in cache) versus having the pointers directly in the struct as you did.

yavko commented 1 year ago

I solved the problem a different way (in private code),

Could you show how?

Update: stable_abi support has been merged into master and will most likely be available in its next version.

Doesn't work for me even with the feature flag, claims it doesn't implement the trait, seems like versioning problem

afranchuk commented 1 year ago

@yavko at the time, the code was private so I could not (though it's general enough I probably could have shared). However now that code is OSS: https://github.com/CACI-International/ergo/blob/ac1a2492e03fbdffc7df10e15ef6b08ca9b8277e/ergo_abi_stable/src/future/mod.rs

yavko commented 1 year ago

@yavko at the time, the code was private so I could not (though it's general enough I probably could have shared). However now that code is OSS: CACI-International/ergo@ac1a249/ergo_abi_stable/src/future/mod.rs

I know this is too much to ask, but could you show an example of its usage? I got it to work in my codebase, but don't actually know how the BoxedFuture struct EDIT: I think I figured it out! Thanks for the code!

yavko commented 1 year ago

Weird I'm getting the same issue I was getting with async-ffi there is no reactor running, must be called from the context of a Tokio 1.x runtime

afranchuk commented 1 year ago

That is unrelated to StableAbi. You are presumably using some async code that relies on tokio without using a tokio runtime.

yavko commented 1 year ago

That is unrelated to StableAbi. You are presumably using some async code that relies on tokio without using a tokio runtime.

Well, thats the thing, I am, the ffi module calls tokio async calls, and then my code is loading that module and running it under a tokio runtime.

afranchuk commented 1 year ago

You're problem is that the thread local state (which tokio relies on to provide the context) will not work across binary boundaries. Each binary gets its own copy of the thread local values. The plugin_tls crate allows thread local state to work across binaries, however it requires the state be declared differently. You'd have to patch tokio to make it work, both for the application starting the tokio runtime and every library accessing it.

yavko commented 1 year ago

You're problem is that the thread local state (which tokio relies on to provide the context) will not work across binary boundaries. Each binary gets its own copy of the thread local values. The plugin_tls crate allows thread local state to work across binaries, however it requires the state be declared differently. You'd have to patch tokio to make it work, both for the application starting the tokio runtime and every library accessing it.

Does this work for async-std/smol? And how are you doing it, have you patched it? Thanks for all the help so far! Edit: Trying out async-net (a part of smol) worked out for me, and I'll just use that from on, ig I won't be able to use tokio, which is fine anyways Edit 2: I also decided to try async-std (yes ik they both use same runtime) and it also works