Results 1 to 6 of 6

Thread: Share data accross threads and emit signals

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Share data accross threads and emit signals

    Hi,

    I need to have access to several information from different threads so I made a class like this:
    Qt Code:
    1. class Foo
    2. {
    3. public:
    4. void increase()
    5. {
    6. QWriteLocker l(&m_lock);
    7. m_ints << 42;
    8. }
    9.  
    10. private:
    11. QVector<int> m_ints;
    12. };
    To copy to clipboard, switch view to plain text mode 
    Foo is then instantiated in the main thread and a pointer is passed to the relevant threads. So far so good. Now I'd like to get informed if e.g. m_ints gets changed. So QObject came into play but as it is only reentrant (except connect and disconnect) it is getting complicated.

    Let's think of this modified class:
    Qt Code:
    1. class Foo : public QObject
    2. {
    3. public:
    4. Foo: QObject(0) {}
    5.  
    6. void increase()
    7. {
    8. QWriteLocker l(&m_lock);
    9. m_ints << 42;
    10. emit added(42);
    11. }
    12.  
    13. signals:
    14. void added(int);
    15.  
    16. private:
    17. QVector<int> m_ints;
    18. };
    To copy to clipboard, switch view to plain text mode 
    So, Foo's thread affinity is my main thread.
    1. Is this class still thread-safe since it does not use any functions of QObject? What about emit?
    2. What does this mean for calling increase() through a pointer from a different tread. Which thread does the "work" (manipulating m_ints) of increase(): The main thread or the local thread?


    If that solution is bad, what would be a good approach to get informed about changes? (Beside the caller of the function emits afterwards the changes ala
    Qt Code:
    1. myFoo->increase();
    2. emit mySignalAdded(42);
    To copy to clipboard, switch view to plain text mode 


    Thanks
    Lykurg

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Share data accross threads and emit signals

    Quote Originally Posted by Lykurg View Post
    Is this class still thread-safe since it does not use any functions of QObject? What about emit?
    That should be ok.

    Quote Originally Posted by Lykurg View Post
    What does this mean for calling increase() through a pointer from a different tread. Which thread does the "work" (manipulating m_ints) of increase(): The main thread or the local thread?
    The thread calling the method is the one executing its code.
    If the receiver of the signal has a different thread affinity than the thread executing the emit, then the slot will be executed by the receiver's owner thread (assuming Qt::AutoConnection).

    However, I would suggest to unlock before emitting, otherwise it is easy to get into a recursive lock situation (e.g. the slot or a methods called from the slot calling a method of this object again).

    Cheers,
    _

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Share data accross threads and emit signals

    An alternative approach would be to use has-a instead of is-a approach, similar to what QFutureWatcher does. You can register an external QObject with your class, keeping your class thread-safe with the use of the lock and make the object inform the watcher (through e.g. QCoreApplication::postEvent()) that its content has changed (or whatever else you need). You may also look into lock-free structures if your vector only grows at the end to completely avoid the need for a lock.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  4. #4
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: Share data accross threads and emit signals

    Quote Originally Posted by anda_skoa View Post
    The thread calling the method is the one executing its code.
    If the receiver of the signal has a different thread affinity than the thread executing the emit, then the slot will be executed by the receiver's owner thread (assuming Qt::AutoConnection).
    Not sure if I get you right (second sentence): Suppose I have two threads A and B beside my main thread MT.
    Qt Code:
    1. // in MT
    2. Foo *f = new Foo;
    3. objInThreadA->setFoo(f);
    4. objInThreadB->setFoo(f);
    5. connect(foo, &Foo::added, objInThreadB, &Bar::doSomething); // autoConnection will use queuedConnection
    6.  
    7. // in Thread A
    8. f->increase();
    To copy to clipboard, switch view to plain text mode 
    So who does what? My understanding is: ThreadA does the work in increase() and then ThreadB do with "doSomething" whatever it likes in his thread.

    Quote Originally Posted by anda_skoa View Post
    However, I would suggest to unlock before emitting, otherwise it is easy to get into a recursive lock situation (e.g. the slot or a methods called from the slot calling a method of this object again).
    Yes, recursive lock is a risk but is emit thread safe? Doesn't it involve QMetaObject etc. With lifting the lock before emitting, wouldn't that open the possibility that two threads run in the same emit simultaneously?


    Added after 4 minutes:


    Quote Originally Posted by wysota View Post
    An alternative approach would be to use has-a instead of is-a approach, similar to what QFutureWatcher does. You can register an external QObject with your class, keeping your class thread-safe with the use of the lock and make the object inform the watcher (through e.g. QCoreApplication::postEvent()) that its content has changed (or whatever else you need).
    Okay, have to think about that. Thanks for the tip.
    Quote Originally Posted by wysota View Post
    You may also look into lock-free structures if your vector only grows at the end to completely avoid the need for a lock.
    Sure, that's the second step but the deadline leaves me no time to do that (at least for now)...

    P.s.: Thanks to you, too, anda_skoa! Forget that in my previous reply.
    Last edited by Lykurg; 17th March 2015 at 09:43.

  5. #5
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Share data accross threads and emit signals

    Quote Originally Posted by Lykurg View Post
    Not sure if I get you right (second sentence): Suppose I have two threads A and B beside my main thread MT.
    Qt Code:
    1. // in MT
    2. Foo *f = new Foo;
    3. objInThreadA->setFoo(f);
    4. objInThreadB->setFoo(f);
    5. connect(foo, &Foo::added, objInThreadB, &Bar::doSomething); // autoConnection will use queuedConnection
    6.  
    7. // in Thread A
    8. f->increase();
    To copy to clipboard, switch view to plain text mode 
    So who does what? My understanding is: ThreadA does the work in increase() and then ThreadB do with "doSomething" whatever it likes in his thread.
    Yes, correct.

    Quote Originally Posted by Lykurg View Post
    Yes, recursive lock is a risk but is emit thread safe? Doesn't it involve QMetaObject etc. With lifting the lock before emitting, wouldn't that open the possibility that two threads run in the same emit simultaneously?
    I don't think emitting a signal changes anything inside the object, so that should be OK.

    Cheers,
    _

  6. #6
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: Share data accross threads and emit signals

    Not that I do not trust you but I wanted to be sure, so in case anyone else stumbles across this thread: emit is thread safe. It calls QMetaObject::activate which then uses a mutex.

    Detailed information can be found at the end of this article: http://woboq.com/blog/how-qt-signals-slots-work.html

    Thanks!

Similar Threads

  1. Share QGLContext among Multiple Threads (4.7.1)
    By JediMaster in forum Newbie
    Replies: 0
    Last Post: 20th June 2013, 13:10
  2. Replies: 8
    Last Post: 25th June 2011, 10:14
  3. Ways to share data between threads
    By AndresBarbaRoja in forum Qt Programming
    Replies: 8
    Last Post: 11th March 2011, 16:47
  4. Define and emit signals
    By ruben.rodrigues in forum Newbie
    Replies: 2
    Last Post: 24th June 2010, 12:50
  5. emit Signals
    By Fastman in forum Qt Programming
    Replies: 5
    Last Post: 22nd August 2007, 13:14

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.