【发布时间】:2019-06-05 12:09:04
【问题描述】:
我将生成器用作长期异步线程(请参阅
How to implement a lightweight long-lived thread based on a generator or asynchronous function in Rust?) 在用户交互场景中。我需要在每一步将用户输入传递给生成器。我想我可以用RefCell 做到这一点,但不清楚如何在创建实例时将引用转移到生成器内部的RefCell?
fn user_scenario() -> impl Generator<Yield = String, Return = String> {
|| {
yield format!("what is your name?");
yield format!("{}, how are you feeling?", "anon");
return format!("{}, bye !", "anon");
}
}
UserData 结构包含用户输入,第二个结构包含由UserData 和生成器实例组成的用户会话。会话收集在HashMap。
struct UserData {
sid: String,
msg_in: String,
msg_out: String,
}
struct UserSession {
udata_cell: RefCell<UserData>,
scenario: Pin<Box<dyn Generator<Yield = String, Return = String>>>,
}
type UserSessions = HashMap<String, UserSession>;
let mut sessions: UserSessions = HashMap::new();
UserData 是在接收用户输入时创建的——此时我需要在生成器中发送一个指向UserData 的链接,将其包装在RefCell 中,但我不知道该怎么做因为生成器的生命周期为 'static,而 RefCell 的生命周期较短!
let mut udata: UserData = read_udata(&mut stream);
let mut session: UserSession;
if udata.sid == "" { //new session
let sid = rnd.gen::<u64>().to_string();
udata.sid = sid.clone();
sessions.insert(
sid.clone(),
UserSession {
udata_cell: RefCell::new(udata),
scenario: Box::pin(user_scenario())
}
);
session = sessions.get_mut(&sid).unwrap();
}
full code is here,但是这里的生成器看不到用户输入。
【问题讨论】:
-
如果你试图在线程之间访问数据,你应该使用某种形式的
Mutex而不是RefCell -
@TheIncorrigible1,谢谢,但当前程序是单线程的,据我了解的问题是生成器有一个“静态生命周期”,而我的 RefCell(...) 生命周期较短,我仍然不明白如何同步生命周期。
-
long-lived asynchronous threads那你能澄清一下吗? -
也许说得不好,我的意思是仅在生成器或异步/等待上的 gorutin 类似物。 Gorutin 栈下最多占用 8Kb,比较敏感,异步比较经济。问题在于,在 Rust 中,这些都是夜间构建和薄弱的文档。