boost::asio::steady_timer only firing once

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

boost::asio::steady_timer only firing once

Boost - Users mailing list
I am trying to perform a task on an interval and I made a POC using boost::asio::steady_timer. When I debug it, it only performs the callback once and does not fire again. I am not sure what I am doing wrong. Any suggestions?

    // DoMouseEvents.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //

    #include <boost/asio.hpp>
    #include "boost/asio/deadline_timer.hpp"
    #include<boost/bind.hpp>
    #include <chrono>
    #include <iostream>

    class Pooper
    {
        boost::asio::io_context & m_ioContext;
        boost::asio::steady_timer m_timer;

    public:
        Pooper(boost::asio::io_context & ioContext)
            :
            m_ioContext(ioContext)
            , m_timer(boost::asio::steady_timer(ioContext))
        {
        }

        void Run()
        {
            m_timer.expires_from_now(std::chrono::seconds(5));
            m_timer.async_wait(boost::bind(&Pooper::OnTimerExpired, this, boost::asio::placeholders::error));
        }

        void OnTimerExpired(const boost::system::error_code & error)
        {
            if (error.failed())
            {
                std::cerr << "boost error: Failed" << std::endl;
            }

            std::cout << "Poop" << std::endl;

            try
            {
                // Move the mouse
                int x = 500;
                int y = 500;
                if (!::SetCursorPos(x, y))
                {
                    int errorCode = GetLastError();
                    std::cerr << "SetCursorPos error: " << errorCode << std::endl;
                }

                // Left button down
                x = 65536 * 500;
                y = 65536 * 500;
                ::mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN, x, y, NULL, NULL);

                // Left button up
                x = 65536 * 500;
                y = 65536 * 500;
                ::mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP, x, y, NULL, NULL);

                m_timer.expires_from_now(std::chrono::seconds(5));
                m_timer.async_wait(boost::bind(&Pooper::OnTimerExpired, this, boost::asio::placeholders::error));
            }
            catch (std::exception &)
            {
                std::cerr << "An exception occured." << std::endl;
            }
        }
    };

    int main()
    {
        boost::asio::io_context ioContext;
        auto pooper = Pooper(ioContext);
        pooper.Run();
        ioContext.run();

        std::cerr << "Exited..." << std::endl;
    }


_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: boost::asio::steady_timer only firing once

Boost - Users mailing list
On Thu, Jul 11, 2019 at 5:43 PM Christopher Pisz via Boost-users
<[hidden email]> wrote:
> boost::asio::steady_timer...only performs the callback once and does not fire again.
> I am not sure what I am doing wrong. Any suggestions?

That's how it is supposed to work. If you want it to fire again, call
async_wait again.

Regards
_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: boost::asio::steady_timer only firing once

Boost - Users mailing list
In reply to this post by Boost - Users mailing list
On Fri, 12 Jul 2019 at 03:43, Christopher Pisz via Boost-users <[hidden email]> wrote:
I am trying to perform a task on an interval and I made a POC using boost::asio::steady_timer. When I debug it, it only performs the callback once and does not fire again. I am not sure what I am doing wrong. Any suggestions?

Why would it 'fire' more than once, there is no loop?

int main() {
    boost::asio::io_context ioContext;
    auto pooper = Pooper(ioContext);
    while ( true ) {
         pooper.Run();
        ioContext.run();
    }
    std::cerr << "Exited..." << std::endl;
}

Now it will poop till you drop.

