Mutex 一次只能有一个读者或作者,RwLock 一次可以有一个作家或多个读者.当你这样说的时候,RwLock似乎总是更好(更少限制)Mutex,为什么我会使用它呢?
我有一个在main(第 9 行)中初始化的变量,我想在我的一个路由处理程序中访问对这个变量的引用。
#[get("/")]
fn index() -> String {
return fetch_data::fetch(format!("posts"), &redis_conn).unwrap(); // How can I get redis_conn?
}
fn main() {
let redis_conn = fetch_data::get_redis_connection(); // initialized here
rocket::ignite().mount("/", routes![index]).launch();
}
Run Code Online (Sandbox Code Playgroud)
在其他语言中,这个问题可以通过使用全局变量来解决。
我正在查看一些使用的代码
Rc<RefCell<SomeStruct>>
Run Code Online (Sandbox Code Playgroud)
所以我出去阅读了 Rc 和 RefCell 之间的差异:
以下是选择 Box、Rc 或 RefCell 的原因的概述:
Rc 使同一数据的多个所有者成为可能;Box 和 RefCell 有一个所有者。
Box 允许在编译时检查不可变或可变借用;Rc 只允许在编译时检查不可变借用;
RefCell 允许在运行时检查不可变或可变借用。因为 RefCell 允许在运行时检查可变借用,所以即使 RefCell 是不可变的,您也可以改变 RefCell 内的值。
因此,请Rc确保SomeStruct可供多人同时访问。但我如何访问?我只看到get_mut返回可变引用的方法。但是文本解释了“Rc 只允许不可变的借用”。
如果可以以 mut 而不是 mut 方式访问 Rc 的对象,为什么需要 RefCell?
我的 C++ 背景让我对内部可变性感到不舒服。下面的代码是我围绕这个主题的调查。
我同意,从借用检查器的角度来看,处理每个内部状态可能迟早改变的单个结构上的许多引用是不可能的;这显然是内部可变性可以提供帮助的地方。
此外,在第15.5章“RefCell 和内部可变性模式”中锈病编程语言,有关的例子Messenger特质及其对实施
MockMessenger结构让我觉得,这是一种常见的API设计,系统地喜欢&self过&mut self,即使它很明显,迟早会强制要求某种可变性。Messenger发送消息时如何实现不改变其内部状态?例外只是打印消息,这与 一致&self,但一般情况可能包括写入某种内部流,这可能意味着缓冲,更新错误标志......所有这些当然都需要&mut self,例如
impl Write for File.
依靠内部的可变性来解决这个问题听起来好像是,在C ++中,const_cast荷兰国际集团或滥用mutable成员只是因为在申请的其他地方,我们是不是一致
const岬(对于C ++的学习者常犯的错误)。
所以,回到我下面的示例代码,我应该:
&mut self(编译器不会抱怨,即使它不是强制性的)从change_e()到change_i()为了与我改变存储的整数值的事实保持一致?&self,因为内部可变性允许它,即使我实际上改变了存储的整数的值?这个决定不仅对结构本身来说是局部的,而且会对使用这个结构的应用程序中可以表达的内容产生很大的影响。第二种解决方案肯定会有很大帮助,因为只涉及共享引用,但它是否与 Rust 中的预期一致。
我在Rust API Guidelines 中找不到这个问题的答案 。是否有任何其他类似于C++CoreGuidelines 的Rust 文档 ?
/*
$ rustc int_mut.rs && ./int_mut …Run Code Online (Sandbox Code Playgroud) 我正在尝试创建一个struct,Path并按需从指定的路径加载图像。这是我到目前为止的内容:
extern crate image;
use std::cell::{RefCell};
use std::path::{Path};
use image::{DynamicImage};
pub struct ImageCell<'a> {
image: RefCell<Option<DynamicImage>>,
image_path: &'a Path,
}
impl<'a> ImageCell<'a> {
pub fn new<P: AsRef<Path>>(image_path: &'a P) -> ImageCell<'a>{
ImageCell { image: RefCell::new(None), image_path: image_path.as_ref() }
}
//copied from https://doc.rust-lang.org/nightly/std/cell/index.html#implementation-details-of-logically-immutable-methods
pub fn get_image(&self) -> &DynamicImage {
{
let mut cache = self.image.borrow_mut();
if cache.is_some() {
return cache.as_ref().unwrap(); //Error here
}
let image = image::open(self.image_path).unwrap();
*cache = Some(image);
}
self.get_image()
}
}
Run Code Online (Sandbox Code Playgroud)
无法编译:
src/image_generation.rs:34:24: 34:29 …Run Code Online (Sandbox Code Playgroud) 我的目标是制作一个独立于基础数据结构的功能(特别是泛洪)。我试图通过传递两个闭包来做到这一点:一个用于查询,它不变地借用一些数据,另一个用于变异,它可变地借用相同的数据。
示例(在Rust Playground上测试):
#![feature(nll)]
fn foo<F, G>(n: i32, closure: &F, mut_closure: &mut G)
where
F: Fn(i32) -> bool,
G: FnMut(i32) -> (),
{
if closure(n) {
mut_closure(n);
}
}
fn main() {
let mut data = 0;
let closure = |n| data == n;
let mut mut_closure = |n| {
data += n;
};
foo(0, &closure, &mut mut_closure);
}
Run Code Online (Sandbox Code Playgroud)
错误:(调试,每晚)
#![feature(nll)]
fn foo<F, G>(n: i32, closure: &F, mut_closure: &mut G)
where
F: Fn(i32) -> bool,
G: FnMut(i32) -> …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个程序,它生成一个后台线程,不断地将数据插入到某个集合中.同时,我想继续获取输入stdin并检查该输入是否在线程正在运行的集合中.
这是一个简单的例子:
use std::collections::HashSet;
use std::thread;
fn main() {
let mut set: HashSet<String> = HashSet::new();
thread::spawn(move || {
loop {
set.insert("foo".to_string());
}
});
loop {
let input: String = get_input_from_stdin();
if set.contains(&input) {
// Do something...
}
}
}
fn get_input_from_stdin() -> String {
String::new()
}
Run Code Online (Sandbox Code Playgroud)
但是由于所有权的原因,这不起作用.
我还是Rust的新手,但这似乎应该是可行的.我只是找不到正确的Arcs,Rcs,Mutexes等组合来包装我的数据.
我需要创建一个 Vec 来跟踪我正在创建的对象并更改其状态以供以后使用。但是,如果我在获取存储在 vec 上的对象时使用克隆,它的状态不会更新,我该怎么做?
#[derive(Debug, Clone)]
struct Movement {
x: i32,
y: i32,
}
fn main() {
let mut current = Some(Movement { x: 1, y: 2 });
let mut stack = Vec::new();
stack.push(¤t);
current.as_mut().unwrap().x = 2;
println!("m: {:?}", current);
println!("stack.m: {:?}", stack.pop());
current = None;
}
Run Code Online (Sandbox Code Playgroud) 在下面的代码中,我试图通过调用其方法之一来更改已计数对象的值:
use std::rc::Rc;
fn main() {
let mut x = Rc::new(Thing { num: 50 });
x.what_to_do_to_get_mut_thing().change_num(19); //what do i do here
}
pub struct Thing {
pub num: u32,
}
impl Thing {
pub fn change_num(&mut self, newnum: u32) {
self.num = newnum;
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用该get_mut函数来实现此目的,但是我不知道这是否是实现此目标的标准方法。
if let Some(val) = Rc::get_mut(&mut x) {
val.change_num(19);
}
Run Code Online (Sandbox Code Playgroud) 对于C ++,有一个类似的,非常受欢迎的问题,但对于Rust,我找不到类似的现有问题。
那么,什么是用例Box,Rc,Ref,RefMut(其他人?)拉斯特?
这个问题的重要部分(对我个人而言):什么时候应该使用智能指针代替引用?
我知道《锈皮书》非常非常彻底地解释了它,但我希望在主题上有一个简洁明了的“备忘单”,其中可能包含本书中缺少的一些实际示例。
rust ×10
api-design ×1
closures ×1
concurrency ×1
mutability ×1
mutex ×1
ownership ×1
rust-rocket ×1