|
From: Daniel J S. <dan...@ie...> - 2004-01-10 07:24:22
|
Ethan Merritt wrote:
>On Friday 09 January 2004 14:50, Daniel J Sebald wrote:
>
>
>>If you turn off buffering immediately after startup, what if a
>>number of Gnuplot commands are already in the buffer?
>>
>>
>
>Since piping now works, this is demonstrated not to be a problem.
>Of course if you have a test example that fails, I will glumly
>retract that optimistic statement.
>
>
>
>>Thus the only way to resolve the race condition, in one form
>>or another from Gnuplot, is for there to be an ability for the "setvbuf"
>>command to return the contents of the buffer right before it was
>>changed.
>>
>>
>
>Not possible. See "man setvbuf".
>
I searched for info. As usual, the man doesn't seem to give details of
the tricky aspects.
>>1) Fix up the I/O scheme so that gnuplot doesn't wait on keyboard
>>input. Whenever keyboard input is available then parse it.
>>
>>
>
>Now you are getting near to the heart of it. Most of our current
>problem comes from not being able to tell when input is available
>without trying to read it. And if we try to read it, then we are stuck
>waiting until success.
>
>The central problem is that there are few (actually none that I know of)
>portable methods of reading from two or more input sources at the same
>time. I know perfectly well how to do it under VMS but, sadly, other
>operating systems are not so capable [grin, duck, and run].
>
You'll have to forgive me. I've tried following the code to see exactly
the path that the commands come in via stdin, where the pipe is read for
the mouse, etc. and I'm having a difficult time keeping track of it all.
So I'm going to play devil's advocate here and ask naive questions.
I find it hard to fathom that this is not possible. I mean, doesn't
this seem like a fundamental task of operating systems? That is, to
distribute I/O around the system? Let's consider an fread() or a
fgets() or fgetc(). Can't I just do an fread() from the stdin (the
place where the commands are typed in) and whatever is there I store in
a "command buffer" and as I'm putting the characters in a command buffer
I watch for the "new line" or "end of gnuplot command" character. When
the end of command character is found, then shuffle that string over to
the current command parsing stuff. If there is nothing in the buffer or
there are less characters than asked for, doesn't the fread() simple
return and EOF or -1 or number of bytes read?
Then, do the same with the mouse stream.
It sounds to me, correct me if I'm wrong, that Gnuplot is now attempting
a graceful method of trying to get a complete command from both the
mouse and the keyboard whenever either is available. Is this what you
mean by asynchronous? If an operating system can do that, that is
impressive. But no, I would not expect that to be a feature of all
operating systems. It seems to me then, that for Gnuplot (to be
portable) is the one that needs to do all the work of reconstructing the
input streams.
Let me attempt a description of what I'm saying without writing the full
code. Say there is a "keyboard_stream" and a "mouse_stream". We make
internal buffers inside Gnuplot of length, say 200.
keyboard_command_buff[201];
mouse_command_buff[201];
keyboard_buff_ptr = 0;
mouse_buff_ptr = 0;
while (not_end_of_Gnuplot) {
int number_chars;
/* Check if there is keyboard input, if so check if a valid command
is complete. */
number_chars = fread(keyboard_stream,
&keyboard_command_buff[keyboard_buff_ptr], 200-keyboard_buff_ptr); /*
That is, read up to whatever is space is left in the buffer */
if (number_chars > 0) {
[search through the characters just read and test for end of command]
if (this is valid end of command) {
execute gnuplot command;
copy any chunk left in buffer to the start of buffer;
keyboard_buff_ptr = 0;
} else {
keyboard_buff_ptr += number_chars;
}
}
if (end of buffer has been reached)
[issue error to the console]
/* Check if there is mouse input, if so check if a valid mouse
string is complete. */
[Do the same for the mouse stream as is done above for the keyboard.]
}
The input method just keeps going around in the loop and never waits on
anything. It may be that only a few characters are read at a time, but
so what. It isn't like this needs to be super efficient as though it
were a time critical communication scenario. We're waiting on mouse and
keyboard commands which are rather slow I assume.
Is there some issue with buffered mouse characters piling up in the
stream while a Gnuplot command is being processed?
(more below)
>The current scheme under linux depends on select(). This scheme,
>problems and all, is the closest thing to simultaneous/asynchronous
>input that I know of in standard linux/unix.
>That said, I am hardly an expert on linux asynchronous I/O.
>
>Here is the bind we are in, as I understand it for the linux+X11 case:
>
Nice summary. Thanks.
(more below)
>A) We have terminal input coming in on stdin; we have mouse input
> coming in via a pipe.
>
>B) These two input sources are asynchrounous. That is, we don't
> know which one will be the next to provide new input.
>
The scheme I describe above attempts to handle this, I think.
>C) We have non-mouse (font, window size, etc) information coming
> back over the pipe also. This could be split off from the mouse pipe,
> but that does not make things any easier, so let's disregard it.
>
This should be fine I think.
>D) If you do a read/scanf/gets/whatever from stdin then you will
> miss all mouse input until you get the next chunk of terminal input.
>
Please explain why this is. I'm to lazy to do a test trial at this
hour, but won't fread() on stdin just send back and EOF or -1 or
something if there are no characters in the buffer?
>E) Conversely if you do a read/scanf/gets/whatever on the mouse pipe
> then you can't even look for new terminal commands until after the
> next mouse event (which may never arrive).
>
>F) The usual way around this dilemma is to use poll or select to notify
> us when either or both of two input streams is presenting new data.
> We currently use select in X11_waitforinput().
>
Yes, this is one way. But if "fread()" is inherently forced to return
something even if the buffer is empty, isn't that a form of polling the
input as well? As I said before, it seems to me that current Gnuplot
really isn't wanting polling for "characters available", rather it is
attempting to poll for "gnuplot command in buffer available" and "mouse
command in buffer available".
>G) Unfortunately, poll/select notification depends on whether the
> input stream is buffered or non-buffered. I do not know if this is
> supposed to be the case, but that's what we see in practice.
>
>H) More things seem to work when stdin is set to unbuffered,
> hence the call to setvbuf(). Other things broke, because this caused
> the current contents of the buffer to be lost. Note that this behaviour
> is not documented anywhere I can find, but it makes sense and is
> easily demonstrated. I am optimistic that this problem is minimized
> by moving the setvbuf() call to the head of the program.
>
>I) Just to make things a little bit worse, we have commands like
> 'pause <n>' and 'pause mouse'.
>
Hey, these are easy to handle for the scheme above. Deactivate the
input test according to some timer, i.e.,
if (time expired >= n) {
n = 0;
/* The junk above */
}
Gnuplot will simply stop checking for input in the appropriate stream
for <n> seconds. (This may not work... but that would be my first
attempt at such.)
>J) Just to make things a little bit worse yet, we try to support gnu
> libreadline, which has its own quirks about handling input streams.
>
I would hope the this is fairly transparent to the C environment.
>K) And if all that was not complicated enough, people want to cut-and-paste
> from X11. This involves cooperation from the X server and from the
> application windows (xterm, nedit, or whatever) on both the cut and the
> paste end. So far as I know, there is no guarantee that just because
> it works for gnuplot running in an xterm window it will also work inside
> konsole or kterm or Eterm or <alphabetofyourchoice>term.
>
Again, I would hope this is transparent to the C environment. The
cutting and pasting simply puts stuff into the "stdin" buffer, I'm guessing.
>
>Now that I understand the problem with setvbuf(), I am considerably
>more hopeful that we can get everything to work using the current
>scheme. More hopeful than I was a week ago.
>poll/select is *supposed* to work, after all.
>But items I, J and K may still cause us problems.
>
>
>
>>3) Since gnuplot only has a "current plot" replot and not information
>>for all its plots, there needs to be some variable that keeps track of
>>which plot number corresponds with the "current plot" replot info. That
>>way, the "replot" command can be reissued when the window number and the
>>replot info match.
>>
>>
>
>That is a separate topic.
>Let's not mix the two.
>
Right. That is something completely different. I'm confused enough the
way it is.
Anyway, tell me what is wrong with the approach I describe. I guess my
main point is that if you want Gnuplot to be portable, it's the one that
will have to do all the work in determining "valid command line string
available" and "valid mouse string available", not the system.
Dan
|