Skip to content

dispatch coroutine initiation function - #834

Closed
ZerocksX wants to merge 1 commit into
chriskohlhoff:masterfrom
ZerocksX:master
Closed

ZerocksX wants to merge 1 commit into
chriskohlhoff:masterfrom
ZerocksX:master

Conversation

@ZerocksX

@ZerocksX ZerocksX commented Jun 7, 2021

Copy link
Copy Markdown

#835

I noticed that dispatching coroutine initiation function to attached thread's executor solves this issue.

@ZerocksX
ZerocksX marked this pull request as ready for review June 7, 2021 11:55
@ZerocksX ZerocksX changed the title dispatch coroutine initialization function dispatch coroutine initiation function Jun 7, 2021
@ZerocksX

ZerocksX commented Jun 9, 2021

Copy link
Copy Markdown
Author

When running this code

#include <boost/asio/co_spawn.hpp>
#include <boost/asio/awaitable.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/strand.hpp>

#include <cstdio>
#include <thread>

namespace net = boost::asio;

class my_app {
    using strand_t = net::strand<net::io_context::executor_type>;

private:    
    strand_t _strand;
    net::steady_timer _render_timer;
    static inline const int render_wait_target_ms = 33;

public:
    template <class T>
    my_app(T&& executor) 
        : _strand(net::make_strand(executor)), _render_timer(_strand) {
    }

    net::awaitable<void> run() {
        using namespace std::chrono;
        auto last_render = steady_clock::now();
        int sleep_ms = 0;
        for(;;) {
            int render_time = co_await render();
            printf("Time to render: %d\n", render_time);
            auto now = steady_clock::now();
            int passed_ms = duration_cast<milliseconds>(now - last_render).count() - sleep_ms;
            last_render = now;
            sleep_ms = std::max(
                render_wait_target_ms - passed_ms,
                0
            );
            _render_timer.expires_after(milliseconds(sleep_ms));
            printf("Passed %dms, waiting for %dms\n", passed_ms, sleep_ms);
            co_await _render_timer.async_wait(net::use_awaitable);
        }
    }

    strand_t strand() {
        return _strand;
    }

private:
    net::awaitable<int> render() {
        int work_done = rand() % 10 + 5;
        std::this_thread::sleep_for(std::chrono::milliseconds(work_done));
        printf("Rendered at %zd\n", 
            std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count() % 100000
        );
        co_return work_done;
    }
};

int main(int argc, char** argv) {
    net::io_context ioc;
    auto app = my_app(ioc);
    net::post(
        app.strand(),
        app.run(),
        net::detached
    );
    ioc.run();
    return 0;
}

impl/use_awaitable.hpp async_result::initiate(Initiation, use_awaitable, Initargs...) reaches this line for (;;) {} // Never reached.
I will look more into this.

@ZerocksX ZerocksX closed this Jun 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant