From 1e3ef96e91487bf06958d1b1867d436e2ebfeafa Mon Sep 17 00:00:00 2001 From: Steve Gerbino Date: Fri, 24 Jul 2026 16:17:41 +0200 Subject: [PATCH 1/2] ci: build the clang-cl leg in post-C++20 mode as well The IOCP backend only compiles on the Windows legs, and none of them exercised anything newer than C++20; newest-standard coverage existed only on platforms where that backend preprocesses away. Use cxxstd=latest rather than 23: the msvc toolset (whose flags clang-win inherits) has no /std: mapping for 23, so cxxstd=23 emits no standard flag, the cxx20_hdr_concepts configure check fails at the C++14 default, and b2 silently skips every target in that variant. latest maps to /std:c++latest, which enables the C++23-and-later library (_HAS_CXX23) on clang-cl. --- .github/compilers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/compilers.json b/.github/compilers.json index 0c8ff041c..4443a1844 100644 --- a/.github/compilers.json +++ b/.github/compilers.json @@ -127,7 +127,7 @@ "clang-cl": [ { "version": "*", - "cxxstd": "20", + "cxxstd": "20,latest", "latest_cxxstd": "20", "runs_on": "windows-2022", "cxx": "clang++-cl", From 67ac0d440e6398120d035eae49d9546e8467879c Mon Sep 17 00:00:00 2001 From: Steve Gerbino Date: Fri, 24 Jul 2026 16:12:47 +0200 Subject: [PATCH 2/2] fix(iocp): define win_scheduler ctor after win_wait_reactor is complete The constructor's unwind path destroys the unique_ptr member, so its definition odr-uses the deleter. In C++23 unique_ptr's destructor is constexpr and gets instantiated eagerly at the point of definition, where win_wait_reactor was still incomplete. Move the ctor below the deferred win_wait_reactor.hpp include, alongside the dtor and shutdown() which already live there for the same reason. --- .../native/detail/iocp/win_scheduler.hpp | 67 ++++++++++--------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/include/boost/corosio/native/detail/iocp/win_scheduler.hpp b/include/boost/corosio/native/detail/iocp/win_scheduler.hpp index 4e7247a05..c717c755e 100644 --- a/include/boost/corosio/native/detail/iocp/win_scheduler.hpp +++ b/include/boost/corosio/native/detail/iocp/win_scheduler.hpp @@ -209,36 +209,10 @@ struct thread_context_guard } // namespace iocp -inline win_scheduler::win_scheduler( - capy::execution_context& ctx, int concurrency_hint) - : iocp_(nullptr) - , outstanding_work_(0) - , stopped_(0) - , stop_event_posted_(0) - , dispatch_required_(0) -{ - // concurrency_hint < 0 means use system default (DWORD(~0) = max) - iocp_ = ::CreateIoCompletionPort( - INVALID_HANDLE_VALUE, nullptr, 0, - static_cast( - concurrency_hint >= 0 ? concurrency_hint : DWORD(~0))); - - if (iocp_ == nullptr) - detail::throw_system_error(make_err(::GetLastError())); - - // Create timer wakeup mechanism (tries NT native, falls back to thread) - timers_ = make_win_timers(iocp_, &dispatch_required_); - - // Connect timer service to scheduler - set_timer_service(&get_timer_service(ctx, *this)); - - // Initialize resolver service - ctx.make_service(*this); -} - -// ~win_scheduler() and shutdown() are defined at the bottom of this -// header so the unique_ptr's deleter and -// wait_reactor_->stop() see the type complete. +// The constructor, ~win_scheduler() and shutdown() are defined at the +// bottom of this header so the unique_ptr's deleter +// and wait_reactor_->stop() see the type complete. The constructor +// needs it too: its unwind path destroys wait_reactor_. inline void win_scheduler::post(std::coroutine_handle<> h) const @@ -697,9 +671,9 @@ win_scheduler::update_timeout() // Defer including the auxiliary wait reactor until the scheduler is // fully defined, since the reactor's inline methods call back into -// win_scheduler. This also gives the dtor and wait_reactor() below a -// complete win_wait_reactor type for unique_ptr destruction and -// lazy construction. +// win_scheduler. This also gives the ctor, dtor and wait_reactor() +// below a complete win_wait_reactor type for unique_ptr destruction +// and lazy construction. // // The macro lets win_wait_reactor.hpp diagnose direct inclusion // (which would land it here with win_scheduler still incomplete). @@ -708,6 +682,33 @@ win_scheduler::update_timeout() namespace boost::corosio::detail { +inline win_scheduler::win_scheduler( + capy::execution_context& ctx, int concurrency_hint) + : iocp_(nullptr) + , outstanding_work_(0) + , stopped_(0) + , stop_event_posted_(0) + , dispatch_required_(0) +{ + // concurrency_hint < 0 means use system default (DWORD(~0) = max) + iocp_ = ::CreateIoCompletionPort( + INVALID_HANDLE_VALUE, nullptr, 0, + static_cast( + concurrency_hint >= 0 ? concurrency_hint : DWORD(~0))); + + if (iocp_ == nullptr) + detail::throw_system_error(make_err(::GetLastError())); + + // Create timer wakeup mechanism (tries NT native, falls back to thread) + timers_ = make_win_timers(iocp_, &dispatch_required_); + + // Connect timer service to scheduler + set_timer_service(&get_timer_service(ctx, *this)); + + // Initialize resolver service + ctx.make_service(*this); +} + inline void win_scheduler::shutdown() {