Hello Task
The minimal Capy program: a task that prints a message.
What You Will Learn
-
Creating a
task<>coroutine -
Using
thread_poolas an execution context -
Launching tasks with
run_async
Source Code
#include <boost/capy.hpp>
#include <iostream>
namespace capy = boost::capy;
capy::task<> say_hello()
{
std::cout << "Hello from Capy!\n";
co_return;
}
int main()
{
capy::thread_pool pool;
capy::run_async(pool.get_executor())(say_hello());
pool.join();
return 0;
}
Walkthrough
The Task
capy::task<> say_hello()
{
std::cout << "Hello from Capy!\n";
co_return;
}
task<> is equivalent to task<void>—a coroutine that completes without returning a value. The co_return keyword marks this as a coroutine.
Tasks are lazy: calling say_hello() creates a task object but does not execute the body. The "Hello" message is not printed until the task is launched.
The Thread Pool
capy::thread_pool pool;
thread_pool provides an execution context with worker threads. By default, it creates one thread per CPU core.
Call pool.join() before the pool is destroyed to wait for all outstanding work to finish. The destructor does not wait for queued work: ~thread_pool calls stop(), which abandons any work that has not yet started, then joins the worker threads. Without the explicit pool.join(), main could destroy the pool and exit before say_hello ever runs, so "Hello from Capy!" might never print.
Launching
capy::run_async(pool.get_executor())(say_hello());
run_async bridges non-coroutine code (like main) to coroutine code. The two-call syntax:
-
run_async(pool.get_executor())— Creates a launcher with the executor -
(say_hello())— Accepts the task and starts execution
The task runs on one of the pool’s worker threads.
Exercises
-
Modify
say_helloto accept astd::string_viewparameter and print it -
Create multiple tasks and launch them all
-
Add a handler to
run_asyncthat prints when the task completes
Next Steps
-
Producer-Consumer — Multiple tasks communicating