代码中调用下面这个函数时,会报如下一堆错误。自觉是因为代码中引用了同步写锁,导致返回的变量被认为是*mut的, 不能Send。但是找不到怎么写才正确。
`*mut ()` cannot be sent between threads safely
within `{async block@src/core/server/tcp.rs:77:18: 81:6}`, the trait `std::marker::Send` is not implemented for `*mut ()`, which is required by `{async block@src/core/server/tcp.rs:77:18: 81:6}: std::marker::Send`
required because it appears within the type `(&HashMap<String, Value<Arc<RwLock<RawRwLock, NetworkInfo>>>>, GuardNoSend)`
required because it captures the following types: `std::string::String`, `parking_lot::lock_api::RwLockReadGuard<'_, parking_lot::RawRwLock, std::collections::HashMap<std::string::String, core::store::expire_map::Value<std::sync::Arc<parking_lot::lock_api::RwLock<parking_lot::RawRwLock, core::entity::NetworkInfo>>>>>`, `std::sync::Arc<parking_lot::lock_api::RwLock<parking_lot::RawRwLock, core::entity::NetworkInfo>>`, `parking_lot::lock_api::RwLockWriteGuard<'_, parking_lot::RawRwLock, std::collections::HashMap<std::string::String, core::store::expire_map::Value<std::sync::Arc<parking_lot::lock_api::RwLock<parking_lot::RawRwLock, core::entity::NetworkInfo>>>>>`, `tokio::time::Timeout<impl std::future::Future<Output = std::result::Result<(), tokio::sync::mpsc::error::SendError<core::store::expire_map::DelayedTask<std::string::String>>>>>`
required because it captures the following types: `protocol::NetPacket<&mut [u8; 65536]>`, `std::net::SocketAddr`, `&std::option::Option<tokio::sync::mpsc::Sender<std::vec::Vec<u8>>>`, `bool`, `&config::ConfigInfo`, `&core::store::cache::AppCache`, `proto::message::RegistrationRequest`, `std::string::String`, `proto::message::RegistrationResponse`, `u32`, `u32`, `u32`, `std::sync::Arc<parking_lot::lock_api::RwLock<parking_lot::RawRwLock, core::entity::NetworkInfo>>`, `impl std::future::Future<Output = std::sync::Arc<parking_lot::lock_api::RwLock<parking_lot::RawRwLock, core::entity::NetworkInfo>>>`, `u32`, `std::ops::Range<u32>`, `i64`, `impl std::future::Future<Output = ()>`, `impl std::future::Future<Output = ()>`
required because it captures the following types: `protocol::NetPacket<&mut [u8; 65536]>`, `impl std::future::Future<Output = std::result::Result<std::option::Option<protocol::NetPacket<std::vec::Vec<u8>>>, error::Error>>`
required because it captures the following types: `&core::service::server::ServerPacketHandler`, `std::net::SocketAddr`, `impl std::future::Future<Output = std::result::Result<std::result::Result<std::option::Option<protocol::NetPacket<std::vec::Vec<u8>>>, error::Error>, protocol::NetPacket<&mut [u8; 65536]>>>`
required because it captures the following types: `&core::service::server::ServerPacketHandler`, `protocol::NetPacket<&mut [u8; 65536]>`, `std::net::SocketAddr`, `std::net::Ipv4Addr`, `impl std::future::Future<Output = std::result::Result<protocol::NetPacket<std::vec::Vec<u8>>, error::Error>>`, `std::option::Option<std::sync::Arc<cipher::aes_gcm_cipher::Aes256GcmCipher>>`, `impl std::future::Future<Output = std::result::Result<std::option::Option<protocol::NetPacket<std::vec::Vec<u8>>>, error::Error>>`
required because it captures the following types: `protocol::NetPacket<&mut [u8; 65536]>`, `impl std::future::Future<Output = std::result::Result<std::option::Option<protocol::NetPacket<std::vec::Vec<u8>>>, error::Error>>`
required because it captures the following types: `std::net::SocketAddr`, `impl std::future::Future<Output = std::result::Result<std::option::Option<protocol::NetPacket<std::vec::Vec<u8>>>, error::Error>>`
required because it captures the following types: `tokio::net::tcp::OwnedReadHalf`, `std::net::SocketAddr`, `core::service::PacketHandler`, `[u8; 4]`, `[u8; 65536]`, `std::option::Option<tokio::sync::mpsc::Sender<std::vec::Vec<u8>>>`, `tokio::io::util::read_exact::ReadExact<'_, tokio::net::tcp::OwnedReadHalf>`, `usize`, `tokio::io::util::read_exact::ReadExact<'_, tokio::net::tcp::OwnedReadHalf>`, `std::option::Option<protocol::NetPacket<std::vec::Vec<u8>>>`, `impl std::future::Future<Output = std::option::Option<protocol::NetPacket<std::vec::Vec<u8>>>>`, `protocol::NetPacket<std::vec::Vec<u8>>`, `impl std::future::Future<Output = std::result::Result<(), tokio::sync::mpsc::error::SendError<std::vec::Vec<u8>>>>`
required because it captures the following types: `impl std::future::Future<Output = std::result::Result<(), std::io::Error>>`
#[derive(Clone)]
pub struct ExpireMap<K, V> {
base: Arc<RwLock<HashMap<K, Value<V>>>>,
sender: mpsc::Sender<DelayedTask<K>>,
}
struct Value<V> {
val: V,
deadline: AtomicCell<Instant>,
expire: Duration,
}
impl<K, V> ExpireMap<K, V>
where
K: Eq + Hash + Clone,
V: Clone,
{
pub async fn optionally_get_with<F>(&self, k: K, f: F) -> V
where
F: FnOnce() -> (Duration, V),
{
if let Some(v) = self.base.read().get(&k) {
// 延长过期时间
v.deadline.store(Instant::now().add(v.expire));
v.val.clone()
} else {
let (expire, val) = f();
let deadline = Instant::now().add(expire);
let value = Value {
val: val.clone(),
deadline: AtomicCell::new(deadline),
expire,
};
let mut write_guard = self.base.write();
write_guard.insert(k.clone(), value);
if let Err(e) = tokio::time::timeout(
expire,
self.sender.send(DelayedTask {
k: k.clone(),
time: deadline,
}),
)
.await
{
log::error!("发送失败:{:?}", e);
}
val.clone()
}
}
}
1
共 4 条评论, 1 页
评论区
写评论给个可复现的最小代码吧
--
👇
ziyouwa:
ziyouwa: 尝试过在insert之后drop掉write_guard,貌似没用
--
👇
Bai-Jinlin: 应该是rwlock的guard跨越了await点,你在获取写锁后drop一下看看
ziyouwa: 尝试过在insert之后drop掉write_guard,貌似没用
--
👇
Bai-Jinlin: 应该是rwlock的guard跨越了await点,你在获取写锁后drop一下看看
应该是rwlock的guard跨越了await点,你在获取写锁后drop一下看看
报错里有说
GuardNoSend
(也就是*mut ()
)非 Send,这个类型会在 lock guard 中出现,你看一下是不是误把 lock guard 移进 future 里了。