Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/.pa11yci.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"http://localhost:8088/capy/index.html",
"http://localhost:8088/capy/why-capy.html",
"http://localhost:8088/capy/quick-start.html",
"http://localhost:8088/capy/4.coroutines/4a.tasks.html",
"http://localhost:8088/capy/4.coroutines/4b.tasks.html",
"http://localhost:8088/capy/reference/boost/capy.html"
]
}
82 changes: 41 additions & 41 deletions doc/lint/baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@
"modules/ROOT/pages/3.concurrency/3b.synchronization.adoc:#1:Google.Colons",
"modules/ROOT/pages/3.concurrency/3c.advanced.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4.intro.adoc:#1:Google.OxfordComma",
"modules/ROOT/pages/4.coroutines/4a.tasks.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4a.tasks.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4b.launching.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4b.launching.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4c.executors.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4c.executors.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4c.executors.adoc:#3:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4d.io-awaitable.adoc:#1:Capy.NoFluff",
"modules/ROOT/pages/4.coroutines/4d.io-awaitable.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4d.io-awaitable.adoc:#2:Capy.NoFluff",
"modules/ROOT/pages/4.coroutines/4d.io-awaitable.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4d.io-awaitable.adoc:#3:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4d.io-awaitable.adoc:#4:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4e.cancellation.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4e.cancellation.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4f.composition.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4f.composition.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4f.composition.adoc:#3:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4f.composition.adoc:#4:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4g.allocators.adoc:#1:Google.LyHyphens",
"modules/ROOT/pages/4.coroutines/4g.allocators.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4b.tasks.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4b.tasks.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4c.launching.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4c.launching.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4d.executors.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4d.executors.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4d.executors.adoc:#3:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4e.io-awaitable.adoc:#1:Capy.NoFluff",
"modules/ROOT/pages/4.coroutines/4e.io-awaitable.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4e.io-awaitable.adoc:#2:Capy.NoFluff",
"modules/ROOT/pages/4.coroutines/4e.io-awaitable.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4e.io-awaitable.adoc:#3:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4e.io-awaitable.adoc:#4:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4f.cancellation.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4f.cancellation.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4g.composition.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4g.composition.adoc:#2:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4g.composition.adoc:#3:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4g.composition.adoc:#4:Vale.Spelling",
"modules/ROOT/pages/4.coroutines/4h.allocators.adoc:#1:Google.LyHyphens",
"modules/ROOT/pages/4.coroutines/4h.allocators.adoc:#1:Vale.Spelling",
"modules/ROOT/pages/5.buffers/5a.buffers.adoc:#1:Google.LyHyphens",
"modules/ROOT/pages/5.buffers/5a.buffers.adoc:#1:Google.OxfordComma",
"modules/ROOT/pages/5.buffers/5a.buffers.adoc:#1:Vale.Spelling",
Expand Down Expand Up @@ -402,7 +402,7 @@
"C2:lint/.docstrings/concept/io_awaitable.hpp.adoc:#4:sentence over 25 words",
"C2:modules/ROOT/pages/2.cpp20-coroutines/2b.syntax.adoc:#1:sentence over 25 words",
"C2:modules/ROOT/pages/2.cpp20-coroutines/2b.syntax.adoc:#2:sentence over 25 words",
"C2:modules/ROOT/pages/4.coroutines/4d.io-awaitable.adoc:#1:sentence over 25 words",
"C2:modules/ROOT/pages/4.coroutines/4e.io-awaitable.adoc:#1:sentence over 25 words",
"advisory-C2:modules/ROOT/pages/9.design/9a.CapyLayering.adoc:#1:sentence over 25 words",
"advisory-C2:modules/ROOT/pages/9.design/9a.CapyLayering.adoc:#2:sentence over 25 words",
"advisory-C2:modules/ROOT/pages/9.design/9a.CapyLayering.adoc:#3:sentence over 25 words",
Expand Down Expand Up @@ -514,25 +514,25 @@
"skipped": false,
"contrastCount": 6,
"fingerprints": [
"/capy/4.coroutines/4a.tasks.html:color-contrast:#content > article > div:nth-child(1) > nav > ul > li:nth-child(2) > a",
"/capy/4.coroutines/4a.tasks.html:color-contrast:#content > article > div:nth-child(1) > nav > ul > li:nth-child(3) > a",
"/capy/4.coroutines/4a.tasks.html:link-name:#_awaiting_other_tasks > a",
"/capy/4.coroutines/4a.tasks.html:link-name:#_declaring_task_coroutines > a",
"/capy/4.coroutines/4a.tasks.html:link-name:#_exception_propagation > a",
"/capy/4.coroutines/4a.tasks.html:link-name:#_lazy_execution > a",
"/capy/4.coroutines/4a.tasks.html:link-name:#_move_semantics > a",
"/capy/4.coroutines/4a.tasks.html:link-name:#_overview > a",
"/capy/4.coroutines/4a.tasks.html:link-name:#_returning_values_with_co_return > a",
"/capy/4.coroutines/4a.tasks.html:link-name:#_running_a_task > a",
"/capy/4.coroutines/4a.tasks.html:link-name:#_symmetric_transfer > a",
"/capy/4.coroutines/4a.tasks.html:link-name:#io-result-and-io-task > a",
"/capy/4.coroutines/4a.tasks.html:list:#toc > aside > div > div > nav > ul",
"/capy/4.coroutines/4a.tasks.html:list:#toc > aside > div > div > nav > ul > ul",
"/capy/4.coroutines/4a.tasks.html:scrollable-region-focusable:#content > article > div:nth-child(10) > div > div:nth-child(2) > div > pre",
"/capy/4.coroutines/4a.tasks.html:scrollable-region-focusable:#content > article > div:nth-child(11) > div > div:nth-child(5) > div > pre",
"/capy/4.coroutines/4a.tasks.html:scrollable-region-focusable:#content > article > div:nth-child(12) > div > div:nth-child(2) > div > pre",
"/capy/4.coroutines/4a.tasks.html:scrollable-region-focusable:#content > article > div:nth-child(7) > div > div:nth-child(3) > div > pre",
"/capy/4.coroutines/4a.tasks.html:scrollable-region-focusable:#content > article > div:nth-child(8) > div > div:nth-child(2) > div > pre",
"/capy/4.coroutines/4b.tasks.html:color-contrast:#content > article > div:nth-child(1) > nav > ul > li:nth-child(2) > a",
"/capy/4.coroutines/4b.tasks.html:color-contrast:#content > article > div:nth-child(1) > nav > ul > li:nth-child(3) > a",
"/capy/4.coroutines/4b.tasks.html:link-name:#_awaiting_other_tasks > a",
"/capy/4.coroutines/4b.tasks.html:link-name:#_declaring_task_coroutines > a",
"/capy/4.coroutines/4b.tasks.html:link-name:#_exception_propagation > a",
"/capy/4.coroutines/4b.tasks.html:link-name:#_lazy_execution > a",
"/capy/4.coroutines/4b.tasks.html:link-name:#_move_semantics > a",
"/capy/4.coroutines/4b.tasks.html:link-name:#_overview > a",
"/capy/4.coroutines/4b.tasks.html:link-name:#_returning_values_with_co_return > a",
"/capy/4.coroutines/4b.tasks.html:link-name:#_running_a_task > a",
"/capy/4.coroutines/4b.tasks.html:link-name:#_symmetric_transfer > a",
"/capy/4.coroutines/4b.tasks.html:link-name:#io-result-and-io-task > a",
"/capy/4.coroutines/4b.tasks.html:list:#toc > aside > div > div > nav > ul",
"/capy/4.coroutines/4b.tasks.html:list:#toc > aside > div > div > nav > ul > ul",
"/capy/4.coroutines/4b.tasks.html:scrollable-region-focusable:#content > article > div:nth-child(10) > div > div:nth-child(2) > div > pre",
"/capy/4.coroutines/4b.tasks.html:scrollable-region-focusable:#content > article > div:nth-child(11) > div > div:nth-child(5) > div > pre",
"/capy/4.coroutines/4b.tasks.html:scrollable-region-focusable:#content > article > div:nth-child(12) > div > div:nth-child(2) > div > pre",
"/capy/4.coroutines/4b.tasks.html:scrollable-region-focusable:#content > article > div:nth-child(7) > div > div:nth-child(3) > div > pre",
"/capy/4.coroutines/4b.tasks.html:scrollable-region-focusable:#content > article > div:nth-child(8) > div > div:nth-child(2) > div > pre",
"/capy/index.html:color-contrast:#content > article > div:nth-child(1) > nav > ul > li:nth-child(2) > a",
"/capy/index.html:link-name:#_assumed_knowledge > a",
"/capy/index.html:link-name:#_code_convention > a",
Expand Down
17 changes: 9 additions & 8 deletions doc/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
** xref:3.concurrency/3c.advanced.adoc[Atomics, Condition Variables & Shared Locks]
** xref:3.concurrency/3d.patterns.adoc[Futures, async & Patterns]
* xref:4.coroutines/4.intro.adoc[Coroutines in Capy]
** xref:4.coroutines/4a.tasks.adoc[The task Type]
** xref:4.coroutines/4b.launching.adoc[Starting Coroutines]
** xref:4.coroutines/4c.executors.adoc[Executors and Execution Contexts]
** xref:4.coroutines/4d.io-awaitable.adoc[The IoAwaitable Protocol]
** xref:4.coroutines/4e.cancellation.adoc[Stop Tokens and Cancellation]
** xref:4.coroutines/4f.composition.adoc[Concurrent Composition]
** xref:4.coroutines/4g.allocators.adoc[Frame Allocators]
** xref:4.coroutines/4h.lambda-captures.adoc[Lambda Coroutine Captures]
** xref:4.coroutines/4a.flow-control.adoc[Flow control]
** xref:4.coroutines/4b.tasks.adoc[The task Type]
** xref:4.coroutines/4c.launching.adoc[Starting Coroutines]
** xref:4.coroutines/4d.executors.adoc[Executors and Execution Contexts]
** xref:4.coroutines/4e.io-awaitable.adoc[The IoAwaitable Protocol]
** xref:4.coroutines/4f.cancellation.adoc[Stop Tokens and Cancellation]
** xref:4.coroutines/4g.composition.adoc[Concurrent Composition]
** xref:4.coroutines/4h.allocators.adoc[Frame Allocators]
** xref:4.coroutines/4i.lambda-captures.adoc[Lambda Coroutine Captures]
* xref:5.buffers/5a.buffers.adoc[Buffer Sequences]
* xref:6.streams/6.intro.adoc[Stream Concepts]
** xref:6.streams/6a.overview.adoc[Overview]
Expand Down
18 changes: 10 additions & 8 deletions doc/modules/ROOT/pages/4.coroutines/4.intro.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,21 @@ Capy's coroutine model is built around a single principle: asynchronous code sho

== What This Section Covers

* xref:4.coroutines/4a.tasks.adoc[The task Type] -- Declaring, returning values from, and
* xref:4.coroutines/4a.flow-control.adoc[Flow control] -- Overview of how coroutines
address the needs of asynchronous I/O in Capy.
* xref:4.coroutines/4b.tasks.adoc[The task Type] -- Declaring, returning values from, and
awaiting cpp:task[task<T>] coroutines.
* xref:4.coroutines/4b.launching.adoc[Starting Coroutines] -- Starting coroutines with
* xref:4.coroutines/4c.launching.adoc[Starting Coroutines] -- Starting coroutines with
cpp:run_async[], and binding child tasks with cpp:run[].
* xref:4.coroutines/4c.executors.adoc[Executors and Execution Contexts] -- Executors,
* xref:4.coroutines/4d.executors.adoc[Executors and Execution Contexts] -- Executors,
execution contexts, thread pools, and strands.
* xref:4.coroutines/4d.io-awaitable.adoc[The IoAwaitable Protocol] -- How the executor and
* xref:4.coroutines/4e.io-awaitable.adoc[The IoAwaitable Protocol] -- How the executor and
stop token propagate through a chain of awaited coroutines.
* xref:4.coroutines/4e.cancellation.adoc[Stop Tokens and Cancellation] -- Cooperative
* xref:4.coroutines/4f.cancellation.adoc[Stop Tokens and Cancellation] -- Cooperative
cancellation with `std::stop_token`, and how Capy tasks observe it.
* xref:4.coroutines/4f.composition.adoc[Concurrent Composition] -- Running tasks
* xref:4.coroutines/4g.composition.adoc[Concurrent Composition] -- Running tasks
concurrently with cpp:when_all[] and cpp:when_any[].
* xref:4.coroutines/4g.allocators.adoc[Frame Allocators] -- How coroutine frames are
* xref:4.coroutines/4h.allocators.adoc[Frame Allocators] -- How coroutine frames are
allocated, and how to customize the allocator.
* xref:4.coroutines/4h.lambda-captures.adoc[Lambda Coroutine Captures] -- A critical
* xref:4.coroutines/4i.lambda-captures.adoc[Lambda Coroutine Captures] -- A critical
pitfall: lambda captures versus coroutine frame lifetime.
36 changes: 36 additions & 0 deletions doc/modules/ROOT/pages/4.coroutines/4a.flow-control.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
= Flow control
:page-mode: explanation

Capy's design is driven by the needs of network I/O processing,

Check warning on line 4 in doc/modules/ROOT/pages/4.coroutines/4a.flow-control.adoc

View workflow job for this annotation

GitHub Actions / Antora Docs

[sentence_length C2] sentence over 25 words (36)
where a piece of the program, in order to continue, needs to wait for an I/O operation to finish,

Check warning on line 5 in doc/modules/ROOT/pages/4.coroutines/4a.flow-control.adoc

View workflow job for this annotation

GitHub Actions / Antora Docs

[vale_adoc Capy.NoFluff] Filler/fluff — delete or rewrite (style guide C5/C9): 'in order to'.
but when this happens is unpredictable. The challenge here is:

1. To utilize this waiting time as efficiently as possible, processing other tasks.

Check warning on line 8 in doc/modules/ROOT/pages/4.coroutines/4a.flow-control.adoc

View workflow job for this annotation

GitHub Actions / Antora Docs

[vale_adoc Capy.NoFluff] Filler/fluff — delete or rewrite (style guide C5/C9): 'utilize'.
2. To avoid any concurrency or lifetime management bugs.
3. To have the user code be simple and intuitive.

To achieve this, Capy utilizes the _proactor_ pattern hidden behind the coroutine `co_await` mechanism.
In this pattern, when the user needs an I/O operation to be performed to see its results, they:

1. Schedule in the I/O runtime an operation to be performed.
2. Register a piece of code to be invoked when the I/O operation finishes.
3. Return control, so that other tasks can make progress.

This is exactly what happens when you write:

[source,cpp]

Check warning on line 21 in doc/modules/ROOT/pages/4.coroutines/4a.flow-control.adoc

View workflow job for this annotation

GitHub Actions / Antora Docs

[doc_lint B2] raw code, not include::example$/role=pseudocode/role=external
----
process(co_await stream.read_some(buffer));
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ <1>
/*~~~*/ <2>
----
<1> The `co_await`-expression schedules an I/O operation to be called in the

Check warning on line 27 in doc/modules/ROOT/pages/4.coroutines/4a.flow-control.adoc

View workflow job for this annotation

GitHub Actions / Antora Docs

[sentence_length C2] sentence over 25 words (26)
xref:4.coroutines/4d.executors.adoc[_execution context_],
and registers
the resumption of the coroutine after the I/O operation finishes. Once the scheduling and registering is done,
the coroutine is suspended, and the program thread switches to performing other tasks.
<2> When the xref:4.coroutines/4d.executors.adoc[_execution context_] finishes performing the scheduled I/O operation, it resumes the coroutine,
and the next instruction following the `co_await`-expression.

While all this registering happens hidden in the coroutine mechanism, the coroutine body
reads as sequential business logic.
Loading
Loading