rethinking interpreter <-> gui interaction

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

rethinking interpreter <-> gui interaction

John W. Eaton
Administrator
Currently, most communication between the Octave interpreter and GUI is
managed by the octave_link class interface defined in the interpreter.
The actions specific to the GUI are implemented in the GUI by the
octave_qt_link class.  These classes provide a thread-safe way for
interpreter and GUI to ask each other to perform actions.  For example,
the interpreter may notify the GUI that the workspace has changed so
that the workspace view in the GUI may be updated.  Or the GUI may ask
the interpreter to invoke a function to change the current directory.

As I understand it, there are four cases that may need to be handled:

   1. The interpreter makes a request or sends a notification to the GUI
and does not need an immediate result.  The interpreter and GUI threads
may continue to run independently.  For example, the inteprerter
notifies the GUI that the current working directory has changed.  The
GUI will respond by updating the directory displayed in the file browser
widget but the interpreter may continue executing while the GUI performs
this action.

   2. The interpreter makes a request or sends a notification to the GUI
and requires an immediate result.  The interpreter thread must be
suspended and wait until the GUI thread is finished with the action.
For example, and interpreter asks the GUI to display an interactive file
selection dialog to obtain a file name from the user.  This action must
be completed before the interpreter may continue executing.

   3. The GUI asks the interpreter to perform an action and does not
need an immediate result.  For example, if the user changes the current
directory through the GUI file browser widget the GUI will ask the
interpreter to execute the "cd" function.  An immediate result is not
needed, so the GUI may continue to execute while this action is
performed.  The interpreter will execute it separately and signal the
GUI when the action is performed so that the file browser may display
the new directory.

   4. The GUI asks the interpreter to perform an action and requires an
immediate result.  The GUI thread must be suspended and wait until the
interpreter thread is finished with the action.  Although this type of
interaction is possible, I'm not sure what examples of it that we
currently have, or whether any that we do have could be rewritten to
behave like item 3 above so that the requested action is performed by
the interpreter and the GUI is notified of the result using a separate
signal sent from the interpreter.

For actions like items 1 and 2 above, the interpreter calls a function
in the GUI that simply emits a Qt signal that is connected to a Qt slot.
  These connections are thread safe and queued if needed.  (The only
reason we don't just emit the Qt signal directly from the interpreter is
to avoid making Qt a direct dependency of the interpreter.)

For actions like items 3 and 4 above, the GUI queues a function that the
interpreter will execute when it is otherwise idle.

The octave_link class is inflexible in that it declares a set of about
30 pure virtual functions that all must be defined by any GUI that
wishes to work with the GUI.  So instead of allowing the GUI to
subscribe to whatever signals it chooses, it must explicitly define
functions handle (or ignore) all of them.  It is also not possible for
the GUI to easily (or independently) attach multiple actions to a signal.

I am looking for alternatives to the current design of the octave_link
class.  It must be thread safe and it should be easy to connect
(disconnect) signals to (from) actions.  It should be possible to attach
a signal to multiple actions or to have multiple signals trigger a
single action.

This all begins to sound a lot like the Qt signal/slot mechanism,
something that we should probably not be re-inventing.  However, I still
hesitate to bring that into the interpreter as it would introduce Qt as
a direct dependency of the interpreter (interpreter objects that need to
emit signals or define slots would have to inherit from the QObject
class).  I would also like to allow for the possibility of other GUI
interfaces that could connect to these interpreter signals and actions
without requiring Qt.

Comments and suggestions welcome.

jwe

Reply | Threaded
Open this post in threaded view
|

Re: rethinking interpreter <-> gui interaction

Daniel Sebald
On 7/1/19 2:47 PM, John W. Eaton wrote:

