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.7k 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 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
    • kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on 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
      0
      • S Offline
        S Offline
        sandy.martel23
        wrote on 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
        • kshegunovK kshegunov

          @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 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.

          kshegunovK 1 Reply Last reply
          0
          • D DRoscoe

            @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.

            kshegunovK Offline
            kshegunovK Offline
            kshegunov
            Moderators
            wrote on 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
            1
            • kshegunovK kshegunov

              @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 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!

              kshegunovK 1 Reply Last reply
              0
              • D DRoscoe

                @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!

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by kshegunov
                #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

                • Login

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