Ilias
一个类似tokio的C++20的迷你异步库 Lightweight asynchronous io library for modern C++, with minimal dependency, support tcp, udp, file, console, pipe
Install / Use
/learn @BusyStudent/IliasREADME
Ilias
<!-- Project Info Badges -->A lightweight asynchronous I/O library based on C++20 stackless coroutines, completion-based, and inspired by Tokio's design.
English | 中文
Features
- Zero-dependency core library
- Cancellation support
- Structured concurrency support (using
TaskScopeandTaskGroup) - Full networking support (TCP / UDP / async DNS resolution)
- File I/O
- TLS support (Windows: Schannel / Others: OpenSSL)
- Cross-platform (Windows / Linux)
- Single-threaded executor, easy to integrate with frameworks like Qt and convenient for development
Table of Contents
- Ilias
- Features
- Table of Contents
- 📊 CI Status
- Quick Start
- Contributing
- License
📊 CI Status
| CI Name | Status |
| --------- | ------- |
| Windows | |
| Linux |
|
| Coverage |
|
Quick Start
Adding to Your Project
For xmake projects
add_repositories("btk-repo https://github.com/Btk-Project/xmake-repo.git")
add_requires("ilias")
target("your_app")
add_packages("ilias")
For CMake projects
include(FetchContent)
FetchContent_Declare(
ilias
GIT_REPOSITORY https://github.com/BusyStudent/Ilias.git
GIT_TAG main
)
FetchContent_MakeAvailable(ilias)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE ilias::ilias)
Basic Environment
#include <ilias/platform.hpp>
#include <ilias/task.hpp>
auto main() -> int {
ilias::PlatformContext ctxt; // Create an I/O context for submitting tasks
ctxt.install(); // Register it to the current thread
// Currently available I/O contexts: IocpContext, EpollContext, UringContext, QIoContext
// A simple executor without I/O is: EventLoop
// PlatformContext is a typedef, automatically selected based on the compilation platform
auto task = []() -> ilias::Task<int> { // Coroutine function, return value must be Task<T>
co_return 1;
};
auto result = task().wait(); // Create the task and block until completion
// Task<T> represents a return value of T
assert(result == 1);
return 0;
}
Simplified with the ilias_main macro
If you want to simplify the code, you can use the ilias_main macro, which is equivalent to the code above.
#include <ilias/platform.hpp>
#include <ilias/task.hpp>
void ilias_main() {
co_return;
}
// Or return an int
int ilias_main() {
co_return 0;
}
// Supports two parameter formats
// - ilias_main()
// - ilias_main(int argc, char** argv)
// Return value supports void and int
// The `auto ->` syntax is currently not supported due to implementation limitations
Network Programming
Simple Message Sending
#include <ilias/platform.hpp>
#include <ilias/task.hpp>
#include <ilias/net.hpp>
using ilias::TcpStream;
void ilias_main() {
auto client = (co_await TcpStream::connect("127.0.0.1:8080")).value();
// ilias::makeBuffer converts any type convertible to std::span<T>
// into std::span<const std::byte> (Buffer) or std::span<std::byte> (MutableBuffer)
// The parameters for read and write are MutableBuffer and Buffer respectively
// read and write return an IoTask<size_t>
// IoTask<T> is an alias for Task<Result<T, std::error_code>>, indicating that an error might occur (see the Error Handling section for details)
std::string_view sv = "HELLO WORLD";
if (auto res = co_await client.write(ilias::makeBuffer(sv)); !res) {
co_return;
}
}
Accepting Connections
#include <ilias/platform.hpp>
#include <ilias/task.hpp>
#include <ilias/net.hpp>
using ilias::TcpListener;
using ilias::TcpStream;
using ilias::IPEndpoint;
// Coroutine to handle a client connection
auto handleClient(TcpStream stream) -> ilias::Task<void> {
std::array<std::byte, 1024> buffer;
// Read data and echo it back
while (true) {
auto n = co_await stream.read(buffer);
if (!n || n == 0) {
break;
}
co_await stream.write(ilias::makeBuffer(buffer.data(), *n));
}
}
void ilias_main() {
auto listener = (co_await TcpListener::bind("127.0.0.1:8080")).value();
while (true) {
auto [stream, endpoint] = (co_await listener.accept()).value();
// Spawn a new coroutine for each client
auto handle = ilias::spawn(handleClient(std::move(stream)));
// The handle can be used to check for completion or to wait for it
// Discarding the handle is equivalent to detaching
}
}
Spawning Coroutines
#include <ilias/platform.hpp>
#include <ilias/task.hpp>
void ilias_main() {
// Spawn a coroutine
auto handle = ilias::spawn(task());
// Spawn a blocking task, which will be submitted to a thread pool
auto handle2 = ilias::spawnBlocking(callable);
// The handle can be used to check for completion or to wait for it
co_await std::move(handle);
// For finer control over the coroutine's lifecycle, use TaskScope or TaskGroup<T>
}
Error Handling
Both error codes and exceptions are supported. The core type is Result<T, E>, an alias for std::expected<T, E>. Depending on the C++ version, it will use either the standard library implementation (C++23) or a third-party one (zeus_expected).
- Exceptions propagate up the call stack and are thrown at the
awaitpoint. Result<T, E>is equivalent tostd::expected<T, E>.Err<T>is equivalent tostd::unexpected<T>.IoResult<T>is equivalent toResult<T, std::error_code>.
Two Ways to Handle Errors
auto example() -> ilias::Task<void> {
// Method 1: Use value() (throws an exception on error, catch it at the top level with try-catch)
auto stream = (co_await TcpStream::connect("example.com:80")).value();
// Method 2: Explicitly check for errors
auto result = co_await TcpStream::connect("example.com:80");
if (!result) {
std::println("Connection failed: {}", result.error().message());
co_return;
}
// Use *result
}
Qt Integration
#include <ilias/platform/qt.hpp>
#include <QApplication>
auto main(int argc, char **argv) -> int {
QApplication app(argc, argv);
ilias::QIoContext ctxt; // An I/O context integrated with Qt
ctxt.install();
// Subsequent code is the same as on other platforms; coroutines can be used normally
return app.exec();
}
Cancellation
Cancellation is supported. A cancellation request will stop the execution of the current coroutine at an await point, similar to throwing an uncatchable exception.
#include <ilias/platform.hpp>
#include <ilias/task.hpp>
using namespace std::literals;
void ilias_main() {
auto task = []() -> ilias::Task<int> {
co_return 1;
};
auto handle = ilias::spawn(task());
handle.stop(); // Send a cancellation signal
// The result of `co_await` on a `WaitHandle<T>` is `Option<T>` (an alias for `std::optional`, with `void` automatically replaced by `std::monostate`)
// If it's `nullopt`, the task was cancelled
auto res = co_await std::move(handle);
assert(res == 1); // Since this task has no await points, the cancellation will not succeed
// A task with an await point
auto task2 = []() -> ilias::Task<int> {
co_await ilias::sleep(1000ms);
co_return 1;
};
auto handle2 = ilias::spawn(task2());
handle2.stop();
auto res2 = co_await std::move(handle2);
assert(res2 == std::nullopt); // Since sleep i
Related Skills
openhue
342.0kControl Philips Hue lights and scenes via the OpenHue CLI.
sag
342.0kElevenLabs text-to-speech with mac-style say UX.
weather
342.0kGet current weather and forecasts via wttr.in or Open-Meteo
tweakcc
1.5kCustomize Claude Code's system prompts, create custom toolsets, input pattern highlighters, themes/thinking verbs/spinners, customize input box & user message styling, support AGENTS.md, unlock private/unreleased features, and much more. Supports both native/npm installs on all platforms.