> Currently, most communication between the Octave interpreter and GUI is
> managed by the octave_link class interface defined in the interpreter.
> The actions specific to the GUI are implemented in the GUI by the
> octave_qt_link class.  These classes provide a thread-safe way for
> interpreter and GUI to ask each other to perform actions.  For example,
> the interpreter may notify the GUI that the workspace has changed so
> that the workspace view in the GUI may be updated.  Or the GUI may ask
> the interpreter to invoke a function to change the current directory.
>
> As I understand it, there are four cases that may need to be handled:
>
>    1. The interpreter makes a request or sends a notification to the GUI
> and does not need an immediate result.  The interpreter and GUI threads
> may continue to run independently.  For example, the inteprerter
> notifies the GUI that the current working directory has changed.  The
> GUI will respond by updating the directory displayed in the file browser
> widget but the interpreter may continue executing while the GUI performs
> this action.
>
>    2. The interpreter makes a request or sends a notification to the GUI
> and requires an immediate result.  The interpreter thread must be
> suspended and wait until the GUI thread is finished with the action. For
> example, and interpreter asks the GUI to display an interactive file
> selection dialog to obtain a file name from the user.  This action must
> be completed before the interpreter may continue executing.
>
>    3. The GUI asks the interpreter to perform an action and does not
> need an immediate result.  For example, if the user changes the current
> directory through the GUI file browser widget the GUI will ask the
> interpreter to execute the "cd" function.  An immediate result is not
> needed, so the GUI may continue to execute while this action is
> performed.  The interpreter will execute it separately and signal the
> GUI when the action is performed so that the file browser may display
> the new directory.
>
>    4. The GUI asks the interpreter to perform an action and requires an
> immediate result.  The GUI thread must be suspended and wait until the
> interpreter thread is finished with the action.  Although this type of
> interaction is possible, I'm not sure what examples of it that we
> currently have, or whether any that we do have could be rewritten to
> behave like item 3 above so that the requested action is performed by
> the interpreter and the GUI is notified of the result using a separate
> signal sent from the interpreter.
>
> For actions like items 1 and 2 above, the interpreter calls a function
> in the GUI that simply emits a Qt signal that is connected to a Qt slot.
>   These connections are thread safe and queued if needed.  (The only
> reason we don't just emit the Qt signal directly from the interpreter is
> to avoid making Qt a direct dependency of the interpreter.)
>
> For actions like items 3 and 4 above, the GUI queues a function that the
> interpreter will execute when it is otherwise idle.
>
> The octave_link class is inflexible in that it declares a set of about
> 30 pure virtual functions that all must be defined by any GUI that
> wishes to work with the GUI.  So instead of allowing the GUI to
> subscribe to whatever signals it chooses, it must explicitly define
> functions handle (or ignore) all of them.  It is also not possible for
> the GUI to easily (or independently) attach multiple actions to a signal.
>
> I am looking for alternatives to the current design of the octave_link
> class.  It must be thread safe and it should be easy to connect
> (disconnect) signals to (from) actions.  It should be possible to attach
> a signal to multiple actions or to have multiple signals trigger a
> single action.
>
> This all begins to sound a lot like the Qt signal/slot mechanism,
> something that we should probably not be re-inventing.  However, I still
> hesitate to bring that into the interpreter as it would introduce Qt as
> a direct dependency of the interpreter (interpreter objects that need to
> emit signals or define slots would have to inherit from the QObject
> class).  I would also like to allow for the possibility of other GUI
> interfaces that could connect to these interpreter signals and actions
> without requiring Qt.
>
> Comments and suggestions welcome.

Yes, 3 sounds like the right idea.

My memory is the following patch is designed as such:

https://savannah.gnu.org/patch/?func=detailitem&item_id=8016#options

There shouldn't be a need to make either side of the link suspend and
wait on anything.  To make the GUI wait feels unnatural.  Instead, you'd
like to allow the user to edit files and whatnot when a long worker
process is running.  Perhaps there might be some arrangement in which a
sequence of events has to happen in the GUI, but I'm pretty sure one can
think of a dynamic signal/slot connection to do that.

