### Build and Install async_simple with CMake Source: https://github.com/alibaba/async_simple/blob/main/README.md Builds and installs the async_simple library using CMake. This method involves cloning the repository, configuring the build with CMake, and then building and installing the library. ```bash git clone -b main --single-branch --depth 1 https://github.com/alibaba/async_simple.git cd async_simple mkdir build cd build cmake .. -DASYNC_SIMPLE_ENABLE_TESTS=OFF -DASYNC_SIMPLE_BUILD_DEMO_EXAMPLE=OFF -DASYNC_SIMPLE_ENABLE_ASAN=OFF cmake --build . cmake --install . # --prefix ./user_defined_install_path ``` -------------------------------- ### Install async_simple with Vcpkg Source: https://github.com/alibaba/async_simple/blob/main/README.md Installs the async_simple library using the Vcpkg package manager. Vcpkg is a cross-platform package manager that simplifies the process of acquiring and building libraries. ```bash ./vcpkg install async-simple ``` -------------------------------- ### Start Lazy with directlyStart(callback, executor) Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Lazy.md Shows how to start a Lazy coroutine and bind it to a specific executor using `directlyStart`. This method allows for explicit control over where the coroutine's work is executed. Necessary headers include `` and executor-specific headers like ``. ```cpp #include #include #include #include #include #include using namespace async_simple::coro; using namespace async_simple::executors; using namespace std::chrono_literals; Lazy<> task() { auto e = co_await currentExecutor{}; // binding executor successfully. assert(e!=nullptr); // lazy schedule, work doesn't run in executor. assert(e->currentThreadInExecutor()==false); co_await coro::Sleep(1s); // Sleep function need executor schedule, now work runs in executor. assert(e->currentThreadInExecutor()==true); } void func() { auto executor=std::make_shared(1); task().directlyStart([executor](Try Result){},executor.get()); } ``` -------------------------------- ### Start Lazy with co_await Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Lazy.md Illustrates how to start a Lazy coroutine using `co_await` within another coroutine function. This implicitly starts the execution of the awaited Lazy. Ensure the correct header is included. ```cpp #include #include Lazy task1(int x) { co_return x; } Lazy<> task2() { auto t = task1(10); auto x = co_await t; // start coroutine 't'. assert(x == 10); } ``` -------------------------------- ### Manage Subdirectories (CMake) Source: https://github.com/alibaba/async_simple/blob/main/CMakeLists.txt Manages the inclusion of subdirectories for the async_simple library, demo examples, and benchmarks. The demo example is included if ASYNC_SIMPLE_BUILD_DEMO_EXAMPLE is ON. Benchmarks are included only if BENCHMARK_INCLUDE_DIR and BENCHMARK_LIBRARIES are defined. ```cmake add_subdirectory(async_simple) option(ASYNC_SIMPLE_BUILD_DEMO_EXAMPLE "Build the demo example" ON) if (ASYNC_SIMPLE_BUILD_DEMO_EXAMPLE) add_subdirectory(demo_example) endif () if (BENCHMARK_INCLUDE_DIR AND BENCHMARK_LIBRARIES) message(STATUS "Building benchmarks") add_subdirectory(benchmarks) else() message(STATUS "Skipping benchmarks") endif() ``` -------------------------------- ### Install Development Dependencies with Pacman (Arch) Source: https://github.com/alibaba/async_simple/blob/main/README.md Installs development dependencies for async_simple on Arch Linux using the Pacman package manager. It includes optional installation of libaio and required packages like cmake and gtest. ```bash # Optional sudo pacman -S libaio # Use cmake to build project sudo pacman -S cmake gtest # Use bazel to build project sudo pacman -S bazel ``` -------------------------------- ### Install Input Directory for ReadFiles Source: https://github.com/alibaba/async_simple/blob/main/demo_example/CMakeLists.txt This defines a custom build command for the ReadFiles target. After building, it copies the 'Input' directory from the source to the binary directory, ensuring necessary input files are available at runtime. ```cmake add_custom_command( TARGET ReadFiles POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/Input ${CMAKE_CURRENT_BINARY_DIR}/Input) ``` -------------------------------- ### Example: Using async with Launch Policies and Attributes Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Uthread.md Demonstrates the usage of `uthread::async` with both `Launch::Schedule` and `Launch::Current` policies, along with custom attributes including stack size. It showcases asynchronous execution and awaiting results. ```cpp TEST_F(UthreadTest, testAsync_v2) { std::atomic running = 1; async( Launch::Schedule, Attribute{.ex = &_executor, .stack_size = 4096}, [](int a, int b) { return a + b; }, 1, 2) .thenValue([&running](int ans) { EXPECT_EQ(ans, 3); running--; }); EXPECT_EQ(await(async( Launch::Current, Attribute{&_executor}, [](int a, int b) { return a * b; }, 2, 512)), 1024); while (running) { } } ``` -------------------------------- ### Chaining Signals (C++) Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/SignalAndCancellation.md Demonstrates how to chain signals together. When a signal is triggered, it forwards the event to other chained signals. The example shows adding a chained signal and verifying the state after emission. ```cpp std::shared_ptr signal = Signal::create(); auto slot = std::make_unique(signal.get()); std::shared_ptr chainedSignal = Signal::create(); slot->addChainedSignal(chainedSignal); signal->emits(SignalType::terminate); assert(chainedSignal->state()==SignalType::terminate); chainedSignal->emits(static_cast(0b10)); assert(signal->state()!=static_cast(0b10)); ``` -------------------------------- ### Install Development Dependencies with apt (Ubuntu/Debian) Source: https://github.com/alibaba/async_simple/blob/main/README.md Installs essential development dependencies for building async_simple on Ubuntu and Debian-based systems using the apt package manager. This includes libaio-dev, cmake, and optionally gtest/gmock. ```bash # Install libaio sudo apt install libaio-dev -y # Install cmake sudo apt install cmake -y # Install bazel See: https://bazel.build/install/ubuntu # Use apt to install gtest and gmock sudo apt install -y libgtest-dev libgmock-dev ``` -------------------------------- ### Generate and Install CMake Configuration Files Source: https://github.com/alibaba/async_simple/blob/main/async_simple/CMakeLists.txt This CMake snippet generates and installs the 'async_simple-targets.cmake' and 'async_simple-config.cmake' files. These files are crucial for other projects to find and use the async_simple library, including dependency discovery and target export. ```cmake install(EXPORT async_simple_targets FILE async_simple-targets.cmake NAMESPACE async_simple:: DESTINATION share/async_simple) # Generate the config file in the current binary dir (this ensures it's not placed directly in source) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/async_simple-config.cmake" "include(CMakeFindDependencyMacro)\n" "find_package(Threads REQUIRED)\n" "include(\"${CMAKE_CURRENT_LIST_DIR}/async_simple-targets.cmake\")\n" ) # Install the generated config file install(FILES "${CMAKE_CURRENT_BINARY_DIR}/async_simple-config.cmake" DESTINATION share/async_simple) ``` -------------------------------- ### Start Lazy with .start(callback) Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Lazy.md Demonstrates initiating a Lazy coroutine's execution asynchronously using the `.start()` method with a callback. The callback receives a `Try` object indicating success or failure. Include `` and `` for basic I/O. ```cpp #include #include #include Lazy task1(int x) { co_return x; } Lazy<> task2() { auto t = task1(10); auto x = co_await t; assert(x == 10); } void func() { task2().start([](Try Result){ if (Result.hasError()) std::cout << "Error Happened in task2.\n"; else std::cout << "task2 completed successfully.\n"; }); } ``` ```cpp #include task().start([](auto&&){}); ``` -------------------------------- ### Install Development Dependencies with Homebrew (macOS) Source: https://github.com/alibaba/async_simple/blob/main/README.md Installs development dependencies for async_simple on macOS using the Homebrew package manager. This includes cmake and googletest, which are necessary for building the project. ```bash # Use cmake to build project brew install cmake brew install googletest ``` -------------------------------- ### Build gtest and gmock from Source with apt Source: https://github.com/alibaba/async_simple/blob/main/README.md Provides instructions to build Google Test (gtest) and Google Mock (gmock) from source on Ubuntu/Debian systems, which can be used as an alternative to installing pre-built packages. This is useful if specific versions are required or if package manager versions are outdated. ```bash # Install gtest sudo apt install libgtest-dev -y sudo apt install cmake -y cd /usr/src/googletest/gtest sudo mkdir build && cd build sudo cmake .. && sudo make install cd .. && sudo rm -rf build cd /usr/src/googletest/gmock sudo mkdir build && cd build sudo cmake .. && sudo make install cd .. && sudo rm -rf build # Install bazel See: https://bazel.build/install/ubuntu ``` -------------------------------- ### Install Development Dependencies with yum (CentOS/Fedora) Source: https://github.com/alibaba/async_simple/blob/main/README.md Installs necessary development dependencies for building async_simple on CentOS and Fedora systems using the yum package manager. This includes libaio-devel and optionally gtest-devel/gmock-devel. ```bash # Install libaio sudo yum install libaio-devel -y # Use yum to install gtest, gmock sudo yum install gtest-devel gmock-devel ``` -------------------------------- ### C++ Latch: Countdown and Wait Example Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Latch.md Demonstrates the basic usage of async_simple::coro::Latch for coordinating multiple coroutines. It shows how to initialize a latch, decrement its counter using count_down(), and wait for the counter to reach zero using wait(). ```cpp #include "async_simple/coro/Latch.h" using namespace async_simple::coro; Latch work_done(3); Lazy<> work1() { //... co_await work_done.count_down(); } Lazy<> work2() { //... co_await work_done.count_down(); } Lazy<> work3() { //... co_await work_done.count_down(); } Lazy<> wait_lazy() { // ... co_await work_done.wait(); } ``` -------------------------------- ### C++ Compile and Execute Command Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/GetStarted.md These commands demonstrate how to compile the C++ source code using clang++ and then execute the compiled program. The compilation requires C++20 standard support. The execution will run the character counting program. ```bash clang++ -std=c++20 CountChar.cpp -o CountChar ./CountChar ``` -------------------------------- ### Adjust Implementation Files for Unhandled Macros Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/modules-converter.md This C++ code example shows how to resolve warnings about unhandled macro uses in implementation files by adding the necessary include directives. It specifically addresses the use of `AS_UNLIKELY` and `assert`, preferring `` over ``. ```cpp // There unhandled macro uses found in the body: // 'AS_UNLIKELY' defined in /home/chuanqi.xcq/async_simple/async_simple/CommonMacros.h:22:9 // 'assert' defined in /usr/include/assert.h:50:10 // Add necessary include, for example: #include ``` -------------------------------- ### Start Lazy with syncAwait Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Lazy.md Demonstrates how to execute a Lazy coroutine synchronously and wait for its result using `syncAwait`. This method blocks the current thread until the Lazy completes. Include `` and ``. ```cpp #include #include #include Lazy task1(int x) { co_return x; } Lazy<> task2() { auto t = task1(10); auto x = co_await t; assert(x == 10); } void func() { auto value = syncAwait(task2()); // Wait for task2() synchronously. } ``` -------------------------------- ### Import async_simple with CMake find_package Source: https://github.com/alibaba/async_simple/blob/main/README.md Demonstrates how to import the installed async_simple library into a CMake project using `find_package`. It also shows how to link against the library, with options for dynamic, header-only, or static linking. ```cmake find_package(async_simple REQUIRED) target_link_libraries( PRIVATE async_simple::async_simple) # dynamic_link # async_simple::async_simple_header_only # async_simple::async_simple_static ``` -------------------------------- ### C++ Latch: Arrive and Wait Synchronization Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Latch.md Illustrates an alternative pattern for using async_simple::coro::Latch where coroutines arrive and wait for others to complete before proceeding. This is useful for scenarios where multiple tasks need to start simultaneously after an initial synchronization point. ```cpp #include "async_simple/coro/Latch.h" using namespace async_simple::coro; Latch work_begin(3); Lazy<> work() { // Synchronize co_await arrive_and_wait(); // ... } Lazy<> ready() { for (int i = 0; i < 3; ++i) { work().via(&ex).detach(); } // ... } ``` -------------------------------- ### Extending Signal with Custom State (C++) Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/SignalAndCancellation.md Example of extending the base Signal class to include custom state (myState). It demonstrates creating a custom signal, attaching a slot with a lambda handler that accesses the custom state, and emitting a signal. ```cpp class MySignal : public Signal { using Signal::Signal; public: std::atomic myState; }; auto mySignal = Signal::create(); auto slot = std::make_unique(mySignal->get()); slot->emplace([](SignalType type, Signal* signal) { auto mySignal = dynamic_cast(signal); std::cout << "myState:" << mySignal->myState << std::endl; }); mySignal->myState=1; mySignal->emits(SignalType::terminate); ``` -------------------------------- ### Wait for and Get Value from Future in C++ Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Future.md Shows how to wait for a Promise to complete and retrieve its value using Future::wait() and Future::value(). It also demonstrates the convenience method Future::get() which combines waiting and retrieving the value. ```cpp async_simple::Future f; f.wait(); int v = f.value(); // Alternative using get() int v = f.get(); ``` -------------------------------- ### Stackful Coroutines with Uthread (C++) Source: https://context7.com/alibaba/async_simple/llms.txt Introduces async_simple::uthread::Uthread for implementing stackful coroutines, enabling context switching for asynchronous operations. The example shows launching tasks, setting completion callbacks, and detached execution using an executor. ```cpp #include "async_simple/uthread/Uthread.h" #include "async_simple/uthread/Async.h" #include "async_simple/executors/SimpleExecutor.h" using namespace async_simple; using namespace async_simple::uthread; void computeTask() { // Stackful coroutine body int result = 0; for (int i = 0; i < 100; ++i) { result += i; } // result == 4950 } int main() { executors::SimpleExecutor executor(4); // Launch::Prompt - returns Uthread handle Uthread uth = async(computeTask, &executor); // Set completion callback uth.join([]() { std::cout << "Task completed\n"; }); // Launch::Schedule - detached execution async(computeTask, &executor); // Launch::Schedule with callback async( computeTask, []() { std::cout << "Done\n"; }, &executor ); return 0; } ``` -------------------------------- ### Using Executors with Coroutines in async_simple (C++) Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Executor.md Demonstrates how to assign an Executor to coroutine instances (Lazy and Uthread) in async_simple. It shows immediate scheduling via `via` and delayed scheduling using `start` or `directlyStart`, as well as scheduling with `uthread::async`. ```cpp Executor e; // lazy // schedule to executor immediately f().via(&e).start([](auto&&){}); // binding executor but dont schedule immediately f().start([](auto&&){},&e); // uthread uthread::async(, &e); ``` -------------------------------- ### C++ Future Continuations with thenValue and thenTry Source: https://context7.com/alibaba/async_simple/llms.txt Shows how to chain asynchronous operations using continuations with async_simple's Future. The example utilizes `thenValue` to process successful results and implicitly handles potential exceptions. ```cpp #include "async_simple/Future.h" #include "async_simple/Promise.h" #include "async_simple/executors/SimpleExecutor.h" using namespace async_simple; int main() { executors::SimpleExecutor executor(4); Promise promise; Future future = promise.getFuture(); // Chain operations with thenValue auto result = std::move(future) .via(&executor) .thenValue([](int x) { return x * 2; }) .thenValue([](int x) { return x + 10; }); promise.setValue(20); // result.get() == 50 int final_value = result.get(); return 0; } ``` -------------------------------- ### Shell Command to Generate Random File Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/GetStarted.md This shell command generates a text file named 'file.txt' containing 10,000 random bytes. It uses 'base64' to encode random data from '/dev/urandom' and pipes the output to 'head' to limit it to 10,000 bytes, then redirects it to 'file.txt'. This file can be used as input for the character counting program. ```bash base64 /dev/urandom | head -c 10000 > file.txt ``` -------------------------------- ### C++ Future and Promise for Asynchronous Operations Source: https://context7.com/alibaba/async_simple/llms.txt Demonstrates the traditional producer-consumer pattern for asynchronous value delivery using async_simple's Future and Promise. This example shows a producer thread setting a value that a consumer thread retrieves via a Future. ```cpp #include "async_simple/Future.h" #include "async_simple/Promise.h" #include using namespace async_simple; void producer(Promise promise) { std::this_thread::sleep_for(std::chrono::seconds(1)); promise.setValue(42); } int main() { Promise promise; Future future = promise.getFuture(); std::thread t(producer, std::move(promise)); // Blocking wait for value int result = future.get(); // result == 42 t.join(); return 0; } ``` -------------------------------- ### Building and Running 'wrk' Benchmark Tool Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/ImproveNetLibWithAsyncSimple.md This section provides instructions for downloading and compiling the 'wrk' HTTP benchmarking tool. 'wrk' is used to perform load testing on the HTTP servers to measure performance. It requires Git for cloning the repository and a C/C++ compiler toolchain for building. ```bash git clone https://github.com/wg/wrk.git cd wrk make ``` -------------------------------- ### Set Target Properties and Install Headers Source: https://github.com/alibaba/async_simple/blob/main/async_simple/CMakeLists.txt This CMake code sets version properties for the 'async_simple' target and installs various header files into their respective include directories. It also conditionally installs Uthread-specific headers if UTHREAD is enabled. ```cmake set_target_properties(async_simple PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) install(FILES ${headers} DESTINATION include/async_simple) install(FILES ${coro_header} DESTINATION include/async_simple/coro) install(FILES ${executors_header} DESTINATION include/async_simple/executors) install(FILES ${experimental_header} DESTINATION include/async_simple/experimental) install(FILES ${util_header} DESTINATION include/async_simple/util) if(UTHREAD) install(FILES ${uthread_header} DESTINATION include/async_simple/uthread) install(FILES ${uthread_internal_header} DESTINATION include/async_simple/uthread/internal) endif() ``` -------------------------------- ### Running 'wrk' Benchmark Test Command Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/ImproveNetLibWithAsyncSimple.md This command line demonstrates how to execute the 'wrk' benchmark tool. It specifies 10 threads, 1000 concurrent connections, and a duration of 30 seconds to test the HTTP server at the given URL. This is used to measure request throughput and latency. ```bash ./wrk -t10 -c1000 -d30s http://127.0.0.1:9980/ ``` -------------------------------- ### Get Future from Promise in C++ Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Future.md Illustrates how to obtain a Future object from a Promise using the getFuture() method. The Future object can then be used to observe the result of the asynchronous operation. ```cpp async_simple::Promise p; async_simple::Future f = p.getFuture(); ``` -------------------------------- ### Run clang-modules-converter Tool Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/modules-converter.md This command executes the clang-modules-converter tool with the specified configuration file to perform the module refactoring on the project. ```shell clang-modules-converter --config=modules.yml ``` -------------------------------- ### collectAll with External Resources and Mixed Tasks Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/SignalAndCancellation.md Demonstrates using `collectAll` with external resources like `http_client` and mixing tasks with different completion times. `collectAll` ensures that all coroutines, including those with specified durations like `sleep(1s)`, are awaited. ```cpp http_client client; // Unlike `collectAny`, we do not need to manually extend the lifecycle of `client` because `collectAll` guarantees that the `http_client::connect` coroutine will return. auto res = co_await collectAll(client.connect("localhost:8080"), sleep(1s)); // If no cancellation signal is sent, `collectAll` will continue to execute until the sleep time of one second elapses and the client completes the connection. auto res = co_await collectAll(client.connect("localhost:8080"), sleep(1s)); ``` -------------------------------- ### SharedMutex for Read-Heavy Scenarios Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Lock.md Provides an example of using SharedMutex for coroutines where read operations significantly outnumber write operations. It demonstrates co-awaiting shared locks for reading and exclusive locks for writing. ```cpp #include using namespace async_simple::coro; SharedMutex lock; Lazy read() { co_await lock.coLockShared(); // critical read section co_await lock.unlockShared(); co_return; } Lazy write() { co_await lock.coLock(); // critical write section co_await lock.unlock(); co_return; } ``` -------------------------------- ### Handle Exceptions with Future in C++ Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Future.md Explains how to handle potential exceptions thrown during an asynchronous operation. It uses Future::wait() and Future::result() to get a Try object, which can then be checked for errors before accessing the value. ```cpp async_simple::Future f; f.wait(); Try t = f.result(); if (t.hasError()) { // HandleException } else { // get value } ``` -------------------------------- ### C++: Get Exception or Value from Try Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Try.md Shows how to retrieve the exception pointer using getException() or the contained value using value() from a Try object. Note that calling value() on an exception-holding Try will throw. ```cpp void foo() { Try t(std::make_exception_ptr(std::runtime_error(""))); std::exception_ptr e = t.getException(); // ... Try t2(5); int res = t2.value(); } ``` -------------------------------- ### Set Value or Exception for Promise in C++ Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Future.md Demonstrates how to fulfill a Promise by setting its value or an exception. This includes setting a direct value, a Try object, or a std::exception_ptr. ```cpp async_simple::Promise p; std::exception_ptr ex_ptr; p.setValue(43); p.setValue(t); // t is Try p.setException(ex_ptr); // ex_ptr is std::exception_ptr ``` -------------------------------- ### Define Async Simple Interface Library (CMake) Source: https://github.com/alibaba/async_simple/blob/main/CMakeLists.txt Defines an INTERFACE library for async_simple, enabling the use of C++20 features and specifying include directories for both build and installation targets. It also links against the Threads library. ```cmake add_library(async_simple_header_only INTERFACE) target_compile_features(async_simple_header_only INTERFACE cxx_std_20) target_include_directories(async_simple_header_only INTERFACE $ $ ) find_package(Threads REQUIRED) target_link_libraries(async_simple_header_only INTERFACE Threads::Threads) ``` -------------------------------- ### Include Directories for Asio Source: https://github.com/alibaba/async_simple/blob/main/demo_example/CMakeLists.txt This command adds the 'asio' directory to the include path for the project. This allows source files to include headers from the Asio library. ```cmake include_directories(asio) ``` -------------------------------- ### C++ Hello World with Async_simple Uthread Source: https://github.com/alibaba/async_simple/blob/main/bazel/support/README.md A basic C++ program demonstrating the use of `async_simple::uthread::Uthread` to print a message asynchronously. This snippet requires the async_simple library to be available as a dependency. ```cpp #include "async_simple/uthread/Uthread.h" #include int main() { async_simple::uthread::Uthread uth({}, []() { std::cout << "Hello async_simple!" << std::endl; }); } ``` -------------------------------- ### Bazel BUILD.bazel for C++ Binary Source: https://github.com/alibaba/async_simple/blob/main/bazel/support/README.md Defines a C++ binary target named 'hello' in Bazel, specifying its source file (`src/hello.cc`) and its dependency on the async_simple library (`@com_github_async_simple//:async_simple`). It also sets the C++ standard to C++20. ```python cc_binary( name = "hello", srcs = ["src/hello.cc"], deps = ["@com_github_async_simple//:async_simple"], copts = ["-std=c++20"], ) ``` -------------------------------- ### C++ File Processing with Lazy Coroutines Source: https://context7.com/alibaba/async_simple/llms.txt Illustrates asynchronous file reading and character counting using async_simple's Lazy coroutines. This example shows how to break down file processing into smaller, awaitable asynchronous tasks. ```cpp #include #include #include #include #include "async_simple/coro/Lazy.h" #include "async_simple/coro/SyncAwait.h" using namespace async_simple::coro; using Texts = std::vector; Lazy ReadFile(const std::string& filename) { Texts Result; std::ifstream infile(filename); std::string line; while (std::getline(infile, line)) Result.push_back(line); co_return Result; } Lazy CountLineChar(const std::string& line, char c) { auto ret = std::count(line.begin(), line.end(), c); co_return static_cast(ret); } Lazy CountTextChar(const Texts& Content, char c) { int Result = 0; for (const auto& line : Content) Result += co_await CountLineChar(line, c); co_return Result; } Lazy CountFileCharNum(const std::string& filename, char c) { Texts Contents = co_await ReadFile(filename); co_return co_await CountTextChar(Contents, c); } int main() { int Num = syncAwait(CountFileCharNum("file.txt", 'x')); std::cout << "The number of 'x' in file.txt is " << Num << "\n"; return 0; } ``` -------------------------------- ### Uthread Launch Policies Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Uthread.md Defines the launch policies for the `uthread::async` function. `Launch::Schedule` creates a Uthread on a specified executor and returns immediately, while `Launch::Current` executes the Uthread in the current thread and blocks until completion. ```cpp enum class Launch { Schedule, Current, }; ``` -------------------------------- ### Build Block Echo Client Executable Source: https://github.com/alibaba/async_simple/blob/main/demo_example/CMakeLists.txt This defines the block_echo_client executable, compiles block_echo_client.cpp, and links it against the system's thread library. This suggests a blocking, rather than asynchronous, echo client implementation. ```cmake add_executable(block_echo_client block_echo_client.cpp) target_link_libraries(block_echo_client ${CMAKE_THREAD_LIBS_INIT}) ``` -------------------------------- ### Chaining Futures with Executors in C++ Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Future.md Demonstrates how to use Future::via() to specify an Executor for running callbacks. This allows control over where and when the asynchronous operations defined in the chain are executed. ```cpp Promise p; auto future = p.getFuture().via(&executor); // the type of executor is derived type of async_simple::Executor auto f = std::move(future) .thenTry([&output0, record](Try&& t) { record(0); output0 = t.value(); return t.value() + 100; }) .thenTry([&output1, &executor, record](Try&& t) { record(1); output1 = t.value(); Promise p; auto f = p.getFuture().via(&executor); p.setValue(t.value() + 10); return f; }) .thenValue([&output2, record](int x) { record(2); output2 = x; return std::to_string(x); }) .thenValue([](string&& s) { return 1111.0; }); p.setValue(1000); f.wait(); ``` -------------------------------- ### Resume Lazy with Specific Executor in C++ Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Future.md This example demonstrates how to explicitly control the executor used for resuming a Lazy object when awaiting a Future. By using 'co_await CurrentExecutor{}', the Future is configured to resume the Lazy on the Lazy's current executor. Requires 'async_simple/coro/FutureAwaiter.h'. ```cpp #include "async_simple/coro/FutureAwaiter.h" #include #include #include #include #include // Assuming sum is a function that takes two ints and a callback, setting the value in the promise void sum(int a, int b, std::function cb) { // Simulate some work and then call the callback std::thread([a, b, cb]() { std::this_thread::sleep_for(std::chrono::milliseconds(100)); cb(a + b); }).detach(); } // Example usage within an async function or coroutine context // async_simple::coro::Lazy example() { async_simple::coro::Promise pr; auto fut = pr.getFuture().via(co_await async_simple::coro::CurrentExecutor{}); sum(1, 1, [pr = std::move(pr)](int val) mutable { pr.setValue(val); }); std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Simulate delay for demonstration auto val = co_await std::move(fut); // 'val' now holds the result from the future // } ``` -------------------------------- ### Configure Async Simple Utility Test Executable Source: https://github.com/alibaba/async_simple/blob/main/async_simple/util/test/CMakeLists.txt Defines the test executable 'async_simple_util_test' by compiling all '.cpp' files in the util_test_src directory and linking it with necessary libraries like 'async_simple', 'deplibs', and 'testdeplibs'. ```cmake file(GLOB util_test_src "*.cpp") add_executable(async_simple_util_test ${util_test_src} ${PROJECT_SOURCE_DIR}/async_simple/test/dotest.cpp) target_link_libraries(async_simple_util_test async_simple ${deplibs} ${testdeplibs}) ``` -------------------------------- ### Collect All Tasks (Variadic Arguments) Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Lazy.md Waits for multiple Lazy tasks provided as variadic arguments to complete and returns their results as a std::tuple, Try, ...>. Requires co_await for coroutine execution. Example demonstrates retrieving results and checking for errors. ```cpp Lazy computeInt(); Lazy computeDouble(); Lazy computeString(); Lazy<> foo() { std::tuple, Try, Try> Res = co_await collectAll(computeInt(), computeDouble(), computeString()); Try IntRes = std::get<0>(Res); if (IntRes.hasError()) { std::cout << "Error happened in computeInt()\n"; } else { std::cout << "Result for computeInt: " << IntRes.value() << "\n"; } // ... } ``` -------------------------------- ### Build Block Echo Server Executable Source: https://github.com/alibaba/async_simple/blob/main/demo_example/CMakeLists.txt This defines the block_echo_server executable, compiles block_echo_server.cpp, and links it against the system's thread library. This suggests a blocking, rather than asynchronous, echo server implementation. ```cmake add_executable(block_echo_server block_echo_server.cpp) target_link_libraries(block_echo_server ${CMAKE_THREAD_LIBS_INIT}) ``` -------------------------------- ### Build Modules Using Ninja and CMake Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/modules-converter.md This sequence of commands configures the build system using CMake with the Ninja generator and the `ASYNC_SIMPLE_BUILD_MODULES` flag enabled, then builds the project, including the newly converted modules. ```shell mkdir build_modules cd build_modules CXX=clang++ CC=clang cmake ../ -DCMAKE_BUILD_TYPE=Release -DASYNC_SIMPLE_DISABLE_AIO=ON -GNinja -DASYNC_SIMPLE_BUILD_MODULES=ON ninja ``` -------------------------------- ### Checkout Baseline Version Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/modules-converter.md This command checks out a specific commit of the async_simple project, serving as the baseline for the module conversion process. ```shell git checkout b0bb413ec51bce99ef6a90a325df7445cc6336e2 ``` -------------------------------- ### Using dispatch to schedule Lazy operations in C++ Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/dispatch.md This C++ snippet demonstrates how to use the dispatch function to schedule a Lazy operation on a different Executor. It includes necessary headers, namespace usage, and assertions to verify the current Executor before and after dispatching. The example assumes the existence of `executor1` and `executor2`. ```c++ #include "async_simple/coro/Dispatch.h" using namespace async_simple::coro; Lazy<> work() { //... Executor* my_ex = co_await CurrentExecutor{}; assert(my_ex == &executor1); co_await dispatch(&executor2); my_ex = co_await CurrentExecutor{}; assert(my_ex == &executor2); } syncAwait(work2().via(&executor1)); ``` -------------------------------- ### C++ CollectAnyResult Structure and Usage Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Lazy.md Defines the CollectAnyResult structure for C++ asynchronous operations. It includes methods to access the index of the first completed task, its value, or any exception thrown. The example demonstrates how to use `collectAny` to run multiple tasks concurrently and process the result of the first one that finishes. ```cpp template struct CollectAnyResult { size_t _idx; Try _value; size_t index() const; bool hasError() const; // Require hasError() == true. Otherwise it is UB to call // this method. std::exception_ptr getException() const; // Require hasError() == false. Otherwise it is UB to call // value() method. const T& value() const&; T& value() &; T&& value() &&; const T&& value() const&&; }; Lazy foo() { std::vector> input; input.push_back(ComputingTask(1)); input.push_back(ComputingTask(2)); auto any_result = co_await collectAny(std::move(input)); std::cout << "The index of the first task completed is " << any_result.index() << "\n"; if (any_result.hasError()) std::cout << "It failed.\n"; else std::cout << "Its result: " << any_result.value() << "\n"; } Lazy foo_var() { auto res = co_await collectAny(ComputingTask(1),ComputingTask(2),ComputingTask(3.14f)); std::cout<< "Index: " << res.index(); std::visit([](auto &&value){ std::cout<<"Value: "<< value < p; auto future = p.getFuture(); auto f = std::move(future) .thenTry([&output0, record](Try&& t) { record(0); output0 = t.value(); return t.value() + 100; }) .thenTry([&output1, &executor, record](Try&& t) { record(1); output1 = t.value(); Promise p; auto f = p.getFuture().via(&executor); p.setValue(t.value() + 10); return f; }) .thenValue([&output2, record](int x) { record(2); output2 = x; return std::to_string(x); }) .thenValue([](string&& s) { return 1111.0; }); p.setValue(1000); f.wait(); ``` -------------------------------- ### Build Project and Generate Compile Commands Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/modules-converter.md This sequence of commands builds the async_simple project using clang and CMake, generating a `compile_commands.json` file necessary for clang-modules-converter to analyze the project's compilation settings. ```shell mkdir build cd build CXX=clang++ CC=clang cmake ../ -DCMAKE_BUILD_TYPE=Release -DASYNC_SIMPLE_DISABLE_AIO=ON make -j4 ``` -------------------------------- ### Implement Custom Sleep Coroutine with Cancellation Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/SignalAndCancellation.md This C++ code demonstrates how to implement a custom coroutine 'sleep' function that supports cancellation. It utilizes `async-simple`'s signal helpers for managing cancellation states during the awaiter's lifecycle. This example is crucial for developers needing to integrate custom asynchronous operations with the library's cancellation mechanism. ```cpp using Duration = std::chrono::milliseconds; class TimeAwaiter { public: TimeAwaiter(Duration dur, Slot *slot) : _asyncTimer(...), _dur(dur), _slot(slot) {} public: bool await_ready() const noexcept { // Check if canceled before suspension (if canceled, the coroutine will immediately call await_resume()) return signalHelper{terminate}.hasCanceled(_slot); } void await_suspend(std::coroutine_handle<> handle) { _asyncTimer.sleep_for(_dur, [handle](auto&&){ handle.resume(); }) bool hasnt_canceled = signalHelper{terminate}.tryEmplace( _slot, [this](SignalType, Signal*) { _asyncTimer.cancel(); }); if (!hasnt_canceled) { // If canceled _asyncTimer.cancel(); } } // Check if canceled after suspension (if canceled, throw SignalException). If not canceled, clear slot function. void await_resume() { signalHelper{terminate}.checkHasCanceled(_slot); } // Helper function to speed up Lazy co_await (it will ignore the lazy's executor) auto coAwait(Executor *) { return *this; } private: AsyncTimer _asyncTimer; Duration _dur; Slot *_slot; }; // Throw SignalException if canceled. template Lazy my_sleep(Duratio dur) { co_return co_await TimeAwaiter{dur,co_await CurrentSlot{}}; } ``` -------------------------------- ### Test Deployment Libraries Configuration (CMake) Source: https://github.com/alibaba/async_simple/blob/main/CMakeLists.txt Configures the list of libraries required for testing, including GTest, GMock, Threads, and optionally AIO libraries. This list is used for linking against test executables. ```cmake set(testdeplibs) list(APPEND testdeplibs ${GTEST_LIBRARIES}) list(APPEND testdeplibs ${GMOCK_LIBRARIES}) list(APPEND testdeplibs ${CMAKE_THREAD_LIBS_INIT}) if(NOT ASYNC_SIMPLE_DISABLE_AIO AND LIBAIO_INCLUDE_DIR AND LIBAIO_LIBRARIES) list(APPEND testdeplibs ${LIBAIO_LIBRARIES}) endif() ``` -------------------------------- ### Registering Signal Handlers with Slots in C++ Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/SignalAndCancellation.md Illustrates registering a signal handler callback function with a `Slot` in C++. The handler is triggered when a specific signal type is emitted. The example shows how to use a `std::promise` within the handler to signal completion and how to handle potential blocking and thread safety concerns, emphasizing that handlers should not block and should access signals via the provided pointer. ```cpp // Create a Signal through factory methods std::shared_ptr signal = Signal::create(); std::vector> works; for (int i=0;i<10;++i) { // Create a slot for each asynchronous task auto slot = std::make_unique(signal.get()); // Execute the task asynchronously std::async(std::launch::async, [slot=std::move(slot)] { std::unique_ptr> p; auto f = p->get_future(); bool ok = slot->emplace(SignalType::terminate, // The bit position representing the callback function to be triggered. This enum should have exactly one bit set to 1. If the signal submitted has this bit set to 1, the callback function will be triggered. [p=std::move(p)](SignalType, Signal*){ p->set_value(); }); if (ok) { // If the cancellation signal has not been triggered f.wait_for(1s*(rand()+1)); // Sleep for a while unless the cancellation signal is triggered. } slot->clear(); // Clear the callback function if (slot->signal()) { // If the slot is bound to a signal slot->signal()->emits(SignalType::terminate); // Trigger the cancellation signal. } return; }); } // ... // Once the first asynchronous sleep task ends, other tasks will be terminated together. for (auto &e:works) e.get(); ``` -------------------------------- ### LazyLocals Implementation and Usage Source: https://github.com/alibaba/async_simple/blob/main/docs/docs.en/Lazy.md LazyLocals provides a mechanism similar to `thread_local` for coroutines, allowing customization by deriving from `LazyLocalBase` and implementing `T::classsof`. async_simple offers safe and efficient type conversion checks without RTTI and manages the lifecycle automatically. The example demonstrates creating a custom `mylocal` type, retrieving and using its value within coroutines via `co_await CurrentLazyLocals`, and setting LazyLocals using `setLazyLocal`. ```cpp template struct mylocal: public LazyLocalBase { template mylocalImpl(Args...&& args): LazyLocalBase(&tag), value(std::forward(args)...){} static bool classof(const LazyLocalBase* base) { return base->getTypeTag() == &tag; } T value; inline static char tag; }; void foo() { auto sub_task = []() -> Lazy<> { // Get the pointer to the lazy local value by calling co_await CurrentLazyLocals mylocal* v = co_await CurrentLazyLocals>{}; // If the coroutine is not bound to a local variable, or the type conversion fails, return a null pointer EXPECT_NE(v, nullptr); EXPECT_EQ(v->value, 42); }; auto task = []() -> Lazy<> { // Obtain the base class pointer LazyLocalBase* v = co_await CurrentLazyLocals{}; // If the coroutine is not bound to a local variable, return a null pointer EXPECT_NE(v, nullptr); // The user can skip the safety check of type conversion by casting the base class pointer EXPECT_EQ(static_cast>(v)->value, 42); // The local value will automatically propagate to each coroutine in the call chain via co_await co_await sub_task(); co_return; }; syncAwait(task().setLazyLocal>(42)); } ```