我有一个全局 HashMap 如下:
static mut CONNECTING_CLIENT: Lazy<Mutex<HashMap<String, TcpStream>>> =
Lazy::new(|| Mutex::new(HashMap::new()));
并且封装了一个方法来获取值的可变借用,如下:
pub async fn get_client_stream(username: &String) -> Option<&mut TcpStream> {
unsafe {
CONNECTING_CLIENT
.lock()
.await
.get_mut(username)
// 这个 get_mut 返回值是 Option<&mut TcpStream>
}
}
报了如下的错误:
cannot return reference to temporary value
returns a reference to data owned by the current function
我猜想是因为 MutexGuard 持有了借用,出了 unsafe 块后就失效了。
参考了 HashMap 的源码后修改成了以下方式:
pub async fn get_client_stream(username: &String) -> Option<&mut TcpStream> {
let mut v = unsafe {
CONNECTING_CLIENT
.lock()
.await
};
v.get_mut(username).map(|v| {
unsafe {
&mut *(v as *mut TcpStream)
}
})
}
这样一来,虽然编译是通过了,但我不能保证这个 unsafe 是否 safe,不知道会不会有问题
求教可能会发生什么问题?有没有其他更好的写法?
1
共 2 条评论, 1 页
评论区
写评论不管是不是static/unsafe,智能指针包裹的可变引用尽可能不要跨作用域传递,最好是用完就drop,免得影响其他引用,包括但不限于Mutex/RwLock/RefCell。
如果觉得每次用的时候都得写一串东西用起来太麻烦,可以考虑用宏来封装,起码不用考虑这么多类型、生命周期以及所有权问题。
我觉得你没必要使用全局可变的静态变量,这样做才需要使用不安全代码块。最好初始化程序时建立一个服务器对象,这个对象能供多条线程使用。
简单示例: