- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个隐藏在 Mutex
后面的 Git 存储库:
pub struct GitRepo {
contents: Mutex<GitContents>,
workdir: PathBuf,
}
我想查询它,但最多只能查询一次:查询完后,我只想使用我们第一次得到的结果。存储库有一个 git2::Repository
,或结果向量。 Repository
是Send
但不是Sync
。
enum GitContents {
Before { repo: git2::Repository },
After { statuses: Git },
}
struct Git {
statuses: Vec<(PathBuf, git2::Status)>,
}
GitContents
枚举反射(reflect)了这样一个事实,即我们要么拥有要查询的存储库,要么拥有查询它的结果,但绝不会两者兼而有之。
我试图让 Rust 强制执行此属性,方法是使用将存储库转换为状态的函数消费存储库,因为它会产生状态向量:
fn repo_to_statuses(repo: git2::Repository, workdir: &Path) -> Git {
// Assume this does something useful...
Git { statuses: Vec::new() }
}
但是,我无法让 Mutex
很好地处理这个问题。到目前为止,这是我尝试编写一个函数,该函数使用谓词 P
查询 GitRepo
,如果没有,则替换 Mutex
中的值'尚未查询:
impl GitRepo {
fn search<P: Fn(&Git) -> bool>(&self, p: P) -> bool {
use std::mem::replace;
// Make this thread wait until the mutex becomes available.
// If it's locked, it's because another thread is running repo_to_statuses
let mut contents = self.contents.lock().unwrap();
match *contents {
// If the repository has been queried then just use the existing results
GitContents::After { ref statuses } => p(statuses),
// If it hasn't, then replace it with some results, then use them.
GitContents::Before { ref repo } => {
let statuses = repo_to_statuses(*repo, &self.workdir);
let result = p(&statuses);
replace(&mut *contents, GitContents::After { statuses });
result
},
}
}
}
尽管涉及突变,但此方法仅采用 &self
而不是 &mut self
因为无论是第一次还是第一次查询存储库,它都会返回相同的结果第二次,尽管第一次有更多的工作要做。但是 Rust 提示:
repo
移出我在 repo_to_statuses(*repo, &self.workdir)
中借用的内容,即使我知道该值应该得到之后立即更换。 (“无法移出借用的内容”)replace
-ing &mut *contents
,因为我正在不可变地借用内容,因为值是 match
-编辑。 (“不能将‘contents’借用为可变的,因为它也被借用为不可变的”)有没有办法让借阅检查员相信我的意图?
最佳答案
你问的问题和真正的内部问题本质上与 Mutex
无关,一旦你锁定它并拥有可变引用或实现 DerefMut
的类型.
您可以使用取消引用运算符为引用分配一个新值 *
.如果需要以前的值,可以使用 std::mem::replace
.
use std::sync::Mutex;
use std::mem;
fn example_not_using_old_value(state: &Mutex<String>) {
let mut state = state.lock().expect("Could not lock mutex");
*state = String::from("dereferenced");
}
fn example_using_old_value(state: &Mutex<String>) -> String {
let mut state = state.lock().expect("Could not lock mutex");
mem::replace(&mut *state, String::from("replaced"))
}
fn main() {
let state = Mutex::new("original".into());
example_not_using_old_value(&state);
let was = example_using_old_value(&state);
println!("Is now {:?}", state);
println!("Was {:?}", was);
}
我们取消引用 MutexGuard<T>
得到 T
,并对其进行可变引用,产生一个 &mut T
我们可以调用mem::replace
与。
您的更广泛的问题是因为您无法移出借用的内容(请参阅 numerous Q&A for that)。查看这些直接相关的问答:
您可能希望添加一个新的枚举变体,它表示当所有内容都已移出但尚未移回任何内容时的状态。然后,您可以用该虚拟对象替换您的值并获得旧值的所有权,执行您的操作,然后将新值放回原处。
关于rust - 如何替换 Mutex 中的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45985827/
我需要在一个函数内锁定一个 std::map 和两个 boost::multimaps 的操作,因为我们有线程试图访问该函数(以及映射)。 我计划使用“std::mutex mutex_var”来保护
已关闭。这个问题是 off-topic 。目前不接受答案。 想要改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 已关闭11 年前。 Improve th
或不同的标题: 为什么处置获得的 Mutex 会破坏它? 我有以下代码,真正的代码在几个方法之间产生,并在这个方法休眠的地方做事: bool createdNew; u
如何测量互斥量、信号量或 futex 的延迟?我的意思是两个事件之间的延迟:解锁先前锁定的互斥体和锁定该互斥体。有两种情况:当所有线程/进程都在同一个 CPU 上时(重新调度线程需要多长时间)以及当第
我执行了以下程序,其中我创建了 100 个线程并发执行。请注意这是一个示例程序。我知道下面的程序不需要多线程,但我的目的是测试互斥量。 class ThreadPool{ public:
我有创建多个线程的代码,所有线程都尝试将信息记录在一个文件中我尝试使用互斥锁来登录文件,但是当我使用 Mutex() 和 Mutex(true or false, "name") 对象时,我得到了不同
我正在研究 Rust 示例。有这段代码: fn new(name: &str, left: usize, right: usize) -> Philosopher { Philosopher
我正在实现一个基于 std::queue 的 C++ 消息队列。 因为我需要 popers 在空队列上等待,所以我考虑使用 mutex 进行互斥,并使用 cond 在空队列上挂起线程,就像 glib
在golang中,sync.Mutex Lock和Unlock是usaul操作,但是Lock和defer Unlock的正确顺序是什么? mu.Lock() defer mu.Unlock() 或 d
在 Go 中,我们可以使用: type Data struct { lock *sync.Mutex } 或 type Data struct { lock sync.Mutex
我尝试摆脱代码中的一些 boost 依赖项,转而使用新的 C++11 功能 (Visual Studio 2013)。 在我的一个组件中,我使用了 boost::mutex与 boost::lock_
我正在使用 scoped_lock 和 mutex 来实现 BlockingQueue posted in a different SO question 的一个版本, 但在 boost 中有多个不同
我在互斥锁析构函数中遇到了上述错误。由于错误可能是由于互斥锁在销毁过程中处于锁定状态,所以我创建了一个新的互斥锁类,它继承自 boost:mutex。这是为了确保互斥锁在销毁期间解锁。但是,仍然会出现
今天写了一些代码来测试mutex的性能。 这是 boost(1.54) 版本,在 vs2010 上编译并进行了 O2 优化: boost::mutex m; auto start = boost::c
我不知道我没有做什么,但我根本无法让自己的调试器保存正在调试的应用程序的“Mutex Owned”或“Mutex Free”信息。 如果我按如下方式调用它,CDB 就可以正常工作: cdb -pn
还没有网上的例子来生动地演示这一点。在 http://en.cppreference.com/w/cpp/header/shared_mutex 看到了一个例子但目前还不清楚。有人可以帮忙吗? 最佳答
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我编写了一个小型 Go 库 ( go-patan ),用于收集某些变量的运行最小值/最大值/平均值/标准偏差。我将它与等效的 Java 实现 ( patan ) 进行了比较,令我惊讶的是 Java 实
我想知道这两者之间的区别是什么 boost::timed_mutex _mutex; if(_mutex.timed_lock(boost::get_system_time() + boost::po
我正在尝试将 dyn 特征存储在 Arc>>>> 中,但是由于某种原因它不起作用 use std::sync::{Arc, Mutex}; trait A{} struct B{} impl A fo
我是一名优秀的程序员,十分优秀!