Open GoogleCodeExporter opened 9 years ago
The way the input system is built, it's not very easy to add a 'truly' blocking
method that is using the underlying input stream for blocking I/O. I'd rather
not add a method that simulates blocking input, since it's quite easy to do
this yourself:
Key key = terminal.readInput();
while(key == null) {
Thread.sleep(1);
key = terminal.readInput();
}
This should do the trick and shouldn't consume any CPU. If sleeping for 1 ms is
too much, you can probably try Thread.yield() instead.
Original comment by mab...@gmail.com
on 7 Oct 2012 at 3:19
I tough use the sleep method to solve this issue. I was afraid a lack of
responsiveness with this solution. I'll try the yield method. Is this solution
you've chosen in the GUI layer?
Thanks for your answer and help.
Chris
Le 7 oct. 2012 à 05:19, lanterna@googlecode.com a écrit :
Original comment by christia...@gmail.com
on 7 Oct 2012 at 1:07
No, I'm doing sleep(1):
if(!repainted) {
try {
Thread.sleep(1);
}
catch(InterruptedException e) {}
}
I did a quick test and it seems both Thread.yield() and Thread.sleep(0) will
cause one CPU core to max load. Thread.sleep(0, 1) (and of course
Thread.sleep(1) ) seemed to work though.
public class YieldTest {
public static void main(String[] args) throws InterruptedException {
while(true) {
Thread.sleep(0, 1);
}
}
}
Original comment by mab...@gmail.com
on 8 Oct 2012 at 1:32
Fine, thanks you :)
Christian
Le 8 oct. 2012 à 03:32, lanterna@googlecode.com a écrit :
Original comment by christia...@gmail.com
on 8 Oct 2012 at 6:37
Do I understand correctly? It is your intention never to add a blocking
version of readInput?
This seems like a fundamental design flaw to me, since every individual
application will now need to pick a sleep value, and make a decision to trade
off responsiveness for CPU usage. Particularly in virtualized environments,
where machine resources are over-committed, and one machine can be running
dozens of OSes, each with dozens of idle applications, it is not appropriate to
have every application on the system wake up 1000 times per second just to poll
for input and discover that it has nothing to do.
One easy possibility would be to add a blocking readInput call that is
initially implemented using the sleep technique you descrive. That way,
Lanterna at least appears to offer a blocking call, and you leave the door open
in the future if you change your mind and want to offer a better implementation.
Original comment by p.r.do...@gmail.com
on 19 Jun 2013 at 11:55
True, but if you use blocking I/O then the screen won't be able to
redraw/refresh the screen until there is input available. I chose this polling
approach mostly because I didn't want to multi-thread it (and also, for my
purposes of writing this library, sleep(1) wasn't a problem).
However, with the next major revision of Lanterna, I'm trying to make the whole
stack thread-safe and could probably put both input and output on separate
threads; truly enabling blocking input. But then again, there would be another
thread doing polling of the input queue to find out if there's anything new...
Original comment by mab...@gmail.com
on 24 Jun 2013 at 11:45
I believe that this is a very, very, very important feature for any server
application using lanterna. I am evaluating using it myself (kudos btw, nice
lib so far!) and the only two stumbling blocks so far have been the privateness
of the util functions to en/disable local echo, linemode etc. in TelnetTerminal
-- and the lack of a blocking readInput.
I'd suggest using the current read(buf,off,len) implementation of the
InputStream derived guy in TelnetTerminal, adding a nonblocking parameter to
it, and change the fillBuffer() stuff from:
if(inputStream.available() > 0) {
fillBuffer();
}
if(bytesInBuffer == 0) {
return -1;
}
to:
if (inputStream.availabe() > 0 || !nonblocking) {
fillBuffer();
}
while (bytesInBuffer == 0) {
if (nonblocking)
return -1;
else
fillBuffer();
}
with appropriate
then, implement read(buf, off, len) by either read(buf, off, len, true) or
read(buf, off, len, false), and make the four-argument version public. Also,
implement read() by read(_, _, _, false).
Rationale: Yes, this blocks the thread. But usually there's two sides to a
socket connection you are interested in. There's the reader side and the writer
side. There's potentially four kinds of interactions that I see (use-case
wise): server-push: write, client-push: read, client-request-reply:
read-and-then-write, server-client-reply: write-and-then-read.
In server-push, obviously, I know that I want to push.
In client-push, I'd like to be notified, and then react.
In client-request-reply, I'd like to be notified, and then react (and reply).
In server-client-reply, I'd like to write, and then be notified of an answer.
This also goes along with an architecture that gives each connection one thread
to play on. The Terminal (and Screen) instances there just live on that one
thread. My computational loop(s) live on (an)other thread(s). Input from the
threads are transported to the other threads in a thread-safe manner already
anyways. I'd like to be able to just sleep on the client, waiting on input. If
the computational loop decides it wants to push something, it would just
interrupt the thread (the read from a socket's input stream should throw an
InterruptedIOException as suggested by the (closed) bugreport at
http://bugs.java.com/view_bug.do?bug_id=4905626 ), I'd handle the
InterruptedIOException in my client, knowing that I'd be pushing something
next; push; and return to my read-block-sleep.
With this approach, don't you think this is suitable for implementation? (I'll
be trying, but thought I'd ask if you, being familiar with the code obviously,
see a glaring problem with it). It should be giving both blocking and
non-blocking I/O depending on your needs and design (1:1 thread:telnetTerminal
or 1:n thread:telnetTerminal).
Original comment by ben...@multimud.net
on 2 Sep 2014 at 8:12
Sounds reasonable. Given that you are mentioning TelnetTerminal, are you using
Lanterna 3 by any chance?
Original comment by mab...@gmail.com
on 21 Sep 2014 at 2:14
Original issue reported on code.google.com by
christia...@gmail.com
on 5 Oct 2012 at 2:44