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: Michael Goffioul
Subject: Re: Passing variables up to the GUI
Date: Sun, 14 Apr 2013 18:17:23 -0400

On Sun, Apr 14, 2013 at 5:17 PM, Daniel J Sebald <address@hidden> wrote:

On the contrary, I think it's the heart of the problem. The line
"rep->count++" is the critical one in the above code. While one thread
is executing it, another one can be doing "rep->count++" or
"--rep->count". Those operations are not atomic, takes several CPU
cycles and can be interrupted by other threads. The problem is that the
resulting values rep->count is then undetermined.

That's true if we're talking OS threads.  However, Octave is running in a QThread, not an OS thread.

And how do you think Qt implements threads? QThread *is* a Qt-wrapper on top of an OS thread.
 
 I'm assuming that Qt has done some kind of magic behind the scenes to make that signal/slot mechanism work out. How do you know that the copy-constructor is done in one thread and the destructor is done in another thread?

That's not really relevant. The problem is that refcount can be modified concurrently by multiple threads. It can be due to the copy that Qt has made to queue the signal, but it can be due to other things: just accessing the content of an octave_value object will probably change refcount of the contained object (like a Matrix).
 
Yes, but that Matrix representation is associated with the octave_value.  If there is nothing in the worker thread that is going to touch that octave_value representation (that was a condition of what I proposed) then the GUI thread is free to increase the rep count, so long as it decreases the object's thread count before returning.

Simply accessing the content of an octave_value object is modifying it, through implicit refcount increment/decrement. I've never even mentioned the problem of accessing/modifying the actual data, I'm just talking about the refcount.
 
    1) Create a "local" duplicate of the octave_value in the routine
    that processes the desired command, on the stack or via "new" or
    whatever. That has a rep count of 1.

    2) Emit the signal that creates a copy of that local octave_value,
    thereby increasing the rep count to 2.

    3) Destroy the local copy off the stack or via "delete".  That
    brings the rep count back down to 1.  *And* from this point forward
    there is no code inside the Worker thread that will touch the
    representation data of the octave_value object because it has gone
    out of scope to any remaining code in the thread.

    4) Sometime later the slots are processed in the GUI thread and that
    representation data still exists, unaltered by anything in the
    Worker thread.

    5) All slots finish, and Qt calls the destructor for the
    octave_value. The representation count goes down to 0 and the data
    is deleted from memory.


What makes you think 3) and 5) won't be executed concurrently?

Your question is the critical one.  My supposition is hinged on the fact that Qt has to do something to make cross-thread signals work.  Hence they have this QThread class.  That question is still in air here.  I've searched the Internet for that answer, but haven't found any just yet.

A QThread is a plaform-independent wrapper on top of a OS thread. When you emit a signal whose receiver is in another thread, Qt will copy the argument of the signal (invoking copy-constructor) and stashed the signal in the event queue of the received thread. When the OS switches thread context and make the target thread to continue execution, the eventloop of the receiver thread will pick up the event and execute the slot. But the source thread continues execution. Theoretically, 3) and 5) can be executed concurrently by the linux/Windows/mach/whatever kernel.

We can stop the discussion here and agree to disagree. But I believe that passing octave_value objects across threads (through Qt signal/slot or whatever else mechanism) can lead to unpredictable results due to the non-thread-safe nature of refcount management. Once that problem is solved, then I fully agree that all your suggestions make sense: that is, Qt will hold a reference to the passed object until the slot execution is completed, and the emitter can safely discard its own reference.

Michael.


reply via email to

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