Polling keyboard input looking for e.g. 'q' in a loop to 'gracefully' terminate execution

I spent some time about a month ago trying to get something like this to work. What I came up with is kind of clumsy, but it does the job. The basic issue is that julia doesn’t provide a good way to check an input stream without blocking. My solution was to call read asynchronously; it still blocks while waiting for input, but it will yield if there is no input, and allow your main computation to continue.

If you use this script, you will want to replace the sleep(0.1) with yield() to ensure that you check the input buffer each iteration.

function monitorInput()
    # Put STDIN in 'raw mode'
    ccall(:jl_tty_set_mode, Int32, (Ptr{Void}, Int32), STDIN.handle, true) == 0 || throw("FATAL: Terminal unable to enter raw mode.")

    inputBuffer = Channel{Char}(100)

    @async begin
        while true
            c = read(STDIN, Char)
            put!(inputBuffer, c)
        end
    end
    return inputBuffer
end


inputBuffer = monitorInput()
for i in 1:100
    if isready(inputBuffer) && take!(inputBuffer) == 'q'
        break
    end
    print('\r', i)
    sleep(0.1)
end

println("\nPlease have a nice day!")

Also, I was never able to get julia back out of “raw mode” to say, ask for a filename to store the partially finished computation. If anyone has a pointer on that, I would love to hear about it.

4 Likes