Other than that, this appears to be [you don't state what you would like to achieve] some kind of event-loop, where you suspend till the next frame. You can suspend the current thread with std::this_thread::sleep_for ( std::chrono::milliseconds ( milliseconds_to_sleep ) ); or  std::this_thread::sleep_until ( some_time_point_in_the_future ); using just std-lib facilities. Having said that, have a look at SFML (https://www.sfml-dev.org/), which has all those things, event-loop, event-polling, mouse, touch, joy-stick, sound, image rendering, window creation etc.

degski
--
@realdegski
"Anyone who believes that exponential growth can go on forever in a finite world is either a madman or an economist" - Kenneth E. Boulding

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: boost::asio::steady_timer only firing once

Boost - Users mailing list
In reply to this post by Boost - Users mailing list
async_wait is called again in the call back. It is scheduled every time it fires.

On Thu, Jul 11, 2019 at 11:54 PM Vinnie Falco via Boost-users <[hidden email]> wrote:
On Thu, Jul 11, 2019 at 5:43 PM Christopher Pisz via Boost-users
<[hidden email]> wrote:
> boost::asio::steady_timer...only performs the callback once and does not fire again.
> I am not sure what I am doing wrong. Any suggestions?

That's how it is supposed to work. If you want it to fire again, call
async_wait again.

Regards
_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: boost::asio::steady_timer only firing once

Boost - Users mailing list
In reply to this post by Boost - Users mailing list
No loop should be needed. io context runs until there is no more work.
There is always work as long as the timer is being waited on,

On Fri, Jul 12, 2019 at 12:00 AM degski via Boost-users <[hidden email]> wrote:
On Fri, 12 Jul 2019 at 03:43, Christopher Pisz via Boost-users <[hidden email]> wrote:
I am trying to perform a task on an interval and I made a POC using boost::asio::steady_timer. When I debug it, it only performs the callback once and does not fire again. I am not sure what I am doing wrong. Any suggestions?

Why would it 'fire' more than once, there is no loop?

int main() {
    boost::asio::io_context ioContext;
    auto pooper = Pooper(ioContext);
    while ( true ) {
         pooper.Run();
        ioContext.run();
    }
    std::cerr << "Exited..." << std::endl;
}

Now it will poop till you drop.

Other than that, this appears to be [you don't state what you would like to achieve] some kind of event-loop, where you suspend till the next frame. You can suspend the current thread with std::this_thread::sleep_for ( std::chrono::milliseconds ( milliseconds_to_sleep ) ); or  std::this_thread::sleep_until ( some_time_point_in_the_future ); using just std-lib facilities. Having said that, have a look at SFML (https://www.sfml-dev.org/), which has all those things, event-loop, event-polling, mouse, touch, joy-stick, sound, image rendering, window creation etc.

degski
--
@realdegski
"Anyone who believes that exponential growth can go on forever in a finite world is either a madman or an economist" - Kenneth E. Boulding
_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: boost::asio::steady_timer only firing once

Boost - Users mailing list
In reply to this post by Boost - Users mailing list
It looks like my problems aren't with the timer at all. This listing pretty much mimicked example 3.
It ends up that my problem is that if you click on a console window in windows 10, the program ceases execution when it enters "quick edit" mode. I was not aware of that new behavior and thought the timer was not working. The program run fine, as is, if you don't touch the mouse.

Sorry, false alarm.

On Thu, Jul 11, 2019 at 7:42 PM Christopher Pisz <[hidden email]> wrote:
I am trying to perform a task on an interval and I made a POC using boost::asio::steady_timer. When I debug it, it only performs the callback once and does not fire again. I am not sure what I am doing wrong. Any suggestions?

    // DoMouseEvents.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //

    #include <boost/asio.hpp>
    #include "boost/asio/deadline_timer.hpp"
    #include<boost/bind.hpp>
    #include <chrono>
    #include <iostream>

    class Pooper
    {
        boost::asio::io_context & m_ioContext;
        boost::asio::steady_timer m_timer;

    public:
        Pooper(boost::asio::io_context & ioContext)
            :
            m_ioContext(ioContext)
            , m_timer(boost::asio::steady_timer(ioContext))
        {
        }

        void Run()
        {
            m_timer.expires_from_now(std::chrono::seconds(5));
            m_timer.async_wait(boost::bind(&Pooper::OnTimerExpired, this, boost::asio::placeholders::error));
        }

        void OnTimerExpired(const boost::system::error_code & error)
        {
            if (error.failed())
            {
                std::cerr << "boost error: Failed" << std::endl;
            }

            std::cout << "Poop" << std::endl;

            try
            {
                // Move the mouse
                int x = 500;
                int y = 500;
                if (!::SetCursorPos(x, y))
                {
                    int errorCode = GetLastError();
                    std::cerr << "SetCursorPos error: " << errorCode << std::endl;
                }

                // Left button down
                x = 65536 * 500;
                y = 65536 * 500;
                ::mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN, x, y, NULL, NULL);

                // Left button up
                x = 65536 * 500;
                y = 65536 * 500;
                ::mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP, x, y, NULL, NULL);

                m_timer.expires_from_now(std::chrono::seconds(5));
                m_timer.async_wait(boost::bind(&Pooper::OnTimerExpired, this, boost::asio::placeholders::error));
            }
            catch (std::exception &)
            {
                std::cerr << "An exception occured." << std::endl;
            }
        }
    };

    int main()
    {
        boost::asio::io_context ioContext;
        auto pooper = Pooper(ioContext);
        pooper.Run();
        ioContext.run();

        std::cerr << "Exited..." << std::endl;
    }


_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: boost::asio::steady_timer only firing once

Boost - Users mailing list
In reply to this post by Boost - Users mailing list
On 12/07/2019 12:42, Christopher Pisz wrote:
> I am trying to perform a task on an interval and I made a POC using
> boost::asio::steady_timer. When I debug it, it only performs the
> callback once and does not fire again. I am not sure what I am doing
> wrong. Any suggestions?

