coroutine condition_variable
I'm using asio's awaitable. Couroutines are pretty neat. One of the things that keeps cropping up in the ability to notify another function that something has finished. In the past, I would use condition_variable and wait on that. Is there a better way to do that with coroutines? eg, I want to do something like: asio::awaitable<void> function(std::mutex& mtx, condition_variable& cv) { std::unique_lock lock{mtx}; // suspend this function until notified or 30 seconds expired auto expired = co_await cv.wait_until(lock, std::chrono::seconds(30)); if (expired) { // or something log("expired"); co_return; } do_some_work(); } then somewhere else I might do: asio::awaitable<void> somewhere_else(condition_variable& cv) { do_other_work(); cv.notify_one(); } I understand that it's a bad idea to hold a lock during co_await. What other problems prevent something like this from being created? Does something like this already exist? It's not clear from asio reference. I'm using boost 1.81.0 but I can upgrade if that is a problem -- Keith Bennett
On Tue, Dec 5, 2023 at 5:43 PM Keith Bennett via Boost-users < boost-users@lists.boost.org> wrote:
One of the things that keeps cropping up in the ability to notify another function that something has finished.
So... "call a function to indicate something has finished?" If only there was something like that... Thanks
From my perspective, I already have something that's using condition_variables. I want to straight adapt it into coroutines as much as
Hi Vinnie, I'd like to think that my question was legitimate and clear. "If only there was something like that" sounds snarky to me and doesn't answer the question at all. Maybe behind the scenes it might look like there's just another function to call when complete. But how do I go from *there* to... resuming a different coroutine which is waiting for that function to complete? possible. I don't want to "call a function to indicate something has finished". That's far more friction required. I spent a couple hours poking around asio documentation and didn't find a solution. To be fair, there's a ton of things in asio that are described with a C++ declaration and zero description whatsoever of what it does. So perhaps it is already solved. So maybe the problem already is solved and I just didn't see it. Can you point me to exactly a coroutine-enabled condition_variable? Or perhaps you can point me to specific documentation to read? Thanks, Keith On Tue, Dec 5, 2023 at 7:48 PM Vinnie Falco via Boost-users < boost-users@lists.boost.org> wrote:
On Tue, Dec 5, 2023 at 5:43 PM Keith Bennett via Boost-users < boost-users@lists.boost.org> wrote:
One of the things that keeps cropping up in the ability to notify another function that something has finished.
So... "call a function to indicate something has finished?" If only there was something like that...
Thanks
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Keith Bennett
On Wed, Dec 6, 2023 at 6:19 AM Keith Bennett via Boost-users < boost-users@lists.boost.org> wrote:
"If only there was something like that" sounds snarky to me and doesn't answer the question at all.
You are right about that but honestly it is irresistible for me to go for the obvious punchline :) For those that don't know, I am referring to "callbacks." I want to straight adapt it into coroutines as much as possible.
Conditional variables are an anti-pattern in asynchronous code, because the wait state ties up the calling thread. Anyway... you could create a `boost::asio::experimental::basic_channel` using the signature `(void)` and then `co_await` the channel to suspend the coroutine. Later when you want to wake it up, send a message to the channel from elsewhere. You will need to be thoughtful about the order of how things are destroyed if you want to tear down the socket (or corresponding I/O object). More here: https://www.boost.org/doc/libs/1_83_0/doc/html/boost_asio/reference/experime... Thanks
Anyway... you could create a `boost::asio::experimental::basic_channel`
using the signature `(void)` and then `co_await` the channel to suspend the coroutine. Later when you want to wake it up, send a message to the channel from elsewhere. You will need to be thoughtful about the order of how things are destroyed if you want to tear down the socket (or corresponding I/O object). More here:
https://www.boost.org/doc/libs/1_83_0/doc/html/boost_asio/reference/experime...
This is actually Chris' recommended solution. It's so new I forgot about it. :)
Thanks
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
On Wed, Dec 6, 2023 at 9:20 AM Richard Hodges via Boost-users < boost-users@lists.boost.org> wrote:
Anyway... you could create a `boost::asio::experimental::basic_channel`
using the signature `(void)` and then `co_await` the channel to suspend the coroutine. Later when you want to wake it up, send a message to the channel from elsewhere. You will need to be thoughtful about the order of how things are destroyed if you want to tear down the socket (or corresponding I/O object). More here:
https://www.boost.org/doc/libs/1_83_0/doc/html/boost_asio/reference/experime...
This is actually Chris' recommended solution. It's so new I forgot about it. :)
Ahh it's still experimental in 1.83.0. I'd rather avoid experimental things for now. I look forward to it coming out of experimental. -- Keith Bennett
On Wed, 6 Dec 2023 at 23:35, Keith Bennett via Boost-users < boost-users@lists.boost.org> wrote:
On Wed, Dec 6, 2023 at 9:20 AM Richard Hodges via Boost-users < boost-users@lists.boost.org> wrote:
Anyway... you could create a `boost::asio::experimental::basic_channel`
using the signature `(void)` and then `co_await` the channel to suspend the coroutine. Later when you want to wake it up, send a message to the channel from elsewhere. You will need to be thoughtful about the order of how things are destroyed if you want to tear down the socket (or corresponding I/O object). More here:
https://www.boost.org/doc/libs/1_83_0/doc/html/boost_asio/reference/experime...
This is actually Chris' recommended solution. It's so new I forgot about it. :)
Ahh it's still experimental in 1.83.0. I'd rather avoid experimental things for now. I look forward to it coming out of experimental.
Channels are robust. Chris is a fan of them. I think it’s fair to say that he sees every async-concurrency synchronisation primitive being implemented with some configuration of a channel.
-- Keith Bennett
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
One of the things that keeps cropping up in the ability to notify another function that something has finished. In the past, I would use condition_variable and wait on that.
There are a couple of ways I have used to do this.
Have a look at Klemens' experimental library https://github.com/klemens-morgenstern/sam It contains an async condition variable fully compatible with asio The other way is to use an asio steady_timer. You would cancel the timer in order to signal the condition. The waiter would see this as an *operation_aborted* error, which would indicate, "you have been signalled". You can set the timer to expires_at(std::chrono::steady_clock::max()) to indicate that the wait should be indefinite. R
On Wed, Dec 6, 2023 at 8:46 AM Richard Hodges via Boost-users < boost-users@lists.boost.org> wrote:
The other way is to use an asio steady_timer. You would cancel the timer in order to signal the condition. The waiter would see this as an *operation_aborted* error, which would indicate, "you have been signalled". You can set the timer to expires_at(std::chrono::steady_clock::max()) to indicate that the wait should be indefinite.
Ahh right, I forgot about infinite waits on a timer. That will solve it, thank you! -- Keith Bennett
participants (3)
-
Keith Bennett
-
Richard Hodges
-
Vinnie Falco