boostorg / boostorg/cobalt

Race() won't compile if as_tuple() or as_result() used to wrap awaitable parameter(s)

Ouverte
#271 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub
Langage dominant
C++
Étoiles
347
Forks
47
Merge moyen
3 j 8 h
PR mergées (30 j)
1

Description

Tested against develop and 1.90.0 tag, on Linux using gcc 14.2.0, -std=c++23.

It doesn't appear to be possible to use as_tuple() or as_result() to wrap awaiter parameters to race().

I want to use this approach as it makes it easier to determine the source of an error, rather than relying on catching system_error from race().

I am unsure if this is by design, and couldn't immediately see a workaround other than not using these conversion wrappers.

Reproducer:

```

#include
#include
#include

using namespace boost;
using namespace std::chrono_literals;

// Uncomment one or none
// #define USE_AS_TUPLE
// #define USE_AS_RESULT

cobalt::main co_main(int, char *[]) {

std::cout << "Starting co_main\nEnter a character: " << std::flush;

cobalt::io::stream_file stdin_stream(::dup(STDIN_FILENO));
cobalt::io::steady_timer timer(10s);
char buffer[1];

// Note: stream_file::read_some() used here rather than cobalt::read() because
// read() doesn't cancel when race is won by timer (see Cobalt Github Issue 270)

#if defined(USE_AS_TUPLE)
// Won't compile:
auto result =
co_await cobalt::race(as_tuple(stdin_stream.read_some(asio::buffer(buffer, 1))), as_tuple(timer.wait()));

switch (result.index()) {
case 0: {
auto [ec, n] = get<0>(result);
if (ec) {
std::cout << "Read error: " << ec.what() << std::endl;
} else {
std::cout << "Read: " << n << " byte: " << std::string_view(buffer, n) << std::endl;
}
break;
}
case 1: {
auto [ec] = get<1>(result);
if (ec) {
std::cout << "Timer error: " << ec.what() << std::endl;
} else {
std::cout << "Read timed out\n";
}
break;
}
}
#elif defined(USE_AS_RESULT)
// Wont compile:
auto result =
co_await cobalt::race(as_result(stdin_stream.read_some(asio::buffer(buffer, 1))), as_result(timer.wait()));

switch (result.index()) {
case 0: {
auto r = get<0>(result);
if (r.error()) {
std::cout << "Read error: " << r.error().what() << std::endl;
} else {
std::cout << "Read: " << *r << " byte: " << std::string_view(buffer, *r) << std::endl;
}
break;
}
case 1: {
auto r = get<1>(result);
if (r.error()) {
std::cout << "Timer error: " << r.error().what() << std::endl;
} else {
std::cout << "Read timed out\n";
}
break;
}
}

#else
// Will compile
try {
auto result = co_await cobalt::race(stdin_stream.read_some(asio::buffer(buffer, 1)), timer.wait());

switch (result.index()) {
case 0: {
auto r = get<0>(result);
std::cout << "Read: " << r << " byte: " << std::string_view(buffer, r) << std::endl;
break;
}
case 1: {
std::cout << "Read timed out\n";
break;
}
}
} catch (system::system_error & ex) {
std::cout << "Exception: " << ex.what() << std::endl;
}
#endif

std::cout << "Done\n";

co_return 0;
}
```

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.