[−][src]Crate extern_executor
External executor for async Rust
This project aims to provide simple executor which helps to run asynchronous Rust code using external event loops.
Usage
On a Rust side you should add extern_executor
as dependency to your cdylib
crate and use spawn()
function to run futures, like so:
use extern_executor::spawn; spawn(async { // your awaits });
On a C side you should implement executor's driver using your preferred event loop API. For example, when libuv is used it may looks like so:
#include <uv.h>
#include <rust_async_executor.h>
static void task_wake(RustAsyncExecutorExternTask data) {
uv_async_t* handle = data;
// wakeup uv's async task
uv_async_send(handle);
}
static void task_poll(uv_async_t* handle) {
// poll internal task until task complete
if (!rust_async_executor_poll(handle->data)) {
// drop internal task when task complete
rust_async_executor_drop(handle->data);
// drop uv's async task handle
uv_close((uv_handle_t*)handle, NULL);
}
}
static RustAsyncExecutorExternTask
task_new(RustAsyncExecutorUserData data) {
uv_loop_t* loop = data;
// crate and initialize uv's async task handle
uv_async_t* handle = malloc(sizeof(uv_async_t));
uv_async_init(loop, handle, task_poll);
return handle;
}
static void task_run(RustAsyncExecutorExternTask task,
RustAsyncExecutorInternTask data) {
uv_async_t* handle = task;
// store internal task handle to be able to poll it later
handle->data = data;
uv_async_send(handle); // do initial polling (important)
}
void uv_rust_async_executor_init(uv_loop_t *loop) {
// send out executor API to Rust side
rust_async_executor_init(task_new, task_run, task_wake, loop);
}
Now you can run your async code in libuv's event loop like so:
int main(void) {
uv_loop_t loop;
uv_loop_init(&loop);
uv_rust_async_executor_init(&loop);
my_async_function(my_async_callback);
uv_run(&loop, UV_RUN_DEFAULT);
uv_loop_close(&loop);
return 0;
}
The C header rust_async_executor.h generated using cbindgen. There are two options how you can get it:
- Copy from include directory in this repo
- Generate by youself by using cbindgen feature
In second case generated header will be available at target/$PROFILE/include
directory.
Built-in event-loop drivers
To simplify setup for some widely used event loops the built-in drivers was introduced. To use driver you should enable corresponding feature. Currently supported next drivers:
- uv built-in libuv event loop integration (see example_uv)
- dart built-in dart-lang event loop integration (see example_dart)
Linking issues
Rust currently have an issues related to re-exporting of symbols from crate's dependencies (#2771).
As temporary solution you can setup build profile like so:
[profile.release]
lto = true
incremental = false
Tokio compatibility
This executor incompatible with tokio's futures because tokio still has non-trivial executor which mixed with reactor.
Modules
ffi |
Macros
externs | Deprecated |
Functions
spawn | Spawn task |