3 ms·
This article hits on a number of interesting points. There is a lot of complexity to be aware of when using C++ coroutines. And a number of “normal” practices b
by cshokie 3y ago
This article hits on a number of interesting points. There is a lot of complexity to be aware of when using C++ coroutines. And a number of “normal” practices become dangerous in them, such as pass by reference.
That said, I think they are still very much worth it. Older asynchronous programming libraries in C++ are so verbose and so much worse than coroutines that it’s an obvious choice to use coroutines.
Also, there is another hazard that the author does not mention in this article: RAII lock wrappers. Holding a lock across suspension points is super dangerous. At best it wastes performance to leave it locked when blocked. At worst it can create deadlocks or corrupt the lock if it is released on a different thread than it was acquired.
- commonlisp94 3y ago> it’s an obvious choice to use coroutines. I agree, but the other choice is to have traditional threads of execution that block. This simple strategy has delivered more successful projects than any other.
- mgaunard 3y agoI don't understand how it is any more verbose.
- meindnoch 3y ago>RAII lock wrappers You don't even need coroutines for this to be dangerous. Holding locks over callback invocations is a pet peeve of mine in PR reviews. Callback invocations, like suspension points, can inject arbitrary operations into our code, which can easily break prior invariants, yet look innocuous for the casual reader.
- surajrmal 3y agoI often just add a task to a runtime queue which gets called once the stack fully unwinds to avoid these sorts of issues. You may not be aware of what locks were acquired prior to your current function being called. Reentrant safe code is considerably more challenging. This might have some overhead as callback parameters have to be placed in the heap, but it's usually worthwhile.
- rockwotj 3y agoAs someone who writes in C++ and uses coroutines everyday for work, I find for our use case this is actually helpful. We use seastar.io a thread per core framework and locks are "async" friendly in that they yield for access instead of blocking. Also embracing fully async message passing between threads simplifies the programming model a ton.