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. Integrating third-party event loop with Qt Event loop
Forum Updated to NodeBB v4.3 + New Features

Integrating third-party event loop with Qt Event loop

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 2.6k Views 1 Watching
  • 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.
  • D Offline
    D Offline
    DRoscoe
    wrote on 26 Apr 2016, 15:51 last edited by
    #1

    I have an application that is currently built upon the Adaptive Communications Environment (ACE) framework. It uses a Reactor object to supply an event loop. Ultimately I want to port the entire application to Qt and eliminate ACE, so as a first step, I created a QCoreApplication and a QObject-derived application class with the QCoreApplication as its parent. In the main application class, I handle Qt signals, however I also need to service events on the ACE Reactor. I am currently doing this using a single-shot QTimer set to 20ms. When the timeout fires, I call a single-shot version of the ACE event loop and set up a new single-shot timer, and the process repeats. This all works.

    The problem I have is the use of the single-shot timer. I don't want this timer firing off when the application is getting ready to shut down, but it is not obvious to me if there is a way to kill this timer at the time I know the app is going away. I could implement a recurring timer with a linked QTimer object, but then I worry about stacked up timeout events if the ACE Reactor call takes too long to execute.

    I'm looking for some input on best practice to do something like this.

    1 Reply Last reply
    0
    • K Offline
      K Offline
      kshegunov
      Moderators
      wrote on 26 Apr 2016, 19:02 last edited by kshegunov
      #2

      @DRoscoe

      Hello,
      You could try providing your own implementation of the QAbastractEventDispatcher class.

      PS.
      Maybe expand a bit on what you mean by "service events on the ACE Reactor" and how ACE works. It might attract better answers than you currently have.

      Read and abide by the Qt Code of Conduct

      D 1 Reply Last reply 27 Apr 2016, 13:45
      0
      • S Offline
        S Offline
        sandy.martel23
        wrote on 27 Apr 2016, 00:58 last edited by
        #3

        What's wrong with simply stopping a single-shot timer ?
        Of course, you have to create your own single-shot timer, don't use the static method QTimer::singleShot().

        1 Reply Last reply
        0
        • K kshegunov
          26 Apr 2016, 19:02

          @DRoscoe

          Hello,
          You could try providing your own implementation of the QAbastractEventDispatcher class.

          PS.
          Maybe expand a bit on what you mean by "service events on the ACE Reactor" and how ACE works. It might attract better answers than you currently have.

          D Offline
          D Offline
          DRoscoe
          wrote on 27 Apr 2016, 13:45 last edited by
          #4

          @kshegunov When the application starts, it makes a call to:

          AopBootstrap::processAceEvents()
          

          This call has the following implementation:

            ACE_Time_Value timeout(0, 10000); // 10ms
            ACE_Reactor::instance()->handle_events(timeout);
            QTimer::singleShot(20, this, SLOT(processAceEvents()));
          

          The ACE reactor is essentially an event dispatcher running in a loop. The call:

          ACE_Reactor::instance()->handle_events(timeout);
          

          Is a single shot call to the event dispatcher to service any events generated by the legacy code. By default it is a blocking call, waiting for an event to arrive. I provide a 10ms timeout to allow the call to return, and then set my timer for 20ms to start the process over again.

          I will look into the QAbstractEventDispatcher class. Perhaps I can insert this call into the normal event loop and bypass the timer altogether.

          K 1 Reply Last reply 27 Apr 2016, 15:15
          0
          • D DRoscoe
            27 Apr 2016, 13:45

            @kshegunov When the application starts, it makes a call to:

            AopBootstrap::processAceEvents()
            

            This call has the following implementation:

              ACE_Time_Value timeout(0, 10000); // 10ms
              ACE_Reactor::instance()->handle_events(timeout);
              QTimer::singleShot(20, this, SLOT(processAceEvents()));
            

            The ACE reactor is essentially an event dispatcher running in a loop. The call:

            ACE_Reactor::instance()->handle_events(timeout);
            

            Is a single shot call to the event dispatcher to service any events generated by the legacy code. By default it is a blocking call, waiting for an event to arrive. I provide a 10ms timeout to allow the call to return, and then set my timer for 20ms to start the process over again.

            I will look into the QAbstractEventDispatcher class. Perhaps I can insert this call into the normal event loop and bypass the timer altogether.

            K Offline
            K Offline
            kshegunov
            Moderators
            wrote on 27 Apr 2016, 15:15 last edited by
            #5

            @DRoscoe

            Sometime ago I was hacking about the event loop for a (long-term slow-moving hopefully-some-day-to-be-finished project). Anyway, I ended up dropping the idea of interjecting into the event processing in favor of polling. However, in my case I didn't have the ability to set a timeout for the blocking wait-for-event call, so my options were somewhat limited.

            Anyway, during my initial attempt I linked against the private API (the usual warning applies) and subclassed the default event dispatcher (I wanted to keep the default processing of timer and socket events). Then I added my own event handling before Qt's in a processEvents override. This worked fine, but it was pointed out that it's not the best way to do things. So I eventually ended up polling the events instead.

            It's also noteworthy to mention that Qt wants to "own" the event loop, so even if you do something like the described you may end up smack in the middle of a war who gets events - Qt or ACE

            It's not exactly an answer to your question, but I hope it's helpful.
            Kind regards.

            Read and abide by the Qt Code of Conduct

            D 1 Reply Last reply 2 May 2016, 13:44
            1
            • K kshegunov
              27 Apr 2016, 15:15

              @DRoscoe

              Sometime ago I was hacking about the event loop for a (long-term slow-moving hopefully-some-day-to-be-finished project). Anyway, I ended up dropping the idea of interjecting into the event processing in favor of polling. However, in my case I didn't have the ability to set a timeout for the blocking wait-for-event call, so my options were somewhat limited.

              Anyway, during my initial attempt I linked against the private API (the usual warning applies) and subclassed the default event dispatcher (I wanted to keep the default processing of timer and socket events). Then I added my own event handling before Qt's in a processEvents override. This worked fine, but it was pointed out that it's not the best way to do things. So I eventually ended up polling the events instead.

              It's also noteworthy to mention that Qt wants to "own" the event loop, so even if you do something like the described you may end up smack in the middle of a war who gets events - Qt or ACE

              It's not exactly an answer to your question, but I hope it's helpful.
              Kind regards.

              D Offline
              D Offline
              DRoscoe
              wrote on 2 May 2016, 13:44 last edited by
              #6

              @kshegunov I don't know why I didn't think of this previously, but I came up with a simple solution. In the end, I ended up with a QTimer instance with a recurring timer. However, when a timeout signal is received and the call to:

              ::processAceEvents()
              

              Is made, I stop the timer. This prevents the stacked timeout issue I was concerned about. I start the timer again, once the call finished:

                ace_event_timer->stop(); // prevent any more timer events
                ACE_Time_Value timeout(0, 10000); // 10ms
                ACE_Reactor::instance()->handle_events(timeout);
                ace_event_timer->start(20); //20ms polling
              

              Having the QTime instance, then, allows me to stop the timer upon receipt of the aboutToQuit() signal.

              Your insights were good. I learned quite a bit investigating your ideas, before stumbling upon my final solution. Perhaps it will benefit me in the future.

              Thanks!

              K 1 Reply Last reply 2 May 2016, 13:51
              0
              • D DRoscoe
                2 May 2016, 13:44

                @kshegunov I don't know why I didn't think of this previously, but I came up with a simple solution. In the end, I ended up with a QTimer instance with a recurring timer. However, when a timeout signal is received and the call to:

                ::processAceEvents()
                

                Is made, I stop the timer. This prevents the stacked timeout issue I was concerned about. I start the timer again, once the call finished:

                  ace_event_timer->stop(); // prevent any more timer events
                  ACE_Time_Value timeout(0, 10000); // 10ms
                  ACE_Reactor::instance()->handle_events(timeout);
                  ace_event_timer->start(20); //20ms polling
                

                Having the QTime instance, then, allows me to stop the timer upon receipt of the aboutToQuit() signal.

                Your insights were good. I learned quite a bit investigating your ideas, before stumbling upon my final solution. Perhaps it will benefit me in the future.

                Thanks!

                K Offline
                K Offline
                kshegunov
                Moderators
                wrote on 2 May 2016, 13:51 last edited by kshegunov 5 Feb 2016, 13:52
                #7

                @DRoscoe
                So you ended up polling as well. :)
                Btw, I would block the timer signals instead of restarting it (although it should behave pretty much the same way, but it still depends if you're running on one thread or more):

                ace_event_timer->blockSignals(true); // prevent any more timer events
                ACE_Time_Value timeout(0, 10000); // 10ms
                ACE_Reactor::instance()->handle_events(timeout);
                ace_event_timer->blockSignals(false); //20ms polling
                

                Kind regards.

                Read and abide by the Qt Code of Conduct

                1 Reply Last reply
                1

                1/7

                26 Apr 2016, 15:51

                • Login

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