summaryrefslogtreecommitdiffstats
path: root/vendor/cxx/book/src/async.md
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/cxx/book/src/async.md')
-rw-r--r--vendor/cxx/book/src/async.md86
1 files changed, 86 insertions, 0 deletions
diff --git a/vendor/cxx/book/src/async.md b/vendor/cxx/book/src/async.md
new file mode 100644
index 000000000..b4c696a36
--- /dev/null
+++ b/vendor/cxx/book/src/async.md
@@ -0,0 +1,86 @@
+{{#title Async functions — Rust ♡ C++}}
+# Async functions
+
+Direct FFI of async functions is absolutely in scope for CXX (on C++20 and up)
+but is not implemented yet in the current release. We are aiming for an
+implementation that is as easy as:
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+ unsafe extern "C++" {
+ async fn doThing(arg: Arg) -> Ret;
+ }
+}
+```
+
+```cpp,hidelines
+rust::Future<Ret> doThing(Arg arg) {
+ auto v1 = co_await f();
+ auto v2 = co_await g(arg);
+ co_return v1 + v2;
+}
+```
+
+## Workaround
+
+For now the recommended approach is to handle the return codepath over a oneshot
+channel (such as [`futures::channel::oneshot`]) represented in an opaque Rust
+type on the FFI.
+
+[`futures::channel::oneshot`]: https://docs.rs/futures/0.3.8/futures/channel/oneshot/index.html
+
+```rust,noplayground
+// bridge.rs
+
+use futures::channel::oneshot;
+
+#[cxx::bridge]
+mod ffi {
+ extern "Rust" {
+ type DoThingContext;
+ }
+
+ unsafe extern "C++" {
+ include!("path/to/bridge_shim.h");
+
+ fn shim_doThing(
+ arg: Arg,
+ done: fn(Box<DoThingContext>, ret: Ret),
+ ctx: Box<DoThingContext>,
+ );
+ }
+}
+
+struct DoThingContext(oneshot::Sender<Ret>);
+
+pub async fn do_thing(arg: Arg) -> Ret {
+ let (tx, rx) = oneshot::channel();
+ let context = Box::new(DoThingContext(tx));
+
+ ffi::shim_doThing(
+ arg,
+ |context, ret| { let _ = context.0.send(ret); },
+ context,
+ );
+
+ rx.await.unwrap()
+}
+```
+
+```cpp
+// bridge_shim.cc
+
+#include "path/to/bridge.rs.h"
+#include "rust/cxx.h"
+
+void shim_doThing(
+ Arg arg,
+ rust::Fn<void(rust::Box<DoThingContext> ctx, Ret ret)> done,
+ rust::Box<DoThingContext> ctx) noexcept {
+ doThing(arg)
+ .then([done, ctx(std::move(ctx))](auto &&res) mutable {
+ (*done)(std::move(ctx), std::move(res));
+ });
+}
+```