I can't see any particular reason why this shouldn't work.

Have you tried it in older versions of Boost.Asio?  It wouldn't surprise
me if somewhere in the switchover to io_contexts and executors,
something has broken the execution guarantees.

In particular I think timers are implemented with a helper thread, so
it's marshalling work between two different contexts, and it wouldn't
surprise me if there were a moment when the outer context doesn't have
any work but the inner context does.

Most apps wouldn't notice since they use a work/run loop to keep the
context running when there's no "work".

(I really think Asio has become too complicated for its own good.)
_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: boost::asio::steady_timer only firing once

Boost - Users mailing list
In reply to this post by Boost - Users mailing list
On Fri, Jul 12, 2019 at 7:11 AM Christopher Pisz via Boost-users <[hidden email]> wrote:
It ends up that my problem is that if you click on a console window in windows 10, the program ceases execution when it enters "quick edit" mode.
I was not aware of that new behavior and thought the timer was not working. The program run fine, as is, if you don't touch the mouse.

FWIW, that's not new behavior. It's always been that way in the DOS console. --DD 

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: boost::asio::steady_timer only firing once

Boost - Users mailing list
On 15/07/2019 18:34, Dominique Devienne wrote:

> On Fri, Jul 12, 2019 at 7:11 AM Christopher Pisz wrote:
>
>     It ends up that my problem is that if you click on a console window
>     in windows 10, the program ceases execution when it enters "quick
>     edit" mode.
>
>     I was not aware of that new behavior and thought the timer was not
>     working. The program run fine, as is, if you don't touch the mouse.
>
> FWIW, that's not new behavior. It's always been that way in the DOS
> console. --DD

Prior to Windows 10, QuickEdit was disabled by default, though.  It only
paused if you selected the Mark menu option explicitly, not if you
simply left-clicked the window.  (Unless you enabled that option yourself.)

You can turn QuickEdit off in the console properties if it's annoying.

(Also, oddly, I didn't receive Christopher's reply above...)
_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: boost::asio::steady_timer only firing once

Boost - Users mailing list
On 16.07.19 02:27, Gavin Lambert via Boost-users wrote:

> On 15/07/2019 18:34, Dominique Devienne wrote:
>> On Fri, Jul 12, 2019 at 7:11 AM Christopher Pisz wrote:
>>
>>     It ends up that my problem is that if you click on a console window
>>     in windows 10, the program ceases execution when it enters "quick
>>     edit" mode.
>>
>>     I was not aware of that new behavior and thought the timer was not
>>     working. The program run fine, as is, if you don't touch the mouse.
>>
>> FWIW, that's not new behavior. It's always been that way in the DOS
>> console. --DD
>
> Prior to Windows 10, QuickEdit was disabled by default, though. It
> only paused if you selected the Mark menu option explicitly, not if
> you simply left-clicked the window.  (Unless you enabled that option
> yourself.)
>
> You can turn QuickEdit off in the console properties if it's annoying.
>

For what it's worth:
I ran into the same "problem" when I was porting some apps to Windows 10;
so I decided to restore the old behaviour by running this code during
startup (when starting inside a console):

static void console_disable_quick_edit()
{
     DWORD console_mode;
     HANDLE console_handle = GetStdHandle( STD_INPUT_HANDLE );

     if( NULL == console_handle )
     { return; }

     if( GetConsoleMode( console_handle, &console_mode ) )
     {
         console_mode &= ~ENABLE_QUICK_EDIT_MODE;
         SetConsoleMode( console_handle, (console_mode | ENABLE_EXTENDED_FLAGS) );
     }

     CloseHandle( console_handle );
}

Regards, Andreas


_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: boost::asio::steady_timer only firing once

Boost - Users mailing list
In reply to this post by Boost - Users mailing list
On Tue, Jul 16, 2019 at 2:28 AM Gavin Lambert via Boost-users <[hidden email]> wrote:
On 15/07/2019 18:34, Dominique Devienne wrote:
> On Fri, Jul 12, 2019 at 7:11 AM Christopher Pisz wrote:
>     It ends up that my problem is that if you click on a console window
>     in windows 10, the program ceases execution when it enters "quick edit" mode.
> FWIW, that's not new behavior. It's always been that way in the DOS console. --DD

Prior to Windows 10, QuickEdit was disabled by default, though.

Good point, thanks. I indeed always enable it myself. And still mainly on Win7,
so wasn't aware of the default change. Thanks for Andreas' code snippet too, interesting.
Not sure changing the behavior of the console is a good idea, there are pros and cons both sides. --DD

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users