Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Is there a way to wait on the current thread?
QtWS25 Last Chance

Is there a way to wait on the current thread?

Scheduled Pinned Locked Moved Solved General and Desktop
19 Posts 7 Posters 2.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Christian EhrlicherC Christian Ehrlicher

    @MEMekaniske said in Is there a way to wait on the current thread?:

    but he said: Rather than having send in the slot the client had set up for connect, I want it here

    Bad design which fits not into the Qt way of doing things. Or in other words: don't use Qt if you don't want to use it's mechanisms.

    F Offline
    F Offline
    Fleshbits
    wrote on last edited by Fleshbits
    #10

    @Christian-Ehrlicher I don't think I'd call it a bad design.

    For example, show me how you are going to unit test this while relying on a slot for every test case. You'd rather call send in the test case itself, after being assured that connect happened.

    Currently, I am relying on qWait, but that seems wasteful, because I am waiting some amount of time, akin to a sleep, without being woken up when the thing I am waiting on happened. As a result, the unit tests are way longer than they need to be, on every automated build.

    I did find a method in the base socket class "waitOnConnected", which will, I think achieve what I am looking for with the connect call. But I was looking for something more general that could be applied to more asynchronous operations than the call to connect.

    1 Reply Last reply
    0
    • Christian EhrlicherC Online
      Christian EhrlicherC Online
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #11

      @Fleshbits said in Is there a way to wait on the current thread?:

      For example, show me how you are going to unit test this while relying on a slot for every test case.

      See QSignalSpy.

      In your normal program use signals and slots as it's designed to be used.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      1
      • S Offline
        S Offline
        SimonSchroeder
        wrote on last edited by
        #12

        C++ used to not have any direct support for suspending a function and resume it later. This has to do with how the call stack works. Hence, Qt does not provide any direct means for this. What might actually work is writing a small loop which exits when connected and repeatedly calls QApplication::processEvents(). This is basically your own small event loop.

        C++20 provides the feature you are requesting, but you should not expect that it ties in very well with Qt's signals and slots. It is called coroutines. These handle their stacks differently and are built so they can return and later resume where they left off. Though it will not integrate with the signals and slots directly.

        M 1 Reply Last reply
        -1
        • S SimonSchroeder

          C++ used to not have any direct support for suspending a function and resume it later. This has to do with how the call stack works. Hence, Qt does not provide any direct means for this. What might actually work is writing a small loop which exits when connected and repeatedly calls QApplication::processEvents(). This is basically your own small event loop.

          C++20 provides the feature you are requesting, but you should not expect that it ties in very well with Qt's signals and slots. It is called coroutines. These handle their stacks differently and are built so they can return and later resume where they left off. Though it will not integrate with the signals and slots directly.

          M Offline
          M Offline
          MEMekaniske
          wrote on last edited by MEMekaniske
          #13

          @SimonSchroeder regarding QApplication::processEvents()

          I'm working on a bit of a intensive proccessing application now, doing serial com with 115200 baudrate, alongside 20mb/s tcp transfers, and emitting a lot of signals and slots for data processing, both backend and to qml.

          I wanted to get some faster responses and updates while either the TCP or Serial com were in the proccessing step after receiving/sending as those used some time, so I added QApplication::processEvents() a few places, and everything started to get wired... eventually crashing or freezing.. All features were also protected by a mutex but still it went dead..

          I had longer and longer periods before crash after removing the QApplication::processEvents() one by one. so for any feature running a lot of processes, it's better to just organize everything better from the start. and as everyone said above, use signals and slots.

          Edit;
          Today I checked the CPU and Memory usage of my program again, yesterday with the processEvents() my app ran at 10-20% of my CPU, today after I have removed them, it's running it's routines with just 0-5 as it should :p Starting to understand why those who are experienced in Qt says to use it only when one really need to.. :)

          F 1 Reply Last reply
          1
          • M MEMekaniske

            @SimonSchroeder regarding QApplication::processEvents()

            I'm working on a bit of a intensive proccessing application now, doing serial com with 115200 baudrate, alongside 20mb/s tcp transfers, and emitting a lot of signals and slots for data processing, both backend and to qml.

            I wanted to get some faster responses and updates while either the TCP or Serial com were in the proccessing step after receiving/sending as those used some time, so I added QApplication::processEvents() a few places, and everything started to get wired... eventually crashing or freezing.. All features were also protected by a mutex but still it went dead..

            I had longer and longer periods before crash after removing the QApplication::processEvents() one by one. so for any feature running a lot of processes, it's better to just organize everything better from the start. and as everyone said above, use signals and slots.

            Edit;
            Today I checked the CPU and Memory usage of my program again, yesterday with the processEvents() my app ran at 10-20% of my CPU, today after I have removed them, it's running it's routines with just 0-5 as it should :p Starting to understand why those who are experienced in Qt says to use it only when one really need to.. :)

            F Offline
            F Offline
            Fleshbits
            wrote on last edited by Fleshbits
            #14

            In my example, I have made a websocket implementation, with an abstract interface, that allows for a concrete implementation. One concrete implementation uses QWebsocket and another uses boost::beast. The abstract interface is the break between Qt specifics and standard C++.

            If I can't break the Qt specifics somewhere along the inheritance tree to abstract away the details, because I am required to fire a signal rather than call std::bind, then I am damning all my users to use Qt in their consuming classes and can never change out my implementation.

            I'd have to fire a signal, in order to use QSignalSpy rather than qWait, in my unit tests, in order to have them run at any kind of acceptable speed.

            M 1 Reply Last reply
            0
            • F Fleshbits

              In my example, I have made a websocket implementation, with an abstract interface, that allows for a concrete implementation. One concrete implementation uses QWebsocket and another uses boost::beast. The abstract interface is the break between Qt specifics and standard C++.

              If I can't break the Qt specifics somewhere along the inheritance tree to abstract away the details, because I am required to fire a signal rather than call std::bind, then I am damning all my users to use Qt in their consuming classes and can never change out my implementation.

              I'd have to fire a signal, in order to use QSignalSpy rather than qWait, in my unit tests, in order to have them run at any kind of acceptable speed.

              M Offline
              M Offline
              MEMekaniske
              wrote on last edited by
              #15

              @Fleshbits If you want to use Qt you have to distribute Qt with your script or application... No way around that if you're not making changes and recompiling from the source itself...

              F 1 Reply Last reply
              0
              • M MEMekaniske

                @Fleshbits If you want to use Qt you have to distribute Qt with your script or application... No way around that if you're not making changes and recompiling from the source itself...

                F Offline
                F Offline
                Fleshbits
                wrote on last edited by
                #16

                @MEMekaniske I'm not sure what distributing it has to do with anything.

                In object orientated programming we often have:

                class IInterfaceToSomething
                {
                // I don't know anything about implementation details
                };

                class ConcreteClassA : public IInterfaceToSomething
                {
                // I implement the interface using Qt's QWebsocket
                };

                class ConcreteClassB : IInterfaceToSomething
                {
                // I implement the interface using boost::beast, but I do the same thing as ConcreteClassA
                } ;

                What I'm talking about is that I am going to be forced to:
                A) Make IInterfaceToSomething a QOBJECT even though ConcreteClassB has nothing to do with QT whatsoever.
                B) Use signals and slots in IIInterfaceToSomething, even though ConcreteClassB would never require it.
                C) Implement ConcreteClassB using QT's signals, slots, and types, even though it has nothing to do with Qt, because the IInterfaceToSomething has to, because ConcreteClassA does.

                I originally abstracted away the Qt specifics, by using std::bind and translating types, in ConcreteClassA where it implemented the common Interface. ConcreteClassA then used private slots to communicate with the QWebsocket it is using.

                However, if we are going to use QSignalSpy in unit tests, then instead of std::bind for ConcreteClassA to implement the interface, we now have to use signals there too, making the interface use signals, making everything derived from it use signals.

                Does that make more sense?
                Qt is invading my entire repo, because I wanted to implement one class with it.

                M 1 Reply Last reply
                0
                • F Fleshbits

                  @MEMekaniske I'm not sure what distributing it has to do with anything.

                  In object orientated programming we often have:

                  class IInterfaceToSomething
                  {
                  // I don't know anything about implementation details
                  };

                  class ConcreteClassA : public IInterfaceToSomething
                  {
                  // I implement the interface using Qt's QWebsocket
                  };

                  class ConcreteClassB : IInterfaceToSomething
                  {
                  // I implement the interface using boost::beast, but I do the same thing as ConcreteClassA
                  } ;

                  What I'm talking about is that I am going to be forced to:
                  A) Make IInterfaceToSomething a QOBJECT even though ConcreteClassB has nothing to do with QT whatsoever.
                  B) Use signals and slots in IIInterfaceToSomething, even though ConcreteClassB would never require it.
                  C) Implement ConcreteClassB using QT's signals, slots, and types, even though it has nothing to do with Qt, because the IInterfaceToSomething has to, because ConcreteClassA does.

                  I originally abstracted away the Qt specifics, by using std::bind and translating types, in ConcreteClassA where it implemented the common Interface. ConcreteClassA then used private slots to communicate with the QWebsocket it is using.

                  However, if we are going to use QSignalSpy in unit tests, then instead of std::bind for ConcreteClassA to implement the interface, we now have to use signals there too, making the interface use signals, making everything derived from it use signals.

                  Does that make more sense?
                  Qt is invading my entire repo, because I wanted to implement one class with it.

                  M Offline
                  M Offline
                  MEMekaniske
                  wrote on last edited by
                  #17

                  @Fleshbits "Qt is invading my entire repo, because I wanted to implement one class with it."

                  You cannot use a class from Qt without using all dependencies of the class as with any other library you'd find.

                  Qt is made for application writing, so better just find, buy or write the class you want to use if you do not want to have all dependencies for the Qt class with your software.

                  F 1 Reply Last reply
                  2
                  • M MEMekaniske

                    @Fleshbits "Qt is invading my entire repo, because I wanted to implement one class with it."

                    You cannot use a class from Qt without using all dependencies of the class as with any other library you'd find.

                    Qt is made for application writing, so better just find, buy or write the class you want to use if you do not want to have all dependencies for the Qt class with your software.

                    F Offline
                    F Offline
                    Fleshbits
                    wrote on last edited by Fleshbits
                    #18

                    @MEMekaniske Either you do not know what abstraction is, or are grossly not understanding what I am talking about.

                    • Abstraction has nothing to do link dependencies.
                    • Any good library should be written in such a way that you can abstract away the details and use an interface.
                    • Modern object orientated programming incorporates techniques like dependency injection which require the above statement to be true.

                    I'm not here to tell you how bad Qt sucks.

                    I am here asking:
                    How does one abstract away QObject::connect somewhere in their inheritance hierarchy?

                    If your answer is, "You cannot" then that is an acceptable answer, but not one that should make anyone happy. It would also be one that I'd find hard to believe concerning a library that has been around for decades and is very popular in the C++ community.

                    1 Reply Last reply
                    0
                    • F Fleshbits

                      @gde23 said in Is there a way to wait on the current thread?:

                      You can use QThread::finished() signal for that.

                      According to the docs that is for when the thread is finished executing. I don't think that's what I am looking for. Perhaps an example would help?

                      Here is what I need:

                      class Client : public QObject
                          {
                          Q_OBJECT
                          public:
                              explicit Client(const QUrl &url);
                              ~Client();
                      
                              void connect();
                              void send(const std::string & message);
                      
                          private Q_SLOTS:
                      
                              void onConnected();
                              void onClosed();
                              void onError(QAbstractSocket::SocketError errorCode);
                      
                          private:
                              QWebSocket * m_webSocket;
                              QUrl m_url;
                          };
                      
                      Client::Client(const QUrl &url)
                              :
                              QObject(),
                              m_url(url)
                          {
                              m_webSocket = new QWebSocket();
                              QObject::connect(m_webSocket, &QWebSocket::connected, this, &Client::onConnected);
                              QObject::connect(m_webSocket, &QWebSocket::disconnected, this, &Client::onClosed);
                              QObject::connect(m_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), this, &Client::onError);
                          }
                      
                          Client::~Client()
                          {
                              delete m_webSocket;
                          }
                      
                          void Client::connect()
                          {
                              m_webSocket->open(m_url);
                          }
                      
                          void Client::send(const std::string & message)
                          {
                              qint64 numbytesWritten = m_webSocket->sendTextMessage(QString::fromStdString(message));
                              std::cout << "Wrote " << numbytesWritten << " bytes" << std::endl;
                          }
                      
                          void Client::onConnected()
                          {
                              std::cout << "Connected" << std::endl;
                              // Fire some kind of condition variable type mechanism here to tell us back in main that we have been connected and the next statement can execute.
                          }
                      
                          void Client::onClosed()
                          {
                              std::cout << "Closed" << std::endl;
                          }
                      
                          void Client::onError(QAbstractSocket::SocketError errorCode)
                          {
                              std::cout << "Error: " << errorCode << std::endl;
                          }
                      
                      int main(int argc, char ** argv)
                          {
                              QCoreApplication app(argc, argv);
                              QUrl url("ws://echo.websocket.org");
                              Client client(url);
                              client.connect();
                      
                              // Rather than having send in the slot the client had set up for connect, I want it here, after a condition_variable type wait, which would be tripped by the slot for connect. However, the connect slot doesn't happen on another thread, it happens on this thread, because everything is running in the event queue set up by QApplication
                              // wait(connectedCV, 5000);
                              client.send("Test message");
                      
                              return app.exec();
                          }
                      
                      JKSHJ Offline
                      JKSHJ Offline
                      JKSH
                      Moderators
                      wrote on last edited by JKSH
                      #19

                      @Fleshbits said in Is there a way to wait on the current thread?:

                          client.connect();
                      
                          // Rather than having send in the slot the client had set up for connect, I want it here, after a condition_variable type wait, which would be tripped by the slot for connect. However, the connect slot doesn't happen on another thread, it happens on this thread, because everything is running in the event queue set up by QApplication
                          // wait(connectedCV, 5000);
                          client.send("Test message");
                      

                      In other words, you don't want Client::connect() return until the Client confirms that the connection is established, but you want Qt to continue processing events until the connection is established.

                      @Bonnie's answer gives you what you want: Use a QEventLoop. It blocks the function without blocking the thread.

                      void Client::connect()
                      {
                          QEventLoop innerLoop;
                          connect(m_webSocket, &QWebSocket::connected,
                                  &innerLoop, &QEventLoop::quit)
                          m_webSocket->open(m_url);
                      
                          // TODO: Also quit the inner event loop if the connection fails/errors
                      
                          // QEventLoop::exec() is a blocking function that keeps processing events and signals.
                          // It returns when QEventLoop::quit() is invoked.
                          // This is analogous to QCoreApplication::exec() and QCoreApplication::quit().
                          innerLoop.exec();
                      }
                      

                      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                      1 Reply Last reply
                      3

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved