<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/coroutines-and-c---async-without-the-pain--eykxkotyv" -->

---
title: Coroutines and C++ - Async Without The Pain? | daily.dev
description: C++ coroutines have been standardized since C++20 but remain underused due to their low-level nature. This talk walks through practical coroutine usage using...
canonical: https://daily.dev/posts/coroutines-and-c---async-without-the-pain--eykxkotyv
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Coroutines and C++ - Async Without The Pain? | daily.dev
og:description: C++ coroutines have been standardized since C++20 but remain underused due to their low-level nature. This talk walks through practical coroutine usage using...
og:url: https://daily.dev/posts/coroutines-and-c---async-without-the-pain--eykxkotyv
og:image: https://api.daily.dev/og/posts/EyKxKoTyV.png
og:image:alt: Coroutines and C++ - Async Without The Pain?
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Coroutines and C++ - Async Without The Pain?

**[C\+\+Online](https://daily.dev/sources/cpponline)** · 54 min read · 0 upvotes · 0 comments

## Summary

C++ coroutines have been standardized since C++20 but remain underused due to their low-level nature. This talk walks through practical coroutine usage using the tiny-coro library, covering core concepts like tasks, awaitables, and schedulers. It demonstrates how coroutines enable non-blocking waits, composable awaitables (timeout, cancellation), structured concurrency via task groups, and producer-consumer patterns with buffer channels. Common pitfalls like dangling references with coroutine parameters, member functions, and lambda captures are also covered. The talk compares tiny-coro with other C++ coroutine libraries including cppcoro, coro (HRT), and Folly.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.youtube.com/watch?v=4keXOkbr0UY>

## Questions this post answers

### What is the difference between a task and an awaitable in C++ coroutines?

A task manages the lifetime of a coroutine, controlling the coroutine frame and suspension behavior, acting like a manager or controller. An awaitable is a small, temporary object used in a co_await expression whose only job is deciding whether, how, and when to suspend and resume a coroutine. Tasks are usually provided by libraries and hide complexity, while developers often write their own awaitables.

_Developers designing async APIs can find deeper coroutine breakdowns like this one on daily.dev._

### Why does using a const string reference in a C++ coroutine cause undefined behavior?

A const string reference parameter can bind to a temporary rvalue, and that temporary is destroyed once the coroutine is created but before it resumes after a suspension point, leaving a dangling reference. This causes undefined behavior when the coroutine later accesses the parameter. The safe fix is passing arguments by value into the coroutine so they are copied into the coroutine frame instead of referenced.

_Anyone debugging dangling reference bugs in async C++ code can track patterns like this on daily.dev._

### Why does TinyCoro only allow a scheduler to resume suspended coroutines instead of letting coroutines resume each other directly?

Allowing one coroutine to directly resume another can create an unbounded resume chain, similar to a linked list, that is never cleaned up and can cause very long call stacks or stack overflow in extreme cases. TinyCoro enforces that only the scheduler may resume suspended coroutines, following the same principle used in Swift, trading some performance overhead for full control over resumption and easier, more robust cancellation.

_Teams evaluating coroutine library design tradeoffs can compare approaches like this on daily.dev._

## Similar posts on daily.dev

- [Event-driven flows](https://daily.dev/posts/event-driven-flows-7nteqvyab) · Andrzej's C\+\+ blog · 0 upvotes · 0 comments
- [Coroutines – A Deep Dive](https://daily.dev/posts/coroutines-a-deep-dive-9yi5wwmdz) · C\+\+ · 1 upvotes · 1 comments
- [Looking at Unity finally made me understand the point of C\+\+ coroutines · Mathieu Ropert](https://daily.dev/posts/looking-at-unity-finally-made-me-understand-the-point-of-c-coroutines-mathieu-ropert-lyk7zdbtl) · Hacker News · 0 upvotes · 0 comments

---

Tags: [#c++](https://daily.dev/tags/c++)

[View this post on daily.dev](https://daily.dev/posts/coroutines-and-c---async-without-the-pain--eykxkotyv)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Coroutines and C++ - Async Without The Pain?","url":"https://daily.dev/posts/coroutines-and-c---async-without-the-pain--eykxkotyv","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/coroutines-and-c---async-without-the-pain--eykxkotyv"},"datePublished":"2026-07-23T16:18:19.493Z","dateModified":"2026-09-13T20:30:56.206Z","description":"C++ coroutines have been standardized since C++20 but remain underused due to their low-level nature. This talk walks through practical coroutine usage using...","image":"https://i.ytimg.com/vi/4keXOkbr0UY/sddefault.jpg","thumbnailUrl":"https://i.ytimg.com/vi/4keXOkbr0UY/sddefault.jpg","isAccessibleForFree":true,"articleSection":"C++Online","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"C++Online","logo":"https://media.daily.dev/image/upload/s--8WzMvjLJ--/f_auto,q_auto/v1783236334/logos/cpponline","url":"https://daily.dev/sources/cpponline"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/coroutines-and-c---async-without-the-pain--eykxkotyv","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"c++","timeRequired":"PT54M","video":{"@type":"VideoObject","name":"Coroutines and C++ - Async Without The Pain?","description":"C++ coroutines have been standardized since C++20 but remain underused due to their low-level nature. This talk walks through practical coroutine usage using...","thumbnailUrl":"https://i.ytimg.com/vi/4keXOkbr0UY/sddefault.jpg","uploadDate":"2026-07-23T16:18:19.493Z","duration":"PT54M","url":"https://api.daily.dev/r/EyKxKoTyV","embedUrl":"https://www.youtube.com/embed/4keXOkbr0UY"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"C++Online","item":"https://daily.dev/sources/cpponline"},{"@type":"ListItem","position":3,"name":"Coroutines and C++ - Async Without The Pain?"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/coroutines-and-c---async-without-the-pain--eykxkotyv#faq","mainEntity":[{"@type":"Question","name":"What is the difference between a task and an awaitable in C++ coroutines?","acceptedAnswer":{"@type":"Answer","text":"A task manages the lifetime of a coroutine, controlling the coroutine frame and suspension behavior, acting like a manager or controller. An awaitable is a small, temporary object used in a co_await expression whose only job is deciding whether, how, and when to suspend and resume a coroutine. Tasks are usually provided by libraries and hide complexity, while developers often write their own awaitables. Developers designing async APIs can find deeper coroutine breakdowns like this one on daily.dev."}},{"@type":"Question","name":"Why does using a const string reference in a C++ coroutine cause undefined behavior?","acceptedAnswer":{"@type":"Answer","text":"A const string reference parameter can bind to a temporary rvalue, and that temporary is destroyed once the coroutine is created but before it resumes after a suspension point, leaving a dangling reference. This causes undefined behavior when the coroutine later accesses the parameter. The safe fix is passing arguments by value into the coroutine so they are copied into the coroutine frame instead of referenced. Anyone debugging dangling reference bugs in async C++ code can track patterns like this on daily.dev."}},{"@type":"Question","name":"Why does TinyCoro only allow a scheduler to resume suspended coroutines instead of letting coroutines resume each other directly?","acceptedAnswer":{"@type":"Answer","text":"Allowing one coroutine to directly resume another can create an unbounded resume chain, similar to a linked list, that is never cleaned up and can cause very long call stacks or stack overflow in extreme cases. TinyCoro enforces that only the scheduler may resume suspended coroutines, following the same principle used in Swift, trading some performance overhead for full control over resumption and easier, more robust cancellation. Teams evaluating coroutine library design tradeoffs can compare approaches like this on daily.dev."}}]}
```

