octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Passing variables up to the GUI


From: Daniel J Sebald
Subject: Re: Passing variables up to the GUI
Date: Sat, 13 Apr 2013 14:29:17 -0500
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.24) Gecko/20111108 Fedora/3.1.16-1.fc14 Thunderbird/3.1.16

On 04/13/2013 10:52 AM, Michael Goffioul wrote:
On Fri, Apr 12, 2013 at 11:55 PM, Daniel J Sebald
<address@hidden <mailto:address@hidden>> wrote:

    On 04/12/2013 10:37 PM, John W. Eaton wrote:

        On 04/12/2013 11:32 PM, Daniel J Sebald wrote:

            On 04/12/2013 10:14 PM, Daniel J Sebald wrote:

                On the GUI side and interface, there is a bit more work.
                I suppose there
                would need to be two queues, maybe one for the user
                input commands, and
                one for the "callback" commands. The GUI needs to queue
                up the command
                and also what object wants the data. The object that
                wants the data has
                to know what it asked for and how to interpret it. Maybe
                it asks for
                "x". Or maybe it asks for "size(x)". Or maybe
                "x(1:10,21:30)".


            Followup thought. Maybe the thing to do is instead of
            attempting the
            "corefeval" function first, is to just create some
            octave_value object
            on the core side, say a small matrix, and see if that can be
            sent over
            by reference using

            emit octave_result (qobject, ovres);

            to some hunk of code on the GUI side that will just toss up
            a dialog
            showing the contents of the object.


        I predict crashes because of reference counting operations that
        are not
        thread safe.


    Eh, we'll see.


Trust me, it'll crash. I've tried that in QtHandles and that's the
reason I implemented atomic refcount in octave.

      Octave is running in a QThread, so Qt's scheme is the one
    influencing garbage collection.


I'm not sure what you refer to with "garbage collection", we're talking
about C++ here. And Qt is completely unaware of the octave-internal
reference counting.

      Documentation says that the slots are all processed immediately
    upon a signal so once that is all done, the reference can be discarded.


That is, if the QObject receiver lives in the same thread that fires the
signal. Otherwise, the default is to queue the signal in the eventloop
of the thread owning the QObject (and for that to work, the target
thread must have a running eventloop). You can change that behavior and
make the signal emission blocking, but then you've the problem of
deadlocking your threads (something I also experienced in QtHandles).

I put a really rough prototype on the patch list last night. Seems to function fine.

The documentation on connections is here:

"
http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads

The connection type can be specified by passing an additional argument to connect(). Be aware that using direct connections when the sender and receiver live in different threads is unsafe if an event loop is running in the receiver's thread, for the same reason that calling any function on an object living in another thread is unsafe.
"

OK, I see now that no argument for the connection type results in *either* a direct connection (e.g., when within the same event loop) or a queued connection (e.g., across threads). If one wants a direct connection, a value of Qt::DirectConnection can be given.

Well, let's think about this. How is this going to crash from a too deep reference count? Would it be the case that if the worker thread (Octave core) keeps emitting signals while the GUI thread doesn't respond to them? Is that the bad scenario you are describing? Or is it that the worker thread emits a signal, then that queued signal creates a "knot in the thread" so that when it continues onward it can only build up references in its computations and can't do garbage collection properly?

This is one reason I've tried to eliminate any sort of ->exec () inside of the GUI thread. My feeling about GUI is it should never be waiting on anything. If from time to time it does something that is momentarily slow (e.g., opening a file), that's fine. But to toss up a dialog box and halt the GUI waiting for user input is bad. That's why DeleteOnClose is such a nice thing.

The situation we are running into with the GUI is that the worker thread is the one with delay. I tried this the other night with John's workspace-variable-name-change feature. I set Octave to running a two-minute command, then altered the name of the variable. The variable name did not change upon hitting return. Upon Octave core finishing, then the name of the variable mysteriously changed (i.e., my short term memory doesn't work more beyond a minute). I don't think that is unreasonable. Octave commands have to remain sequential; to do otherwise would really get to be tricky programming.

There are things that could be done on the GUI side to prevent dangerous building up of queued signals. For example, don't either queue an Octave command or signal an Octave command (effectively the same as queueing) if it has already been queued. For example, if the user asks to change the name of a variable, set some flag in the object. When the slot is called, clear that flag. If the flag hasn't been cleared, don't send another Octave command, maybe issue a Critical message dialog box like "Busy Processing". But I doubt a user is going to keep changing variable names if they don't seem to change immediately, so I wouldn't go about doing such a thing for no compelling reason.

There is this option Qt::BlockingQueuedConnection that we could use. This runs the risk of, as you said, deadlocking the threads. But that might be fine in this case so long as there is no ->exec() in the GUI event loop. If the deadlocking is placed at moments where the GUI just accepts the data and stores it somewhere, builds a table, etc., I don't think that is too critical. If just the connections that are requesting octave_value_list data are BlockingQueued, then these are the GUI routines that are just wanting some data and not much else. I'm not sure using BlockingQueued is a good idea though in a complex system; not without some thought anyway. There is too much risk of some other programmer putting in an ->exec () into the code not realizing that is bad.

In summary, yeah there are concerns, but it seems to me that Qt has worked out a lot of details so that there seems to be some kind of solution if just staying within the design. The other approach is to keep building function callbacks, which is something Qt documentation suggests not doing.

Dan


reply via email to

[Prev in Thread] Current Thread [Next in Thread]