Fix unreliable closing of the send end

(write Nothing) into a bounded queue can block for two reasons:

  - the queue is full and there is no reader, in which case we
    shouldn't do it, because it would be a deadlock,

  - the queue is full temporariliy (the reader is busy), in which case
    we _should_ signal the end of stream.

So the (write Nothing <|> pure ()) is flaky, it doesn't distinguish
the two cases, and thus fails to signal the end of the stream in the
second case.

The fix is to use the same kind of (TVar Bool) signaling as in the
other direction.  As an additional benefit, this change somewhat
simplifies the code.