【发布时间】:2022-12-06 16:19:44
【问题描述】:
以下代码描述了使用 HashMap 准备异步调用的容器:
use std::{
collections::HashMap,
any::Any,
marker::Send
};
use futures::future::{Future, BoxFuture};
// ===================================
pub type AnyType = Box<dyn Any + Send>;
// ===================================
trait AsyncFn {
fn call(&self, arg: AnyType) -> BoxFuture<'static, ()>;
}
impl<T, F> AsyncFn for T
where
T: Fn(AnyType) -> F,
F: Future<Output = ()> + 'static + Send,
{
fn call(&self, arg: AnyType) -> BoxFuture<'static, ()> {
Box::pin(self(arg))
}
}
async fn async_test(data: AnyType) -> () {
let d: Box<String> = data.downcast().unwrap();
println!("String data = {d:?}");
}
#[async_std::main]
async fn main() {
let mut callables: HashMap<String, Box<dyn AsyncFn>> = HashMap::new();
callables.insert(
"test_func".to_string(),
Box::new(async_test)
);
let awaitable = callables.get("test_func").unwrap();
awaitable.call(Box::new("test string argument1".to_string())).await;
}
我面临着以这种方式准备未来调用的任务,不仅是一个异步函数,而且还有一个额外的相关参数。我试着这样做:
// ...
pub type AnyBindType = Option<AnyType>;
// ===================================
trait AsyncBindFn {
fn call(&self, arg: AnyBindType) -> BoxFuture<'static, ()>;
}
impl<T, F> AsyncBindFn for T
where
T: Fn(AnyBindType) -> F,
F: Future<Output = ()> + 'static + Send,
{
fn call(&self, arg: AnyBindType) -> BoxFuture<'static, ()> {
Box::pin(self(arg))
}
}
async fn async_test2(data: AnyBindType) -> () {
if let Some(ref d) = data {
let d = d.downcast_ref::<String>();
println!("String data = {d:?}");
}
}
#[async_std::main]
async fn main() {
// ...
let mut bind_callables: HashMap<String, (Box<dyn AsyncBindFn>, AnyBindType)> = HashMap::new();
bind_callables.insert(
"bind_test_func".to_string(),
(Box::new(async_test2), Some(Box::new("test bind string argument1".to_string())))
);
let bind_awaitable_data = bind_callables.get("bind_test_func").unwrap();
let (bind_awaitable, bind_arg) = bind_awaitable_data;
// if let Some(ref d) = bind_arg {
// let d = d.downcast_ref::<String>();
// println!("String data = {d:?}");
// }
bind_awaitable.call(bind_arg).await; // ! ERROR
// ^^^^^^^^ - mismatched type
}
数据传输到 HashMap 后,获取原始数据的唯一方法是对其执行 remove(),但我需要能够重用它。意思是,我需要通过 ref 访问。
在最后一个示例中,注释掉的if let 的最后一个块成功打印了此数据,但由于它是一个引用,我无法将其发送到相应的函数中执行相同的操作,因为它是类型不匹配。
因此,签名的描述应该相应地更改,以便该函数引用一个可选参数,但是当我收到它时,我将有一个对可选数据的引用,等等......
如何克服这种情况?
【问题讨论】:
标签: rust