Boost logo

Boost :

From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2023-11-09 16:28:28


czw., 9 lis 2023 o 16:01 Andrzej Krzemienski <akrzemi1_at_[hidden]>
napisał(a):

>
>
> czw., 9 lis 2023 o 15:09 Klemens Morgenstern <
> klemensdavidmorgenstern_at_[hidden]> napisał(a):
>
>> On Thu, Nov 9, 2023 at 9:41 PM Andrzej Krzemienski via Boost
>> <boost_at_[hidden]> wrote:
>>
>>
>> > In Boost.Cobalt (formerly Boost.Async) we have function cobalt::race
>> > (formerly select()) that takes a range of awaitables `p` and returns an
>> > awaitable capable on awaiting on one of the elements of `p`:
>> >
>> >
>> https://www.boost.org/doc/libs/develop/libs/cobalt/doc/html/index.html#race-outline
>> >
>> > Example:
>> >
>> > ```
>> > promise<string> talk_to_server_1();
>> > promise<string> talk_to_server_2();
>> > promise<string> timeout_with_default();
>> >
>> > vector<promise<int>> servers = { talk_to_server_1(), talk_to_server_2(),
>> > timeout_with_default() };
>> > pair<size_t, string> ans = co_await race(servers);
>> > ```
>> >
>> > This obviously cannot work when the input range passed to `race` is
>> empty.
>>
>> This example doesn't help, because this should obviously use the
>> variadic version.
>>
>> The reason to use the ranged one is for when you have another
>> component dictating what elements to listen to.
>>
>> try
>> {
>> vector<promise<int>> servers;
>> for (const auto & server : config.get_servers())
>> servers.push_back(talk_to_server(server));
>>
>> co_await race(servers);
>> }
>> catch(std::exception &)
>> {
>> // handle errors from running any server
>> }
>>
>> That means the code using the ranged version is likely unaware of the
>> actual value, because there's a very high likelihood it's not known at
>> compile time.
>>
>
> Thanks Klemens. This is very useful information (when to use which
> overload), and I recommend that it should be put in the documentation.
>

Actually, your explanation convinces me even stronger that this should be a
different function with a different name. It is a different use case, it
has a different signature, a different return type.

Regards,
&rzej;

>
> Stil, I do not feel convinced. Your example illustrates, I think, the
> situation where an untrusted external input is passed unvalidated to the
> guts of the program. I would never like to encourage or support this way of
> writing servers. Of course, people will still do it, and it is prudent of
> you to be prepared for it, but I would still strongly insist that your
> library calls this usage a bug: that is something that the programmer
> should fix as soon as they can. It doesn't prevent you from throwing
> exceptions, but you have an opportunity to additionally discourage the use
> like this (via warnings, crashes in debug mode, additional control flows in
> debugger).
>
> >
>> > Hi Everyone,
>> > I would like to discuss one correctness aspect of Boost.COBALT. We have
>> > this list and the Slack channel, so I am not sure which place is better.
>> > Let me do it here.
>> >
>>
>> I don't see why this is a correctness issue and not a design choice.
>> When is it correct to use an exception?
>>
>
> To some extent, this is your choice as a library author. But I am trying
> to set up a guideline or a policy applicable to a range of libraries.
> The uncontroversial circumstance that warrants a throw, is when a function
> cannot deliver its promise, but the caller couldn't have known about it
> when calling a function:
>
> ```
> File f ("C:/folder/filename.cfg");
> ```
> Here I checked that the file existed one millisecond ago. I requested for
> it to be open, but the OS determined that the file is no longer there.
> There was nothing I can do to guarantee that the file would be openable.
>
> The case with `race` is different. There is a very simple way of checking
> the empty-range, and it never can produce a meaningful result.
>
> Regards,
> &rzej;
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk