Closing mpsc channel from receiving end


#1

Hey guys,
I am writing a small space Invaders clone for the terminal, using terminal. The built in async input functions only sends bytes, whereas the standard, blocking variant returns a Key enum, which is much easier to work with (recognizing special keys and so on)
So I decided to build my own asynchronous function, spawning a thread and sending the inputs over a mpsc channel to the main thread. However I only need async input in the game loop and if that finishes, I’d like to kill this thread. There doesn’t seem a way to do this though, when I kill it from inside when the channel was closed, the thread keeps locking stdin until the next input after exit, which fails to send then. Is there a convenient way to avoid this?


#2

I’ll supply a playground as soon as I have time, sorry if that long text is hard to follow


#3

As far as I know forcibly killing a thread is generally considered a bad idea, as it will leave all locks locked, leak, etc.

If the thread is blocked and waiting on something, then there isn’t much you can do, because even if you had a communication channel to the thread, it wouldn’t receive it.

However, if the thread can be periodically unblocked (e.g. there’s poll timeout), then it can check a shared flag. It could be as simple as having a global static atomic value which you flip in main thread, and the input thread checks it between keystrokes and quits when it sees the flag changed.


#4

You can try sending a SIGINT to the background thread; if it’s blocked on reading from stdin, it’ll pop out with io::Error(ErrorKind::Interrupted) and you’ll know it’s time for it to exit.

It’s unclear whether another game loop can start. In that case, you probably don’t want to start a new thread again. Instead, you can keep this one around but make it recv a control message (over a mpsc::channel) that tells it to start processing input again.


#5

A timeout sounds great, haven’t thought of that at all.
Hopefully termion supports this though.

I will also look into that SIGINT thing, haven’t worked with that before. Is it Cross-Platform?


#6

Windows will require different code, I believe, but posix platforms should work.

Doesn’t termion provide a raw byte parser to turn input bytes into typed events? Perhaps you can use its async input reader to get the bytes and then parse them.


#7

Yeah, now that you say it I remember this function, totally forgot about that. Nice stuff, thanks :smiley: