< 返回版块

ziyouwa 发表于 2024-04-17 22:39

Tags:RwLock, async

代码中调用下面这个函数时,会报如下一堆错误。自觉是因为代码中引用了同步写锁,导致返回的变量被认为是*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()
        }
    }
}

评论区

写评论
Bai-Jinlin 2024-04-18 14:18

给个可复现的最小代码吧

--
👇
ziyouwa:
ziyouwa: 尝试过在insert之后drop掉write_guard,貌似没用

--
👇
Bai-Jinlin: 应该是rwlock的guard跨越了await点,你在获取写锁后drop一下看看

作者 ziyouwa 2024-04-18 13:29

ziyouwa: 尝试过在insert之后drop掉write_guard,貌似没用

--
👇
Bai-Jinlin: 应该是rwlock的guard跨越了await点,你在获取写锁后drop一下看看

Bai-Jinlin 2024-04-18 12:23

应该是rwlock的guard跨越了await点,你在获取写锁后drop一下看看

TinusgragLin 2024-04-18 00:27

报错里有说 GuardNoSend(也就是 *mut ())非 Send,这个类型会在 lock guard 中出现,你看一下是不是误把 lock guard 移进 future 里了。

1 共 4 条评论, 1 页