In the patch, that is the key, dynamic connections to a "queue" result.
There currently is a queuing mechanism for commands, say "cd" or "pwd".
The patch extends that idea to include a broadcaster.  In the latter
command, some information is returned in an octave_value class.  In the
GUI, the object that wants the information puts the command "pwd" in the
queue and dynamically makes a connection to the queue result or
"broadcast".  The queue also keeps a record of the requesting object's
ID (this) so that on the return trip all the objects that may be
connected to the broadcaster can compare their "this" against the ID to
recognize, "Hey, that's my data!".  Once the GUI has its data, it can
choose to disconnect so that the broadcaster doesn't get too many
subscribers--or whatever analogy one wants to use.

Dan

Reply | Threaded
Open this post in threaded view
|

Re: rethinking interpreter <-> gui interaction

John W. Eaton
Administrator
On 7/1/19 11:57 PM, Daniel J Sebald wrote:
> On 7/1/19 2:47 PM, John W. Eaton wrote:

> There shouldn't be a need to make either side of the link suspend and
> wait on anything.

Don't functions like inputdlg have to wait for a result?  As I
understand it, function like that ask the GUI to create a dialog and
then they can't return until the dialog is closed and a result is
returned (or an error is thrown).

> To make the GUI wait feels unnatural.  Instead, you'd
> like to allow the user to edit files and whatnot when a long worker
> process is running.

Yes, I agree that it should be possible to do something like editing
files as that doesn't generally require the interpreter to perform any
action.  But what should happen if the GUI asks the interpreter to
perform some action when it is already busy executing some other code?
At what point is it safe for the interpreter to check the command queue
and call other functions?

> In the patch, that is the key, dynamic connections to a "queue" result.
> There currently is a queuing mechanism for commands, say "cd" or "pwd".
> The patch extends that idea to include a broadcaster.  In the latter
> command, some information is returned in an octave_value class.  In the
> GUI, the object that wants the information puts the command "pwd" in the
> queue and dynamically makes a connection to the queue result or
> "broadcast".  The queue also keeps a record of the requesting object's
> ID (this) so that on the return trip all the objects that may be
> connected to the broadcaster can compare their "this" against the ID to
> recognize, "Hey, that's my data!".  Once the GUI has its data, it can
> choose to disconnect so that the broadcaster doesn't get too many
> subscribers--or whatever analogy one wants to use.

OK, I will look again at the patch.  I probably promised to do that in
the past, maybe more than once.  But I don't think I really understood
threads and Qt signals and slots well enough until now to be able to
properly evaluate it.

Thanks,

jwe



Reply | Threaded
Open this post in threaded view
|

Re: rethinking interpreter <-> gui interaction

Daniel Sebald
On 7/2/19 12:55 AM, John W. Eaton wrote:

> On 7/1/19 11:57 PM, Daniel J Sebald wrote:
>> On 7/1/19 2:47 PM, John W. Eaton wrote:
>
>> There shouldn't be a need to make either side of the link suspend and
>> wait on anything.
>
> Don't functions like inputdlg have to wait for a result?  As I
> understand it, function like that ask the GUI to create a dialog and
> then they can't return until the dialog is closed and a result is
> returned (or an error is thrown).

I suppose so; the input dialog would be used in a script sequence so
couldn't not pause.  More generally perhaps there should be a modal
setting.  Maybe then dialogs can be used to build GUIs as well, i.e.,
have a callback function.  Isn't that how many of these menu items work?
  But the core processing engine wouldn't necessarily have to sit idle,
just not advance the script until a callback arrives???  If Qt puts the
inputdlg in modal mode, then there is no way any other GUI object could
issue some other callback.


