Event Loops & Schedulers
Relevant source files
The following files were used as context for generating this wiki page:
The EventLoop and SerialScheduler components provide the core asynchronous execution infrastructure for HXLibs. The system manages coroutine lifecycles, platform-specific I/O multiplexing, and ordered task execution. It abstracts OS-specific APIs like Linux io_uring and Windows IOCP into a unified coroutine-based interface.
EventLoop Architecture
The EventLoop class coordinates three primary sub-loops: an I/O event driver, a timer loop, and a thread loop. It acts as the central orchestrator for coroutine resumption based on external events or timeouts.
Core Components
| Component | Description |
|---|---|
internal::EventDrive | The platform-specific I/O multiplexer (IoUring on Linux, Iocp on Windows). |
TimerLoop | Manages time-based tasks and sleep operations. |
ThreadLoop | Manages tasks requiring background thread execution. |
Sources: [include/HXLibs/coroutine/loop/EventLoop.hpp:426-440](https://github.com/HengXin666/HXLibs/blob/23b9882b257fe12f3fc2e260ce7b65d11bc51e3c/include/HXLibs/coroutine/loop/EventLoop.hpp#L426-L440)
Execution Flow
The run() method executes the main loop, which continuously polls timers and the I/O driver. If no I/O tasks are pending, the loop sleeps for the duration suggested by the timer loop.
Sources: [include/HXLibs/coroutine/loop/EventLoop.hpp:398-410](https://github.com/HengXin666/HXLibs/blob/23b9882b257fe12f3fc2e260ce7b65d11bc51e3c/include/HXLibs/coroutine/loop/EventLoop.hpp#L398-L410)
Platform-Specific Drivers
HXLibs uses different backends depending on the operating system to achieve high-performance I/O.
Linux: io_uring
The Linux implementation utilizes io_uring for asynchronous I/O. It initializes a submission queue and completion queue. The run method calls io_uring_submit_and_wait_timeout to process completed tasks. Completed tasks are mapped back to coroutine handles using the user_data field in the cqe (completion queue entry).
Sources: [include/HXLibs/coroutine/loop/EventLoop.hpp:116-160](https://github.com/HengXin666/HXLibs/blob/23b9882b257fe12f3fc2e260ce7b65d11bc51e3c/include/HXLibs/coroutine/loop/EventLoop.hpp#L116-L160), [include/HXLibs/platform/EventLoopApi.hpp:32-35](https://github.com/HengXin666/HXLibs/blob/23b9882b257fe12f3fc2e260ce7b65d11bc51e3c/include/HXLibs/platform/EventLoopApi.hpp#L32-L35)
Windows: IOCP
The Windows implementation utilizes I/O Completion Ports (IOCP). It initializes a completion port handle via CreateIoCompletionPort. The loop uses GetQueuedCompletionStatusEx to retrieve batch I/O results. Coroutine handles are resumed after the system retrieves OVERLAPPED entries from the port.
Sources: [include/HXLibs/coroutine/loop/EventLoop.hpp:217-268](https://github.com/HengXin666/HXLibs/blob/23b9882b257fe12f3fc2e260ce7b65d11bc51e3c/include/HXLibs/coroutine/loop/EventLoop.hpp#L217-L268), [include/HXLibs/platform/EventLoopApi.hpp:38-50](https://github.com/HengXin666/HXLibs/blob/23b9882b257fe12f3fc2e260ce7b65d11bc51e3c/include/HXLibs/platform/EventLoopApi.hpp#L38-L50)
Coroutine Synchronization
The EventLoop provides methods to integrate standard functions and coroutines into the event-driven environment.
- sync/trySync: Blocks the current thread until the provided coroutine completes. It throws an exception if called while the loop is already running to prevent deadlocks.
- start: Initiates a coroutine by calling
resume()on its handle. - makeTimer: Returns a timer object capable of asynchronous sleep operations.
Sources: [include/HXLibs/coroutine/loop/EventLoop.hpp:347-396](https://github.com/HengXin666/HXLibs/blob/23b9882b257fe12f3fc2e260ce7b65d11bc51e3c/include/HXLibs/coroutine/loop/EventLoop.hpp#L347-L396), [tests/execution/demo.cpp:16-20](https://github.com/HengXin666/HXLibs/blob/23b9882b257fe12f3fc2e260ce7b65d11bc51e3c/tests/execution/demo.cpp#L16-L20)
Serial Scheduler
The SerialScheduler ensures that a group of coroutines executes sequentially rather than concurrently. It uses a queue to manage pending tasks and a background promise to handle automatic cleanup of completed tasks.
Sequential Task Management
The scheduler maintains a std::queue of tuples containing the task reference and its corresponding std::coroutine_handle<>.
Sources: [include/HXLibs/coroutine/executor/_SerialScheduler.hpp:118-142](https://github.com/HengXin666/HXLibs/blob/23b9882b257fe12f3fc2e260ce7b65d11bc51e3c/include/HXLibs/coroutine/executor/_SerialScheduler.hpp#L118-L142)
Memory Safety and RAII
The SerialScheduler implements a BackgroundTask structure with a BackgroundPromise to manage the lifetime of sequential execution chains. This prevents "use-after-free" errors when a scheduler is destroyed while tasks are still pending in the queue.
Sources: [include/HXLibs/coroutine/executor/_SerialScheduler.hpp:41-86](https://github.com/HengXin666/HXLibs/blob/23b9882b257fe12f3fc2e260ce7b65d11bc51e3c/include/HXLibs/coroutine/executor/_SerialScheduler.hpp#L41-L86), [tests/coroutine/04_SerialExecutor.cpp:59-65](https://github.com/HengXin666/HXLibs/blob/23b9882b257fe12f3fc2e260ce7b65d11bc51e3c/tests/coroutine/04_SerialExecutor.cpp#L59-L65)
Summary
The HXLibs Event Loop system provides a robust foundation for asynchronous C++20 applications. By leveraging io_uring and IOCP, it achieves platform-native performance while providing developers with a high-level coroutine API. The SerialScheduler complements this by offering a mechanism for ordered, non-concurrent task execution within the same event loop context.