Prevent race condition when watching model

This temporarily leads to two initial loads of the model. I'm going to
fix that in subsequent commits.
This commit is contained in:
Hanno Braun 2022-03-18 15:27:01 +01:00
parent 1227f69d06
commit 6568d0c8c3
2 changed files with 11 additions and 9 deletions

View File

@ -80,15 +80,6 @@ fn main() -> anyhow::Result<()> {
parameters.insert(key, value); parameters.insert(key, value);
} }
// Since we're loading the model before setting up the watcher below,
// there's a race condition, and a modification could be missed between
// those two events.
//
// This can't be addressed with the current structure, since the watcher
// closure takes ownership of the model.
//
// This is being tracked in the following issue:
// https://github.com/hannobraun/fornjot/issues/32
let shape = model.load(&parameters)?; let shape = model.load(&parameters)?;
let shape_processor = ShapeProcessor::new(args.tolerance)?; let shape_processor = ShapeProcessor::new(args.tolerance)?;

View File

@ -5,6 +5,7 @@ use std::{
path::PathBuf, path::PathBuf,
process::Command, process::Command,
sync::mpsc, sync::mpsc,
thread,
}; };
use notify::Watcher as _; use notify::Watcher as _;
@ -100,6 +101,8 @@ impl Model {
parameters: HashMap<String, String>, parameters: HashMap<String, String>,
) -> Result<Watcher, Error> { ) -> Result<Watcher, Error> {
let (tx, rx) = mpsc::sync_channel(0); let (tx, rx) = mpsc::sync_channel(0);
let tx2 = tx.clone();
let watch_path = self.src_path.clone(); let watch_path = self.src_path.clone();
let mut watcher = notify::recommended_watcher( let mut watcher = notify::recommended_watcher(
@ -155,6 +158,14 @@ impl Model {
watcher.watch(&watch_path, notify::RecursiveMode::Recursive)?; watcher.watch(&watch_path, notify::RecursiveMode::Recursive)?;
// To prevent a race condition between the initial load and the start of
// watching, we'll trigger the initial load here, after having started
// watching.
//
// Will panic, if the receiving end has panicked. Not much we can do
// about that, if it happened.
thread::spawn(move || tx2.send(()).unwrap());
Ok(Watcher { Ok(Watcher {
_watcher: Box::new(watcher), _watcher: Box::new(watcher),
channel: rx, channel: rx,