Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Ghci out of the Arc<Mutex<_>> #39

Merged
merged 1 commit into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 22 additions & 33 deletions src/ghci/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl Ghci {
error_path: Option<Utf8PathBuf>,
setup_commands: Vec<String>,
test_command: Option<String>,
) -> miette::Result<Arc<Mutex<Self>>> {
) -> miette::Result<Self> {
let start_instant = Instant::now();

let mut child = {
Expand Down Expand Up @@ -132,7 +132,7 @@ impl Ghci {
let stderr_handle = task::spawn(async { Ok(()) });
let stdin_handle = task::spawn(async { Ok(()) });

let ret = Arc::new(Mutex::new(Ghci {
let mut ret = Ghci {
command: command_arc,
process: child,
stdout: stdout_handle,
Expand All @@ -144,7 +144,7 @@ impl Ghci {
error_path: error_path.clone(),
setup_commands: setup_commands.clone(),
test_command,
}));
};

// Three tasks for my three beautiful streams.
let stdout = task::spawn(
Expand Down Expand Up @@ -185,7 +185,6 @@ impl Ghci {

// Now, replace the `JoinHandle`s with the actual values.
{
let mut ret = ret.lock().await;
ret.stdout = stdout;
ret.stderr = stderr;
ret.stdin = stdin;
Expand Down Expand Up @@ -222,16 +221,15 @@ impl Ghci {
let span = tracing::debug_span!("Start-of-session sync");
let _enter = span.enter();
// Sync up for any prompts.
let mut guard = ret.lock().await;
guard.sync().await?;
ret.sync().await?;
// Get the initial list of loaded modules.
guard.refresh_modules().await?;
ret.refresh_modules().await?;
}

tracing::info!("ghci started in {:.2?}", start_instant.elapsed());

// Run the user-provided test command, if any.
ret.lock().await.test().await?;
ret.test().await?;

Ok(ret)
}
Expand All @@ -240,10 +238,7 @@ impl Ghci {
///
/// This may fully restart the `ghci` process.
#[instrument(skip_all, level = "debug")]
pub async fn reload(
this: Arc<Mutex<Self>>,
events: Vec<FileEvent>,
) -> miette::Result<Arc<Mutex<Self>>> {
pub async fn reload(&mut self, events: Vec<FileEvent>) -> miette::Result<()> {
// TODO: This method is pretty big -- we should break it up.

// Once we know which paths were modified and which paths were removed, we can combine
Expand All @@ -254,7 +249,6 @@ impl Ghci {
let mut needs_reload = Vec::new();
let mut add = Vec::new();
{
let guard = this.lock().await;
for event in events {
match event {
FileEvent::Remove(path) => {
Expand All @@ -270,7 +264,7 @@ impl Ghci {
break;
}
FileEvent::Modify(path) => {
if guard.modules.contains_source_path(&path)? {
if self.modules.contains_source_path(&path)? {
// We can `:reload` paths `ghci` already has loaded.
tracing::debug!(?path, "Needs reload");
needs_reload.push(path);
Expand All @@ -290,16 +284,15 @@ impl Ghci {
format_bulleted_list(&needs_restart)
);
// TODO: Probably also need a restart hook / `.cabal` hook / similar.
let mut guard = this.lock().await;
guard.stop().await?;
let command = guard.command.clone();
return Self::new(
command,
guard.error_path.clone(),
guard.setup_commands.clone(),
guard.test_command.clone(),
self.stop().await?;
let new = Self::new(
self.command.clone(),
self.error_path.clone(),
self.setup_commands.clone(),
self.test_command.clone(),
)
.await;
.await?;
let _ = std::mem::replace(self, new);
}

let needs_add_or_reload = !add.is_empty() || !needs_reload.is_empty();
Expand All @@ -311,7 +304,7 @@ impl Ghci {
format_bulleted_list(&add)
);
for path in add {
let add_result = this.lock().await.add_module(path).await?;
let add_result = self.add_module(path).await?;
if let Some(CompilationResult::Err) = add_result {
compilation_failed = true;
}
Expand All @@ -324,9 +317,7 @@ impl Ghci {
format_bulleted_list(&needs_reload)
);
let (sender, receiver) = oneshot::channel();
let guard = this.lock().await;
guard
.stdin_channel
self.stdin_channel
.send(StdinEvent::Reload(sender))
.await
.into_diagnostic()?;
Expand All @@ -342,22 +333,20 @@ impl Ghci {
} else {
// If we loaded or reloaded any modules, we should run tests.
let (sender, receiver) = oneshot::channel();
let guard = this.lock().await;
guard
.stdin_channel
self.stdin_channel
.send(StdinEvent::Test {
sender,
test_command: guard.test_command.clone(),
test_command: self.test_command.clone(),
})
.await
.into_diagnostic()?;
receiver.await.into_diagnostic()?;
}
}

this.lock().await.sync().await?;
self.sync().await?;

Ok(this)
Ok(())
}

/// Sync the input and output streams of this `ghci` session. This will block until all input
Expand Down
8 changes: 3 additions & 5 deletions src/watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use std::time::Duration;

use camino::Utf8PathBuf;
use tokio::runtime::Handle;
use tokio::sync::Mutex;
use tokio::task::block_in_place;
use tokio::task::JoinHandle;
use tracing::instrument;
Expand Down Expand Up @@ -39,7 +38,7 @@ pub struct Watcher {
impl Watcher {
/// Create a new [`Watcher`] from a [`Ghci`] session.
pub fn new(
ghci: Arc<Mutex<Ghci>>,
ghci: Ghci,
watch: &[Utf8PathBuf],
debounce: Duration,
poll: Option<Duration>,
Expand Down Expand Up @@ -70,9 +69,8 @@ impl Watcher {
}
}

#[derive(Clone)]
struct ActionHandler {
ghci: Arc<Mutex<Ghci>>,
ghci: Ghci,
}

impl ActionHandler {
Expand All @@ -94,7 +92,7 @@ impl ActionHandler {

let events = file_events_from_action(&action)?;
if !events.is_empty() {
self.ghci = Ghci::reload(self.ghci.clone(), events).await?;
self.ghci.reload(events).await?;
}

Ok(())
Expand Down