Tenho um Event
design bastante direto, que define uma trigger()
função e operator co_await()
mantém um conjunto de awaitables, que ele retoma quando acionado. Uma demonstração está aqui .
struct Event{
void trigger();
auto operator co_await();
private:
class Awaitable;
std::set<Awaitable*> awaitables;
bool triggered;
};
struct Event::Awaitable {
explicit Awaitable(Event* e) : evt(e) {}
bool await_ready() const noexcept { return evt->triggered; }
void await_suspend(std::coroutine_handle<> h) {
std::cout << "await_suspend\n";
awaiter = h;
evt->awaitables.insert(this);
}
void await_resume() {std::cout << "await_resume\n"; }
bool await_must_resume() const noexcept { return false; }
private:
friend Event;
Event* evt;
std::coroutine_handle<> awaiter;
public:
};
auto Event::operator co_await() { return Awaitable{this}; }
void Event::trigger() {
triggered = true;
std::cout << "resuming " << awaitables.size() << " awaitable(s)\n";
for(auto&& a : std::move(awaitables))
a->awaiter.resume();
}
Compilar no gcc e executar mostra que await_suspend
é chamado, que é o que eu esperaria. Mas o MSVC chama await_resume
em vez disso, o que não consigo explicar. Isso é um bug no compilador ou no UB no design?
usar uma variável inicializada é UB.
corrigindo
bool triggered = false;
oubool triggered{};
corrigindo seu problema.demonstração godbolt