我有一个最小的例子:
use std::{future::Future, pin::Pin, thread::JoinHandle, fmt::Debug};
use tokio::runtime::Runtime;
struct Callback<E> {
f: Box<dyn Fn() -> Pin<Box<dyn Future<Output = Result<(), E>> + Send + Sync>> + Send + Sync>,
}
trait Provider {
fn setup(&self) -> JoinHandle<()>;
}
enum Foo {
A,
B
}
trait IntoFoo {
fn into_foo(&self) -> Foo;
}
impl<E: Debug + IntoFoo> Provider for Callback<E> {
fn setup(&self) -> JoinHandle<()> {
std::thread::spawn(move || {
// Running async function sycnhronously within another thread.
let rt = Runtime::new().unwrap();
rt.block_on(handle(Box::new(move || (self.f)())))
.expect("request loop failed")
})
}
}
async fn handle<E: Debug + IntoFoo + 'static>( callback_fn: Box<dyn Fn() -> Pin<Box<dyn Future<Output = Result<(), E>> + Send + Sync>> + Send + Sync>) -> Result<(), E> {
perform(Box::new(move || (callback_fn)())).await
}
pub async fn perform<
E: Debug + IntoFoo>(
op: Box<dyn Fn() -> Pin<Box<dyn Future<Output = Result<(), E>> + Send + Sync>> + Send + Sync>,
) -> Result<(), E> {
(op)().await
}
这是一些真实代码的简化版本,我基本上必须在 struct 中传递一个martec回调.这个回调通过多个函数传递.其中一个线程在新生成的线程中调用该函数.
当调用handle
时,我得到的错误是在线程派生代码中.
错误是:
error: lifetime may not live long enough
--> src/indexer/callback.rs:41:41
|
27 | fn bootstrap(&self, input: StageReceiver) -> BootstrapResult {
| - let's call the lifetime of this reference `'1`
...
41 | rt.block_on(handle_event(input, Box::new(move |ev: &Event| (self.f)(ev)), &retry_policy, utils))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static`
我应该如何协调这件事?可以更改 struct 字段类型和任何类似的内容.然而,我必须注意:该函数必须能够被多次调用(它可能在handle
中的循环中).
其他一些线程建议在Box中传递异步回调,它们的结果是一个固定的盒装特征对象.这就是为什么我try 了这个系统.