You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Addition of so_evt_async_start to the agent_t?
#114
works as I expected. But writing unit tests I noticed repetitions of this pattern:
classdemo : publicso_5::agent_t
{
structmsg_start_asyncfinal : public so_5::signal_t {};
...
public:demo(context_t ctx)
: so_5::agent_t{ ctx + so_5::enable_cpp_coro() }
{...}
...
voidso_define_agent() override
{
so_subscribe_self().event(&demo::evt_async_start);
}
voidso_evt_start() override
{
// Usually it's only one action in so_evt_start.
so_5::send<msg_start_async>(*this);
}
...
so_5::cpp_coro::task_t<void>
evt_async_start(mhood_t<msg_start_async>)
{
... // The actual starting actions that may use co_await.
}
...
};
It's a direct consequence of the fact that so_evt_start is a synchronous event. It can't use coroutines inside. Because of that it's necessary to send a helper signal that will be handled in an asynchronous event-handler where co_await can be used without a problem.
So I have an idea to add a new virtual method so_evt_async_start to the agent_t class. It will have the default implementation:
And a user could override it for their own purposes. With presence of such a method the code above will look like that:
classdemo : publicso_5::agent_t
{
// No need to define a separate start signal.
...
public:demo(context_t ctx)
: so_5::agent_t{ ctx + so_5::enable_cpp_coro() }
{...}
...
// No need to override so_define_agent for just one subscription.// No need to override so_evt_start for just one send inside.
...
so_5::cpp_coro::task_t<void>
so_evt_async_start() override
{
... // The actual stating actions that may use co_await.
}
...
};
I hope such an approach will be much simpler and straightforward.
An important implementation note. The so_evt_async_start will be called only if so_5::enable_cpp_coro() is added to the agent's tuning options. Without so_5::enable_cpp_coro the support for C++20 coroutines is disabled for an agent and so_evt_async_start won't be called (even if it's overridden by a user).
Another important implementation note. There will be a strict order of invocations of so_evt_start and so_evt_async_start: the so_evt_start will be called first (even if it wasn't overridden in a derived class -- the inherited implementation will be invoked), and only then so_evt_async_start will be called. I think it's pretty obvious and logical.
The calls of so_evt_start and so_evt_async_start will go one after another without a possibility for event-handlers to be called in between. For example:
classmixed_start_demo : publicso_5::agent_t
{
structmsg_do_initfinal : public so_5::signal_t {};
...
public:demo(context_t ctx)
: so_5::agent_t{ ctx + so_5::enable_cpp_coro() }
{...}
...
voidso_define_agent() override
{
so_subscribe_self().event(&mixed_start_demo::evt_do_init);
...
}
voidso_evt_start() override
{
// This message will be sent to itself just before// invocation of so_evt_async_start.
so_5::send<msg_do_init>(*this);
...
}
...
so_5::cpp_coro::task_t<void>
so_evt_async_start() override
{
... // Other starting actions.
}
...
};
In such a case so_evt_start will be called first, then so_evt_async_start will be invoked and only then msg_do_init will be delivered to the agent.
I don't think that something like so_evt_async_finish is needed. At least at the current moment. But if you see cases where it would be useful, then please let me know.
PS. Such a feature with conjunction with coroutine's support opens a possibility to write agents that only have so_evt_async_start:
classagent_that_was_impossible_in_the_past : publicso_5::agent_t
{
public:agent_that_was_impossible_in_the_past(context_t ctx)
: so_5::agent_t{ ctx + so_5::enable_cpp_coro() }
{}
so_5::cpp_coro::task_t<void>
so_evt_async_start() override
{
... // A lot of actions with co_await. Without leaving so_evt_async_start,// without usage of states and so on...
}
};
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
I'm working on C++20 coroutines support for agents. For now such code:
works as I expected. But writing unit tests I noticed repetitions of this pattern:
It's a direct consequence of the fact that
so_evt_startis a synchronous event. It can't use coroutines inside. Because of that it's necessary to send a helper signal that will be handled in an asynchronous event-handler where co_await can be used without a problem.So I have an idea to add a new virtual method
so_evt_async_startto theagent_tclass. It will have the default implementation:And a user could override it for their own purposes. With presence of such a method the code above will look like that:
I hope such an approach will be much simpler and straightforward.
An important implementation note. The
so_evt_async_startwill be called only ifso_5::enable_cpp_coro()is added to the agent's tuning options. Withoutso_5::enable_cpp_corothe support for C++20 coroutines is disabled for an agent andso_evt_async_startwon't be called (even if it's overridden by a user).Another important implementation note. There will be a strict order of invocations of
so_evt_startandso_evt_async_start: theso_evt_startwill be called first (even if it wasn't overridden in a derived class -- the inherited implementation will be invoked), and only thenso_evt_async_startwill be called. I think it's pretty obvious and logical.The calls of
so_evt_startandso_evt_async_startwill go one after another without a possibility for event-handlers to be called in between. For example:In such a case
so_evt_startwill be called first, thenso_evt_async_startwill be invoked and only thenmsg_do_initwill be delivered to the agent.I don't think that something like
so_evt_async_finishis needed. At least at the current moment. But if you see cases where it would be useful, then please let me know.PS. Such a feature with conjunction with coroutine's support opens a possibility to write agents that only have
so_evt_async_start:All reactions