我有以下 struct :

use std::sync::Mutex;

pub struct Message {
    id: String,
    content: String,
    last_read: Option<String>,
    uuid: String,
}

impl Message {
    pub fn get_uuid(&self) -> String {
        self.uuid.to_owned()
    }
}

pub struct Queue {
    queue: Vec<Message>, // the actual queue
    read_timeout: u32,   // the amount of time a message is hidden from consumers
    size: u32,           // should always be the same as queue.len()
    uuid: String,
}

pub struct AppState {
    pub queues: Mutex<Vec<Queue>>,
}

最后,我有一些处理数据的函数.他们有重复的逻辑,正如你在下面看到的.他们在得到queue英镑后做的事情不同,但检索队列的方式是相同的.

pub async fn add_message(
    data: AppState
) {
    let queue_uuid = &String::from("my uuid");
    
    let queue_mutex = data.queues.lock();
    let mut queues = match queue_mutex {
        Ok(q) => q,
        Err(_) => return,
    };
    // find matching queue 
    let queue = queues.iter_mut().find(|q| q.uuid == *queue_uuid);
}

pub async fn get_message(
    data: AppState
) {
    let queue_uuid = &String::from("my uuid");
    
    let queue_mutex = data.queues.lock();
    let mut queues = match queue_mutex {
        Ok(q) => q,
        Err(_) => return,
    };
    // find matching queue 
    let queue = queues.iter_mut().find(|q| q.uuid == *queue_uuid);
    // once the queue is found, do some stuff with it 
}

我想要推翻这一逻辑.

impl AppState {
    pub fn get_queues(&self) -> &Mutex<Vec<Queue>> {
        &self.queues
    }

    pub fn get_queue_by_id(&mut self, uuid: String) -> Result<&mut Queue, String> {
        let queue_mutex = self.queues.lock();
        let mut queues = match queue_mutex {
            Ok(q) => q,
            Err(_) => return Err(String::from("Whoops! Something went wrong")),
        };
        match queues.iter_mut().find(|q| q.uuid == uuid) {
            None => Err(format!("Could not find queue with uuid {}", uuid)),
            Some(q) => Ok(q),
        }
    }
}

然而,这将产生一个错误,因为我不能返回q,因为它将在函数返回时被删除.对此有什么好的解决方案吗?

附注:我知道这样做可能会更有效率--例如,使用散列映射而不是向量来存储当前队列.我是一个铁 rust 新手,打算对此进行大量重构,所以任何反馈都是有帮助的!谢谢!

推荐答案

除了在async上下文中比在std::sync::Mutex上下文中更合适之外,futures变体还有另一个好处,它允许您的使用模式具有MutexGuard::map,这让您返回MappedMutexGuard<Vec<Queue>, Queue>:

impl AppState {
    pub async fn get_queue_by_id(
        &mut self,
        uuid: String,
    ) -> Result<MappedMutexGuard<Vec<Queue>, Queue>, String> {
        let mut queues = self.queues.lock().await;
        match queues.iter_mut().position(|q| q.uuid == uuid) {
            None => Err(format!("Could not find queue with uuid {}", uuid)),
            Some(p) => Ok(MutexGuard::map(queues, |q| &mut q[p])),
        }
    }
}

据我所知,std中的Mutex不可能做到这一点,见this Rust internals discussion.

Rust相关问答推荐

无法在线程之间安全地发送future (&Q;)&错误

如何在Bevy/Rapier3D中获得碰撞机的计算质量?

铁 rust 中的共享对象实现特征

铁 rust ,我的模块介绍突然遇到了一个问题

为什么我需要 to_string 函数的参考?

Rust,如何从 Rc> 复制内部值并返回它?

当我try 使用 SKI 演算中的S I I实现递归时,为什么 Rust 会失败?

使用 pyo3 将 Rust 转换为 Python 自定义类型

Rust Option 的空显式泛型参数

可选包装枚举的反序列化

Nom 解析器无法消耗无效输入

将 &str 或 String 保存在变量中

为什么这个闭包没有实现Fn?

如何在 Rust 中将 UTF-8 十六进制值转换为 char?

我如何将特征作为 struct 的拥有字段?

为什么 Rust 编译器在移动不可变值时执行复制?

当 `T` 没有实现 `Debug` 时替代 `unwrap()`

Cargo:如何将整个目录或文件包含在功能标志中?

使用泛型作为关联类型,没有幻像数据

为什么当borrow 变量发生变化时,borrow 变量不会改变?