>> To make the GUI wait feels unnatural.  Instead, you'd like to allow
>> the user to edit files and whatnot when a long worker process is running.
>
> Yes, I agree that it should be possible to do something like editing
> files as that doesn't generally require the interpreter to perform any
> action.  But what should happen if the GUI asks the interpreter to
> perform some action when it is already busy executing some other code?
> At what point is it safe for the interpreter to check the command queue
> and call other functions?

I don't know.  Depends on the amount of sophistication you have in mind.
  The GUI can put more commands in the queue.  But a "break" routine
could work that way.  How callbacks might be mixed in there is also a
question.

Dan

Reply | Threaded
Open this post in threaded view
|

Re: rethinking interpreter <-> gui interaction

PhilipNienhuis
In reply to this post by John W. Eaton
John W. Eaton wrote

> Currently, most communication between the Octave interpreter and GUI is
> managed by the octave_link class interface defined in the interpreter.
> The actions specific to the GUI are implemented in the GUI by the
> octave_qt_link class.  These classes provide a thread-safe way for
> interpreter and GUI to ask each other to perform actions.  For example,
> the interpreter may notify the GUI that the workspace has changed so
> that the workspace view in the GUI may be updated.  Or the GUI may ask
> the interpreter to invoke a function to change the current directory.
>
> As I understand it, there are four cases that may need to be handled:

<1-3 snipped>


>    4. The GUI asks the interpreter to perform an action and requires an
> immediate result.  The GUI thread must be suspended and wait until the
> interpreter thread is finished with the action.  Although this type of
> interaction is possible, I'm not sure what examples of it that we
> currently have, or whether any that we do have could be rewritten to
> behave like item 3 above so that the requested action is performed by
> the interpreter and the GUI is notified of the result using a separate
> signal sent from the interpreter.

Maybe changing a value in the Variable Editor could belong to case 4?

It might be debatable at what moment the new value is to be conveyed to the,
or a, running interpreter, and even more debatable whether it should be
allowed at all to (be able to) change vales in the V.E. while the
interpreter is busy.
But then again, if the interpreter's actual business is not immediately
affected by the new variable value it could be permitted - and maybe it is
even desirable e.g. in debug sessions. Maybe requiring that the interpreter
is temporarily halted (pause or so) could make it a better scenario, but
then we're probably back at one of the other cases.

Philip




--
Sent from: http://octave.1599824.n4.nabble.com/Octave-Maintainers-f1638794.html

Reply | Threaded
Open this post in threaded view
|

Re: rethinking interpreter <-> gui interaction

Daniel Sebald
In reply to this post by Daniel Sebald
On 7/2/19 2:19 AM, Daniel J Sebald wrote:
> On 7/2/19 12:55 AM, John W. Eaton wrote:
>> On 7/1/19 11:57 PM, Daniel J Sebald wrote:
>>> On 7/1/19 2:47 PM, John W. Eaton wrote:
[snip]

>> Yes, I agree that it should be possible to do something like editing
>> files as that doesn't generally require the interpreter to perform any
>> action.  But what should happen if the GUI asks the interpreter to
>> perform some action when it is already busy executing some other code?
>> At what point is it safe for the interpreter to check the command
>> queue and call other functions?
>
> I don't know.  Depends on the amount of sophistication you have in mind.
>   The GUI can put more commands in the queue.  But a "break" routine
> could work that way.  How callbacks might be mixed in there is also a
> question.

Inquiring for information would be a simple entry into the queue if the
GUI is interested in maintaining sequential commands.  That's easy.

But if you are wondering of how one would do, say, periodically updating
the GUI (e.g., updating the variable display), perhaps a pause(0) would
make a good place to update the GUI.  It might be easy to devise a
"hidden" command scheme, i.e., one which the GUI issues but doesn't show
up in the user's console or command history.  For example, the variable
editor displays "myvar" which is a big matrix in which only
myvar(589:602,345:353) are visible on the screen, then perhaps a hidden

   pause(0);
   ov = myvar(589:602,345:353);

would do.  ???

Dan