我设计了一个简单的fifo,它存储a DequePolicy,如果元素太多,它可以从后面删除元素:
use super::deque_policy::DequePolicy;
use std::collections::VecDeque;
use std::sync::Arc;
use std::sync::Condvar;
pub struct BoundedFifo<T> {
pub deque: VecDeque<T>,
pub policy: Box<dyn DequePolicy<T>>,
//pub condvar: Condvar
}
impl<T> BoundedFifo<T> {
pub fn new(policy: Box<dyn DequePolicy<T>>) -> BoundedFifo<T> {
BoundedFifo{
deque: VecDeque::<T>::new(),
policy: policy,
//condvar: Condvar::new()
}
}
}
impl<T> BoundedFifo<T> {
pub fn pop_front(&mut self) -> Option<T> {
self.policy.before_pop_front(&self.deque);
//self.condvar.notify_all();
self.deque.pop_front()
}
pub fn push_back(&mut self, t: T) {
self.deque.push_back(t);
//self.condvar.notify_all();
self.policy.after_push_back(&mut self.deque);
}
}
我想在 2 个线程之间共享这个 fifo,但是有一个问题。我希望一个线程能够等待元素出现在 fifo 上。这就是为什么我添加了condvar现在评论的内容。
我评论它是因为我很快意识到要fifo在线程之间共享,我必须把它放在一个Arc<Mutex<>>. 因此,例如,为了等待condvar它在内部fifo: Arc<Mutex<BoundedFifo<u8>>>,我必须将它锁定在一个线程上:fifo.lock().unwrap().condvar.wait_timeout(...). 这基本上可以防止其他线程写入,因此没有必要等待。
然后我就有了这样做的想法:
type Fifo<T> = Arc<(Mutex<BoundedFifo<T>>, Condvar)>;
现在我可以等待一个 condvar,但我还必须记住每当我调用fifo: Fifo<T>'spush_back和时通知这个 condvar pop_front。例如:
let pair = ...
let fifo = pair.0;
let condvar = pair.1;
fifo.push_back(0);
condvar.notify_all();
这很容易出错,因为我很容易忘记调用它。在 C++ 上,它会让我等待共享事物中的某些内容(即使这是不安全的)。
我考虑过创建宏push_back!,pop_front!这将push_back与pop_front调用 一起调用notify_all,condvar但我觉得这不是很优雅。
我对 Rust 有点陌生,所以我正在为此寻求更好的解决方案。例如,是否有可能实现push_back和pop_frontfor Fifo<T>?这样我就避免了宏:slight_smile:。这是一个想法。