From 45dc4228df728ac0b4fa173cccad983dcb4e19c6 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Wed, 12 Jun 2024 10:01:15 -0400 Subject: [PATCH 1/2] wait before taking on both --- stdlib/REPL/src/LineEdit.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index d3072978d2537..4af16275e572e 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -2830,15 +2830,19 @@ function prompt!(term::TextTerminal, prompt::ModalInterface, s::MIState = init_s old_state = mode(s) l = Base.ReentrantLock() t = @async while true - fcn = take!(s.async_channel) - status = @lock l fcn(s) + wait(s.async_channel) + status = @lock l begin + fcn = take!(s.async_channel) + fcn(s) + end status ∈ (:ok, :ignore) || break end Base.errormonitor(t) while true - kmap = keymap(s, prompt) - fcn = match_input(kmap, s) + eof(term) || peek(term, Char) # wait before locking but don't consume @lock l begin + kmap = keymap(s, prompt) + fcn = match_input(kmap, s) kdata = keymap_data(s, prompt) s.current_action = :unknown # if the to-be-run action doesn't update this field, # :unknown will be recorded in the last_action field From e7d2dea28ec2c5b07fb5b8824b1d7228ac36fd26 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Wed, 12 Jun 2024 12:44:13 -0400 Subject: [PATCH 2/2] add spawn to free input reader from sticky repl task --- stdlib/REPL/src/LineEdit.jl | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index 4af16275e572e..76b151a79817a 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -2823,22 +2823,23 @@ keymap_data(ms::MIState, m::ModalInterface) = keymap_data(state(ms), mode(ms)) function prompt!(term::TextTerminal, prompt::ModalInterface, s::MIState = init_state(term, prompt)) Base.reseteof(term) + l = Base.ReentrantLock() + t1 = Threads.@spawn :interactive while true + wait(s.async_channel) + status = @lock l begin + fcn = take!(s.async_channel) + fcn(s) + end + status ∈ (:ok, :ignore) || break + end raw!(term, true) enable_bracketed_paste(term) try activate(prompt, s, term, term) old_state = mode(s) - l = Base.ReentrantLock() - t = @async while true - wait(s.async_channel) - status = @lock l begin - fcn = take!(s.async_channel) - fcn(s) - end - status ∈ (:ok, :ignore) || break - end - Base.errormonitor(t) - while true + # spawn this because the main repl task is sticky (due to use of @async and _wait2) + # and we want to not block typing when the repl task thread is busy + t2 = Threads.@spawn :interactive while true eof(term) || peek(term, Char) # wait before locking but don't consume @lock l begin kmap = keymap(s, prompt) @@ -2873,7 +2874,10 @@ function prompt!(term::TextTerminal, prompt::ModalInterface, s::MIState = init_s end end end + return fetch(t2) finally + put!(s.async_channel, Returns(:done)) + wait(t1) raw!(term, false) && disable_bracketed_paste(term) end # unreachable