Results 1 to 16 of 16

Thread: Sharing data between threads

  1. #1
    Join Date
    Sep 2008
    Posts
    13
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Sharing data between threads

    Hello everyone,

    I'm using QT4.4.1 and have the following situation:

    We have 'C' code with which we want to add a Graphical User Interface to, so I created the GUI using QT4 and built it as a static library. I then create a new thread in our multi-threaded 'C' application and execute the GUI. I was able to do with no problems at all, but now I want to be able to send data back and forth between the C-main function and the QT-main function (QT GUI Library).

    I wasn't sure how to do this because the QApplication::exec() is necessary to start the GUI and has it's own event loop that processes different events.

    Can anyone provide any help on this subject? Creating a separate thread in QT (QThreads) and running the C application is not an option because I will not have access to manipulate the C code, only the QT GUI library.


    Regards,
    BB
    Last edited by bbui210; 15th October 2008 at 01:39. Reason: More relevent title

  2. #2
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Sharing data between threads

    You may notify Qt via QCoreApplication::postEvent() (which is tread-safe.).

    HTH

  3. #3
    Join Date
    Sep 2008
    Posts
    13
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: Sharing data between threads

    Okay, but I'm still not sure how to get data from the C code into the QT application when I am outside of the QT event loop.

    For example I have the following code in the C++ library:

    C++ Library
    Qt Code:
    1. int hpgeUI(int argc, char *argv[])
    2. {
    3. QApplication rdac(argc, argv, QApplication::GuiServer);
    4.  
    5. MainWindow window;
    6. window.showFullScreen(); //Run in full screen mode
    7. window.setPalette(QPalette(QColor(233, 233, 235))); //Set palette color to off white
    8. window.setAutoFillBackground(true); //Fill background w/ palette color
    9. window.show();//Show window
    10.  
    11. return rdac.exec();
    12. }
    To copy to clipboard, switch view to plain text mode 

    I then execute this function from a new thread in my C code:

    C Code:
    Qt Code:
    1. int main(int argc, char *argv[])
    2. {
    3. char arg[] = "-display transformed:Rot90 -nomous";
    4.  
    5. while(hpgeUI(2, *arg)) //While GUI is running
    6. //do some updating of data here using mutex protected data
    7. }
    To copy to clipboard, switch view to plain text mode 

    From what I understand, the QApplication does not exit or return anything until it receives an exit() command, so the while() loop above will not do anything until the GUI is closed. Is this correct?

    So my question is, how do I get data from the Main C Code into my QApplication if my code sits and waits for an exit() from QApplication?

    If my assumptions are incorrect, then I can simply run a separate loop after executing the exec() function and use the postEvent() function correct?


    I appreciate all the help.

    Regards,
    BB

  4. #4
    Join Date
    Jan 2006
    Location
    travelling
    Posts
    1,116
    Thanks
    8
    Thanked 127 Times in 121 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Sharing data between threads

    well... my two cents : wrong paradigm!

    let me explain it a little better : it does not make sense to call the GUI part from the "non-GUI" part. Instead, create your GUI as a standalone application that lives its own life and interacts with the "non-GUI" part either invoking it as a command line application or directly calling relevant code (provided it is packed into a library).

    If your core code is supposed to produce data as long as the GUI is running just display that GUI from the main function and mess with the data in a separate thread with which the GUI can exchnage data through signals/slots and/or thread-safe classes known to both (using a producer/consumer approach for instance).
    Current Qt projects : QCodeEdit, RotiDeCode

  5. #5
    Join Date
    Sep 2008
    Posts
    13
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: Sharing data between threads

    Quote Originally Posted by fullmetalcoder View Post
    let me explain it a little better : it does not make sense to call the GUI part from the "non-GUI" part.
    Yes, I understand that this way of thinking doesn't make sense, that the GUI should be the core of the application and the rest of the precessing should be threaded out. However, I am unable to do this because our "core" code is huge and is in C (not C++).

    I do understand I am not visualizing this properly, so any help/push in the right direction is much appreciated.


    Instead, create your GUI as a standalone application that lives its own life and interacts with the "non-GUI" part either invoking it as a command line application or directly calling relevant code (provided it is packed into a library).
    I would like to keep the whole application as one instead of two separate applications sending data back and forth between the two.


    If your core code is supposed to produce data as long as the GUI is running
    Yes this is what it's supposed to do

    just display that GUI from the main function and mess with the data in a separate thread with which the GUI can exchnage data through signals/slots and/or thread-safe classes known to both (using a producer/consumer approach for instance).
    The main function is in C and because of this I am having a hard time putting all of this together.

    I cannot change the way the Main/Core application is laid out, so I have to work with a given thread created from this Core and have to display the data given to me.

    I may still be looking at it all wrong, but I hope this clears things up a little bit and again, I appreciate all the help.

    Regards,
    BB

  6. #6
    Join Date
    Jan 2006
    Location
    travelling
    Posts
    1,116
    Thanks
    8
    Thanked 127 Times in 121 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Post Re: Sharing data between threads

    you can always call C code from C++ (unless you use loose casts that some C++ compilers may not accept) but the opposite is not true.

    wouldn't it be possible to do the following :
    Qt Code:
    1. int main(int argc, char **argv)
    2. {
    3. QApplication app(argc, argv);
    4.  
    5. // setup GUI
    6.  
    7. // launch the core loop in another thread, no matter how (QThread or whatever is already used in your core, as long as it does not block things now)
    8.  
    9. return app.exec(); // start GUI event loop (so display and interactivity)
    10. }
    To copy to clipboard, switch view to plain text mode 

    Then communication between GUI and "core" can be done through any of the following (it is possible to mix these):

    • signals/slots
    • events
    • "global" thread-safe classes wrapping around the shared data (GUI and "core" have access to the instance of such classes. such a class serializes data acess using mutexes or read/write locks and everyone is happy).

    Given that your core is written in C and that you cannot modify it the simplest approach would probably be to create a QThread subclass in which you do data collection (or production...) and which takes care of communication with the GUI (it can uses all three above means of communication while the "core" cannot).

    Of course this is just a general canvas but without more precisions that's a much as you may get.
    Current Qt projects : QCodeEdit, RotiDeCode

  7. #7
    Join Date
    Sep 2008
    Posts
    13
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: Sharing data between threads

    Thank you for your help

    Quote Originally Posted by fullmetalcoder View Post
    Given that your core is written in C and that you cannot modify it the simplest approach would probably be to create a QThread subclass in which you do data collection (or production...) and which takes care of communication with the GUI (it can uses all three above means of communication while the "core" cannot).
    I was thinking of something like this.

    So one option would be to create this QThread that can read/write to mutex protected global data in my GUI Library and then create a function/method that will allow the outside (CORE Application) read/write to these protected variables also.

    Am I on the right track?

  8. #8
    Join Date
    Jan 2006
    Location
    travelling
    Posts
    1,116
    Thanks
    8
    Thanked 127 Times in 121 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Sharing data between threads

    I was thinking about something more like this :

    1. your C code has well-defined entry points already (you can feed hime some data and get other from it)
    2. you create a thread which uses this entry point to do whathever operation you need with the core
    3. the data that must be shared between core and UI is located in a third class (or a set of class). both the GUI and the "runner thread" have access to instances of this (set of) class so they can read/write data independently
    4. this (set of) class serializes read/write operations using either QMutex or QReadWriteLock so that threading does not screw things up

    I hope I am making it clear enough. Please tell me if it is not the case.
    Current Qt projects : QCodeEdit, RotiDeCode

  9. The following user says thank you to fullmetalcoder for this useful post:

    bbui210 (15th October 2008)

  10. #9
    Join Date
    Sep 2008
    Posts
    13
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: Sharing data between threads

    I think I have a better idea of how to accomplish this. It's time to start punching out some code. I will report back with the status of how well it goes.

    Thank you,
    BB

  11. #10
    Join Date
    Sep 2008
    Posts
    13
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: Sharing data between threads

    So I have got some code to compile, but I'm having some problems. Here is what I'm doing to give you an idea of what's going on with my code:


    • I have C code with which I create a thread to run the GUI in
    • In the GUI code I create a QThread which provides me entry points to write data to and from.


    I can compile it all and run it, but it seems as though the GUI Thread is blocking my Main thread. The graphics show up, but everything else in my main C code is not executing.

    My GUI code:
    Qt Code:
    1. //globals
    2. idThread *idthread;
    3. MainWindow *window;
    4.  
    5. int hpgeUI(char *argv[])
    6. //int main(int argc, char *argv[])
    7. {
    8. rdac = new QApplication(argc, argv, QApplication::GuiServer);
    9. idthread = new idThread;
    10. window = new MainWindow;
    11.  
    12. window->showFullScreen(); //Run in full screen mode
    13. window->setPalette(QPalette(QColor(233, 233, 235))); //Set palette color to off white
    14. window->setAutoFillBackground(true); //Fill background w/ palette color
    15. window->show();//Show window
    16. rdac->connect(idthread, SIGNAL(newIdValue(int)), window, SLOT(newIdValue(int)));
    17. //return 0;
    18. return rdac->exec();
    19. }
    20.  
    21. void updateData(int id)
    22. {
    23. idthread->updateID(id);
    24. }
    To copy to clipboard, switch view to plain text mode 


    The QThread to pass data to and from the C code:
    Qt Code:
    1. void idThread::updateID(int id)
    2. {
    3. /* Lock the mutex so we can grab the data */
    4. QMutexLocker locker(&mutex);
    5. /* copy the id to our thread's copy */
    6. this->localID = id;
    7. /* if the thread is not running, start it, else restart the thread. */
    8. if(!isRunning()){
    9. start(LowPriority);
    10. } else {
    11. restart = true;
    12. /* wake up the thread if necessary */
    13. condition.wakeOne();
    14. }
    15. }
    16.  
    17. void idThread::run()
    18. {
    19. cout << "Running idThread\n";
    20. int id = 0;
    21. forever //Qt psuedo-keyword, like foreach
    22. {
    23. /* Lock the mutex and copy ID to a local copy so that if new ID's come in, we can get them immediately */
    24. mutex.lock();
    25. id = this->localID;
    26. mutex.unlock();
    27. /* if we get an abort for some reason, break from this loop and kill the thread */
    28. if(abort)
    29. return;
    30. /* Emit the new ID unless restart is true */
    31. if(!restart)
    32. emit newIdValue(id);
    33. /* Once we're done with all the iterations, we call QWaitCondition::wait() to put the thread */
    34. /* to sleep by calling, unless restart is true. There's no use in keeping a worker thread looping */
    35. /* indefinitely while there's nothing to do. */
    36. mutex.lock();
    37. if(!restart)
    38. condition.wait(&mutex);
    39. restart = false;
    40. mutex.unlock();
    41. }
    42.  
    43. }
    To copy to clipboard, switch view to plain text mode 


    My C Code that puts everything together:

    Qt Code:
    1. void *initUI(char *argv[]) {
    2. printf("This is the initUI thread\n");
    3. hpgeUI(argv);
    4. return 0;
    5. }
    6.  
    7.  
    8. int main(int argc, char *argv[])
    9. {
    10.  
    11. pthread_t ui;
    12. pthread_create(&ui, NULL, initUI(argv), 0);
    13. printf("Done initializing...\n");
    14. int x = 0, test = 0x1;
    15. while(1)
    16. {
    17. x++;
    18. if(x%50 == 0) {
    19. printf("Testing with value: 0x%04x\n", test);
    20. if(test < 0x8)
    21. test++;
    22. else
    23. test = 0x1;
    24. updateData(test);
    25. }
    26. }
    27. return 0;
    28. }
    To copy to clipboard, switch view to plain text mode 



    Am I going about it all wrong? Again, I appreciate all the help.

    Regards,
    BB

  12. #11
    Join Date
    Jan 2006
    Location
    travelling
    Posts
    1,116
    Thanks
    8
    Thanked 127 Times in 121 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Sharing data between threads

    It might look like as though I'm repeating myself but :

    • it is a bad idea to init your GUI from the core. Doing the opposite is recommended
    • I am not familiar with pthread and how well Qt interacts with other threading APIs in the same app but what I am sure about is that Qt docs explicitely tell you that the GUI runs in its own thread and that you may not call GUI commands from another thread so I suppose your approach, being inherently disrespectful of Qt docs, is likely to fail (again I am not familiar with the possible interactions at this level so it might actually work).

    I just packed a minimalistic example showing the design I've explained to you. It is BSD-licensed so you can reuse it freely even in closed source projects. If you have any question about the code please ask.

    Note : the app expects you to type some text in the line edit. It will send the data to the "core thread" which in turns call some C code through an entry point, get a result back (here some sort of hash) and make it available to the GUI. Modifications may be needed for use with your application but the design is here.
    Current Qt projects : QCodeEdit, RotiDeCode

  13. #12
    Join Date
    Sep 2008
    Posts
    13
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: Sharing data between threads

    Thank you again for your quick responses.

    Quote Originally Posted by fullmetalcoder View Post
    • it is a bad idea to init your GUI from the core. Doing the opposite is recommended
    Yea, and trust me, if I had a choice I would have done so in a heartbeat. I just don't have a choice and will have to make this work. I'm really not that hardheaded

    • I am not familiar with pthread and how well Qt interacts with other threading APIs in the same app but what I am sure about is that Qt docs explicitly tell you that the GUI runs in its own thread and that you may not call GUI commands from another thread so I suppose your approach, being inherently disrespectful of Qt docs, is likely to fail (again I am not familiar with the possible interactions at this level so it might actually work).
    I understand that the GUI commands all must reside in the same thread. I have done this by creating a thread and starting the GUI in it, as seen in the function initUI (from the code above). So getting the UI up and running is not a problem now. My problem, which might be the mix of pthread and QT, is that once the GUI executes (in its own thread), the originating thread doesn't move on.

    I do all of my (dummy) data transfers after the start of the GUI, so because the thread seems to be halted or paused, I am unable to transfer/pipe the data.

    Maybe it's not getting any CPU time? I don't know.

    Any advice?

    Regards,
    BB


    EDIT: THIS MAY BE A TOPIC FOR ANOTHER THREAD (Starting QT in a seperate pthread). Unless anyone has any insights to this issue?
    Last edited by bbui210; 17th October 2008 at 02:08.

  14. #13
    Join Date
    Jan 2006
    Location
    travelling
    Posts
    1,116
    Thanks
    8
    Thanked 127 Times in 121 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Sharing data between threads

    Well, either the example code you shown is not really what you're working on but only a rough approximation of something a lot more complicated, or you did not even look at the example code I proposed. As far as I understood your explanations the proposed design should do pretty fine (may need some adjustements but I'm not going to write your program ). All you have to do is to init your GUI where I init my simple test widget and place calls to your C code inside the run() function of the CoreThread.

    Again (yeah I like repeating myself), creating GUI from core is more than just a design error, it is a complete design failure. If you can call GUI init code from core then you can also change your core to fit in a GUI app from the start. If you can't (as you claim) then you shouldn't be able to init any GUI but you will always be able to access your core from the GUI (or at least from the place that creates your GUI). I really don't understand what bugs you about such a simple yet important change of paradigm.
    Current Qt projects : QCodeEdit, RotiDeCode

  15. #14
    Join Date
    Sep 2008
    Posts
    13
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: Sharing data between threads

    Quote Originally Posted by fullmetalcoder View Post
    Well, either the example code you shown is not really what you're working on but only a rough approximation of something a lot more complicated
    Yes my example is a very simplified version so that I could explain how things are working. The actual Core application creates about 10-15 other threads that do processing and modification of mutex protected global variables.

    or you did not even look at the example code I proposed.
    I had a look, I sent you a PM with some questions about it.

    As far as I understood your explanations the proposed design should do pretty fine (may need some adjustements but I'm not going to write your program ).
    Of course you're not, where would the fun be if you did?


    I really don't understand what bugs you about such a simple yet important change of paradigm.
    It is partially because the Core is such a huge base of code that I do not want to make any large changes to it (or tell the creator to do so). I had hoped that it would be possible for the core to create a separate GUI thread among the dozen of others, but I am seeing that what I want to do is not possible. Sorry if it took a few iterations of beating my head against the wall until you got your point across.

    Regards,
    BB

  16. #15
    Join Date
    Jan 2006
    Location
    travelling
    Posts
    1,116
    Thanks
    8
    Thanked 127 Times in 121 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Sharing data between threads

    you really don't have to change the core (except maybe move it out of the main() function) and you wouldn't have to change the GUI much either (where it to be designed already). You just have to insert a layer between them that handle communication in a way that is independent from both (i.e use signals/slots and/or events to pass data from GUi to communication layer (CoreThread in my example) and use C core entry points, from communication layer, to pass that data (and retrieve results) to the C core).

    The underlying architecture of the core is not an issue as long as it offers entry points to the data it manipulates (in and out). The rest is just a matter of bridging UI and core as explained above.
    Current Qt projects : QCodeEdit, RotiDeCode

  17. #16
    Join Date
    Sep 2008
    Posts
    13
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: Sharing data between threads

    Yea, after my last post I've finally cleared up my confusion. I combined what you were saying and what I was trying to say and was able to work.

    Again, I appreciate all your help.

    Regards,
    BB

Similar Threads

  1. Loading library from application
    By mourad in forum Installation and Deployment
    Replies: 0
    Last Post: 2nd April 2008, 15:10

Tags for this Thread

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
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.