У меня есть общий Vec<CacheChange>
. Всякий раз, когда пишется новый CacheChange
, я хочу разбудить читателей. Я помню, что Condvar
хорош для сигнализации о том, что предикат/ситуация готова, а именно, когда Vec
изменен.
Поэтому я потратил некоторое время на создание абстракции Monitor
, чтобы владеть Vec
и обеспечивать семантику wait
и lock
.
Теперь проблема в том, что я не знаю, когда сбросить Condvar
. Каков хороший способ дать читателям разумное количество времени, чтобы нажать на предикат и проложить себе путь к удержанию блокировки? перед закрытием кондвара? Я неправильно подхожу к Condvar
s?
Это код Rust, но это больше вопрос основ для точного одновременного доступа/уведомления между несколькими читателями.
pub struct Monitor<T>(
sync::Arc<MonitorInner<T>>
);
struct MonitorInner<T> {
data: sync::Mutex<T>,
predicate: (sync::Mutex<bool>, sync::Condvar)
}
impl<T> Monitor<T> {
pub fn wait(&self) -> Result<(),sync::PoisonError<sync::MutexGuard<bool>>> {
let mut open = try!(self.0.predicate.0.lock());
while !*open {
open = try!(self.0.predicate.1.wait(open));
}
Ok(())
}
pub fn lock(&self) -> Result<sync::MutexGuard<T>, sync::PoisonError<sync::MutexGuard<T>>> {
self.0.data.lock()
}
pub fn reset(&mut self) -> Result<(),sync::PoisonError<sync::MutexGuard<bool>>> {
let mut open = try!(self.0.predicate.0.lock());
*open = false;
Ok(())
}
pub fn wakeup_all(&mut self) -> Result<(),sync::PoisonError<sync::MutexGuard<bool>>> {
let mut open = try!(self.0.predicate.0.lock());
*open = true;
self.0.predicate.1.notify_all();
Ok(())
}
}
После первого пробуждения мои читатели могут пропустить чтение. Вероятно, потому что они все еще удерживают блокировку данных, пока предикат снова переключается. Я видел это в своем тестовом коде только с одним читателем и одним писателем.
Затем возникает сложность, когда сбрасывать Monitor
, в идеале он должен быть заблокирован после того, как все читатели имели возможность просмотреть данные. Это может вызвать взаимоблокировку, если читатель будет игнорировать свои мониторы (нет гарантии, что они будут обслуживать каждый вызов пробуждения).
Нужно ли мне использовать какую-то систему отслеживания чтения с тайм-аутами и отслеживать, когда приходят новые данные, в то время как чтение монитора все еще обслуживается? Существует ли существующая парадигма, о которой мне следует знать?