Boost logo

Boost :

From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2023-11-09 13:41:10


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.

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.
Boost.COBALT docs say that for this situation "Selecting an empty range
will cause an exception to be thrown". But I do not think it is the right
approach. The right approach would be to clearly communicate to the user of
the library that this is an incorrect usage of the library: if you pass an
empty range to `race` you clearly do not know what you are doing, or you
simply overlooked it and planted a bug.

The library should list it as a *precondition* in the docs: the passed
range cannot be empty. If you do it, you cannot expect your program to work
correctly.

>From the perspective of the library author, you can now, for the event of
passing the empty range, putt all the tools that help in debugging:
* BOOST_ASSERT
* insert a breakpoint

And on the next line, you can also throw an exception to avoid an UB. But
in that case the exception would not be part of the official contract.

If the docs just say "throws an exception" (as today, which I think is
wrong) then the library author is not allowed to insert any debugging aids
(such as BOOST_ASSERT or breaking into the debugger) because the user may
be relying on the exception throw.

You do not want the users to rely on the exception throw: you want to
prevent the users from passing the empty range.

What do others think about it?

Regards,
&rzej;


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