Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package aws-crt-cpp for openSUSE:Factory checked in at 2026-10-18 20:09:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/aws-crt-cpp (Old) and /work/SRC/openSUSE:Factory/.aws-crt-cpp.new.3698736 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "aws-crt-cpp" Sun Oct 18 20:09:06 2026 rev:61 rq:1385013 version:0.43.9 Changes: -------- --- /work/SRC/openSUSE:Factory/aws-crt-cpp/aws-crt-cpp.changes 2026-09-11 18:07:48.150086241 +0200 +++ /work/SRC/openSUSE:Factory/.aws-crt-cpp.new.3698736/aws-crt-cpp.changes 2026-10-18 20:09:07.641743606 +0200 @@ -1,0 +2,11 @@ +Tue Oct 13 09:32:29 UTC 2026 - John Paul Adrian Glaubitz <[email protected]> + +- Update to version 0.43.9 + * Update submodules by @azkrishpy in (#904) +- from version 0.43.8 + * update Schedule API to return a task handle by @sbiscigl in (#911) +- from version 0.43.7 + * add access to schedule directly on event loop group from io + bootstrap by @sbiscigl in (#909) + +------------------------------------------------------------------- Old: ---- v0.43.6.tar.gz New: ---- v0.43.9.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ aws-crt-cpp.spec ++++++ --- /var/tmp/diff_new_pack.v22vsC/_old 2026-10-18 20:09:08.326772273 +0200 +++ /var/tmp/diff_new_pack.v22vsC/_new 2026-10-18 20:09:08.327772315 +0200 @@ -20,7 +20,7 @@ %define library_soversion 1 Name: aws-crt-cpp -Version: 0.43.6 +Version: 0.43.9 Release: 0 Summary: AWS C++ wrapper for AWS SDK C libraries License: Apache-2.0 ++++++ v0.43.6.tar.gz -> v0.43.9.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.43.6/VERSION new/aws-crt-cpp-0.43.9/VERSION --- old/aws-crt-cpp-0.43.6/VERSION 2026-09-09 20:44:58.000000000 +0200 +++ new/aws-crt-cpp-0.43.9/VERSION 2026-10-07 20:11:42.000000000 +0200 @@ -1 +1 @@ -0.43.6 +0.43.9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.43.6/include/aws/crt/io/Bootstrap.h new/aws-crt-cpp-0.43.9/include/aws/crt/io/Bootstrap.h --- old/aws-crt-cpp-0.43.6/include/aws/crt/io/Bootstrap.h 2026-09-09 20:44:58.000000000 +0200 +++ new/aws-crt-cpp-0.43.9/include/aws/crt/io/Bootstrap.h 2026-10-07 20:11:42.000000000 +0200 @@ -89,6 +89,12 @@ */ void EnableBlockingShutdown() noexcept; + /** + * Returns a non-owning view of the next event loop from the EventLoopGroup this bootstrap was + * constructed with. Use it to schedule tasks (such as delayed work) on the transport's loop. + */ + EventLoop GetNextEventLoop() const noexcept; + /// @private aws_client_bootstrap *GetUnderlyingHandle() const noexcept; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.43.6/include/aws/crt/io/ChannelHandler.h new/aws-crt-cpp-0.43.9/include/aws/crt/io/ChannelHandler.h --- old/aws-crt-cpp-0.43.6/include/aws/crt/io/ChannelHandler.h 2026-09-09 20:44:58.000000000 +0200 +++ new/aws-crt-cpp-0.43.9/include/aws/crt/io/ChannelHandler.h 2026-10-07 20:11:42.000000000 +0200 @@ -6,6 +6,7 @@ #include <aws/crt/Exports.h> #include <aws/crt/Types.h> +#include <aws/crt/io/EventLoopGroup.h> #include <aws/io/channel.h> #include <chrono> @@ -31,12 +32,6 @@ ApplicationData, }; - enum class TaskStatus - { - RunReady, - Canceled, - }; - /** * Wrapper for aws-c-io channel handlers. The semantics are identical as the functions on * aws_channel_handler. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.43.6/include/aws/crt/io/EventLoopGroup.h new/aws-crt-cpp-0.43.9/include/aws/crt/io/EventLoopGroup.h --- old/aws-crt-cpp-0.43.6/include/aws/crt/io/EventLoopGroup.h 2026-09-09 20:44:58.000000000 +0200 +++ new/aws-crt-cpp-0.43.9/include/aws/crt/io/EventLoopGroup.h 2026-10-07 20:11:42.000000000 +0200 @@ -7,6 +7,10 @@ #include <aws/io/event_loop.h> +#include <chrono> +#include <functional> +#include <memory> + namespace Aws { namespace Crt @@ -14,6 +18,67 @@ namespace Io { /** + * The status a scheduled task runs with: RunReady if it fired normally, or Canceled if the + * owning event loop shut down before it fired. + */ + enum class TaskStatus + { + RunReady, + Canceled, + }; + + /** + * A handle to a task scheduled with EventLoop::Schedule. Cancel() is safe to call from any + * thread, and does nothing if the task already ran. + */ + class AWS_CRT_CPP_API ScheduledTask final + { + public: + ScheduledTask() noexcept = default; + + void Cancel() noexcept; + + private: + class Impl; + + explicit ScheduledTask(std::shared_ptr<Impl> impl) noexcept; + + std::shared_ptr<Impl> m_impl; + + friend class EventLoop; + }; + + /** + * A non-owning view of a single event-loop belonging to an EventLoopGroup, on which tasks may be + * scheduled to run after a delay. Obtain one from EventLoopGroup or ClientBootstrap; the referenced + * loop is owned by the EventLoopGroup and must outlive any scheduled work. + */ + class AWS_CRT_CPP_API EventLoop final + { + public: + /** + * @return true if this view refers to a valid event loop. + */ + explicit operator bool() const noexcept { return m_loop != nullptr; } + + /** + * Runs the task on this event loop once run_in has passed, and returns a handle you can use to cancel + * it before then. If you cancel it, or the loop shuts down before run_in, the task fires early with + * TaskStatus::Canceled instead of RunReady. + */ + ScheduledTask Schedule( + std::function<void(TaskStatus)> &&task, + std::chrono::nanoseconds run_in) noexcept; + + private: + explicit EventLoop(aws_event_loop *loop) noexcept; + + aws_event_loop *m_loop; + + friend class ClientBootstrap; + }; + + /** * A collection of event loops. * * An event-loop is a thread for doing async work, such as I/O. Classes that need to do async work will ask diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.43.6/source/io/Bootstrap.cpp new/aws-crt-cpp-0.43.9/source/io/Bootstrap.cpp --- old/aws-crt-cpp-0.43.6/source/io/Bootstrap.cpp 2026-09-09 20:44:58.000000000 +0200 +++ new/aws-crt-cpp-0.43.9/source/io/Bootstrap.cpp 2026-10-07 20:11:42.000000000 +0200 @@ -126,6 +126,11 @@ return nullptr; } + + EventLoop ClientBootstrap::GetNextEventLoop() const noexcept + { + return EventLoop(aws_event_loop_group_get_next_loop(m_bootstrap->event_loop_group)); + } } // namespace Io } // namespace Crt } // namespace Aws diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.43.6/source/io/EventLoopGroup.cpp new/aws-crt-cpp-0.43.9/source/io/EventLoopGroup.cpp --- old/aws-crt-cpp-0.43.6/source/io/EventLoopGroup.cpp 2026-09-09 20:44:58.000000000 +0200 +++ new/aws-crt-cpp-0.43.9/source/io/EventLoopGroup.cpp 2026-10-07 20:11:42.000000000 +0200 @@ -3,6 +3,10 @@ * SPDX-License-Identifier: Apache-2.0. */ #include <aws/crt/io/EventLoopGroup.h> + +#include <aws/common/task_scheduler.h> + +#include <atomic> #include <iostream> namespace Aws @@ -74,6 +78,91 @@ return nullptr; } + class ScheduledTask::Impl : public std::enable_shared_from_this<ScheduledTask::Impl> + { + public: + Impl(aws_event_loop *loop, std::function<void(TaskStatus)> &&fn) : m_loop(loop), m_fn(std::move(fn)) + { + aws_task_init(&m_run.task, Impl::OnRun, this, "cpp-crt-event-loop-task"); + aws_task_init(&m_cancel.task, Impl::OnCancel, this, "cpp-crt-event-loop-cancel-task"); + } + + void Schedule(std::chrono::nanoseconds run_in) noexcept + { + m_run.self = shared_from_this(); + + uint64_t currentTimestamp = 0; + aws_event_loop_current_clock_time(m_loop, ¤tTimestamp); + aws_event_loop_schedule_task_future( + m_loop, &m_run.task, currentTimestamp + static_cast<uint64_t>(run_in.count())); + } + + void Cancel() noexcept + { + if (m_done.load() || m_cancelRequested.exchange(true)) + { + return; + } + + m_cancel.self = shared_from_this(); + aws_event_loop_schedule_task_now(m_loop, &m_cancel.task); + } + + private: + struct Queued + { + aws_task task; + std::shared_ptr<Impl> self; + }; + + static void OnRun(struct aws_task *, void *arg, enum aws_task_status status) + { + auto *self = reinterpret_cast<Impl *>(arg); + std::shared_ptr<Impl> runSelf = std::move(self->m_run.self); + std::function<void(TaskStatus)> fn; + fn.swap(self->m_fn); + self->m_done.store(true); + fn(static_cast<TaskStatus>(status)); + } + + static void OnCancel(struct aws_task *, void *arg, enum aws_task_status status) + { + auto *self = reinterpret_cast<Impl *>(arg); + std::shared_ptr<Impl> cancelSelf = std::move(self->m_cancel.self); + if (status == AWS_TASK_STATUS_RUN_READY && !self->m_done.load()) + { + aws_event_loop_cancel_task(self->m_loop, &self->m_run.task); + } + } + + aws_event_loop *m_loop; + std::function<void(TaskStatus)> m_fn; + Queued m_run; + Queued m_cancel; + std::atomic<bool> m_cancelRequested{false}; + std::atomic<bool> m_done{false}; + }; + + ScheduledTask::ScheduledTask(std::shared_ptr<Impl> impl) noexcept : m_impl(std::move(impl)) {} + + void ScheduledTask::Cancel() noexcept + { + if (m_impl) + { + m_impl->Cancel(); + } + } + + EventLoop::EventLoop(aws_event_loop *loop) noexcept : m_loop(loop) {} + + ScheduledTask EventLoop::Schedule( + std::function<void(TaskStatus)> &&task, + std::chrono::nanoseconds run_in) noexcept + { + auto impl = MakeShared<ScheduledTask::Impl>(ApiAllocator(), m_loop, std::move(task)); + impl->Schedule(run_in); + return ScheduledTask(impl); + } } // namespace Io } // namespace Crt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.43.6/tests/CMakeLists.txt new/aws-crt-cpp-0.43.9/tests/CMakeLists.txt --- old/aws-crt-cpp-0.43.6/tests/CMakeLists.txt 2026-09-09 20:44:58.000000000 +0200 +++ new/aws-crt-cpp-0.43.9/tests/CMakeLists.txt 2026-10-07 20:11:42.000000000 +0200 @@ -13,6 +13,13 @@ add_test_case(ApiStaticDefaultCreateDestroy) add_test_case(ApiStaticVersionReporting) add_test_case(EventLoopResourceSafety) +add_test_case(EventLoopScheduleRunsAfterDelay) +add_test_case(EventLoopScheduleCanceledOnShutdown) +add_test_case(EventLoopScheduleCancelBeforeFire) +add_test_case(EventLoopScheduleCancelAfterFireIsNoop) +add_test_case(EventLoopScheduleCancelFromWithinTask) +add_test_case(EventLoopScheduleDoubleCancel) +add_test_case(EventLoopScheduleDefaultHandleCancelIsNoop) add_test_case(ClientBootstrapResourceSafety) if(NOT BYO_CRYPTO) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.43.6/tests/EventLoopScheduleTest.cpp new/aws-crt-cpp-0.43.9/tests/EventLoopScheduleTest.cpp --- old/aws-crt-cpp-0.43.6/tests/EventLoopScheduleTest.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/aws-crt-cpp-0.43.9/tests/EventLoopScheduleTest.cpp 2026-10-07 20:11:42.000000000 +0200 @@ -0,0 +1,227 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include <aws/crt/Api.h> +#include <aws/crt/io/Bootstrap.h> +#include <aws/crt/io/EventLoopGroup.h> +#include <aws/crt/io/HostResolver.h> +#include <aws/testing/aws_test_harness.h> + +#include <atomic> +#include <chrono> +#include <future> +#include <thread> + +static int s_TestEventLoopScheduleRunsAfterDelay(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + Aws::Crt::Io::EventLoopGroup eventLoopGroup(0, allocator); + Aws::Crt::Io::DefaultHostResolver defaultHostResolver(eventLoopGroup, 8, 30, allocator); + Aws::Crt::Io::ClientBootstrap clientBootstrap(eventLoopGroup, defaultHostResolver, allocator); + + std::promise<Aws::Crt::Io::TaskStatus> taskStatus; + std::future<Aws::Crt::Io::TaskStatus> taskStatusFuture = taskStatus.get_future(); + + const auto scheduledAt = std::chrono::steady_clock::now(); + std::chrono::steady_clock::time_point ranAt; + + clientBootstrap.GetNextEventLoop().Schedule( + [&](Aws::Crt::Io::TaskStatus status) + { + ranAt = std::chrono::steady_clock::now(); + taskStatus.set_value(status); + }, + std::chrono::milliseconds(200)); + + ASSERT_TRUE(std::future_status::ready == taskStatusFuture.wait_for(std::chrono::seconds(10))); + ASSERT_TRUE(Aws::Crt::Io::TaskStatus::RunReady == taskStatusFuture.get()); + + auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(ranAt - scheduledAt); + ASSERT_TRUE(elapsed.count() >= 150); + } + + return AWS_OP_SUCCESS; +} + +static int s_TestEventLoopScheduleCanceledOnShutdown(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + + std::promise<Aws::Crt::Io::TaskStatus> taskStatus; + std::future<Aws::Crt::Io::TaskStatus> taskStatusFuture = taskStatus.get_future(); + Aws::Crt::Io::ScheduledTask scheduledTask; + + { + Aws::Crt::Io::EventLoopGroup eventLoopGroup(0, allocator); + Aws::Crt::Io::DefaultHostResolver defaultHostResolver(eventLoopGroup, 8, 30, allocator); + Aws::Crt::Io::ClientBootstrap clientBootstrap(eventLoopGroup, defaultHostResolver, allocator); + + scheduledTask = clientBootstrap.GetNextEventLoop().Schedule( + [&taskStatus](Aws::Crt::Io::TaskStatus status) { taskStatus.set_value(status); }, + std::chrono::seconds(30)); + } + + ASSERT_TRUE(std::future_status::ready == taskStatusFuture.wait_for(std::chrono::seconds(10))); + ASSERT_TRUE(Aws::Crt::Io::TaskStatus::Canceled == taskStatusFuture.get()); + + scheduledTask.Cancel(); + } + + return AWS_OP_SUCCESS; +} + +static int s_TestEventLoopScheduleCancelBeforeFire(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + Aws::Crt::Io::EventLoopGroup eventLoopGroup(0, allocator); + Aws::Crt::Io::DefaultHostResolver defaultHostResolver(eventLoopGroup, 8, 30, allocator); + Aws::Crt::Io::ClientBootstrap clientBootstrap(eventLoopGroup, defaultHostResolver, allocator); + + std::promise<Aws::Crt::Io::TaskStatus> taskStatus; + std::future<Aws::Crt::Io::TaskStatus> taskStatusFuture = taskStatus.get_future(); + + const auto scheduledAt = std::chrono::steady_clock::now(); + auto scheduledTask = clientBootstrap.GetNextEventLoop().Schedule( + [&taskStatus](Aws::Crt::Io::TaskStatus status) { taskStatus.set_value(status); }, std::chrono::seconds(30)); + + scheduledTask.Cancel(); + + ASSERT_TRUE(std::future_status::ready == taskStatusFuture.wait_for(std::chrono::seconds(10))); + ASSERT_TRUE(Aws::Crt::Io::TaskStatus::Canceled == taskStatusFuture.get()); + + auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - scheduledAt); + ASSERT_TRUE(elapsed.count() < 10); + } + + return AWS_OP_SUCCESS; +} + +static int s_TestEventLoopScheduleCancelAfterFireIsNoop(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + Aws::Crt::Io::EventLoopGroup eventLoopGroup(0, allocator); + Aws::Crt::Io::DefaultHostResolver defaultHostResolver(eventLoopGroup, 8, 30, allocator); + Aws::Crt::Io::ClientBootstrap clientBootstrap(eventLoopGroup, defaultHostResolver, allocator); + + std::atomic<int> invocations{0}; + std::promise<Aws::Crt::Io::TaskStatus> taskStatus; + std::future<Aws::Crt::Io::TaskStatus> taskStatusFuture = taskStatus.get_future(); + + auto scheduledTask = clientBootstrap.GetNextEventLoop().Schedule( + [&](Aws::Crt::Io::TaskStatus status) + { + ++invocations; + taskStatus.set_value(status); + }, + std::chrono::milliseconds(10)); + + ASSERT_TRUE(std::future_status::ready == taskStatusFuture.wait_for(std::chrono::seconds(10))); + ASSERT_TRUE(Aws::Crt::Io::TaskStatus::RunReady == taskStatusFuture.get()); + + scheduledTask.Cancel(); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + ASSERT_INT_EQUALS(1, invocations.load()); + } + + return AWS_OP_SUCCESS; +} + +static int s_TestEventLoopScheduleCancelFromWithinTask(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + Aws::Crt::Io::EventLoopGroup eventLoopGroup(0, allocator); + Aws::Crt::Io::DefaultHostResolver defaultHostResolver(eventLoopGroup, 8, 30, allocator); + Aws::Crt::Io::ClientBootstrap clientBootstrap(eventLoopGroup, defaultHostResolver, allocator); + + std::atomic<int> invocations{0}; + std::promise<Aws::Crt::Io::ScheduledTask> handle; + std::shared_future<Aws::Crt::Io::ScheduledTask> handleFuture = handle.get_future().share(); + std::promise<Aws::Crt::Io::TaskStatus> taskStatus; + std::future<Aws::Crt::Io::TaskStatus> taskStatusFuture = taskStatus.get_future(); + + handle.set_value(clientBootstrap.GetNextEventLoop().Schedule( + [&, handleFuture](Aws::Crt::Io::TaskStatus status) + { + ++invocations; + Aws::Crt::Io::ScheduledTask self = handleFuture.get(); + self.Cancel(); + taskStatus.set_value(status); + }, + std::chrono::milliseconds(50))); + + ASSERT_TRUE(std::future_status::ready == taskStatusFuture.wait_for(std::chrono::seconds(10))); + ASSERT_TRUE(Aws::Crt::Io::TaskStatus::RunReady == taskStatusFuture.get()); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + ASSERT_INT_EQUALS(1, invocations.load()); + } + + return AWS_OP_SUCCESS; +} + +static int s_TestEventLoopScheduleDoubleCancel(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + Aws::Crt::Io::EventLoopGroup eventLoopGroup(0, allocator); + Aws::Crt::Io::DefaultHostResolver defaultHostResolver(eventLoopGroup, 8, 30, allocator); + Aws::Crt::Io::ClientBootstrap clientBootstrap(eventLoopGroup, defaultHostResolver, allocator); + + std::atomic<int> invocations{0}; + std::promise<Aws::Crt::Io::TaskStatus> taskStatus; + std::future<Aws::Crt::Io::TaskStatus> taskStatusFuture = taskStatus.get_future(); + + auto scheduledTask = clientBootstrap.GetNextEventLoop().Schedule( + [&](Aws::Crt::Io::TaskStatus status) + { + ++invocations; + taskStatus.set_value(status); + }, + std::chrono::seconds(30)); + + scheduledTask.Cancel(); + scheduledTask.Cancel(); + + ASSERT_TRUE(std::future_status::ready == taskStatusFuture.wait_for(std::chrono::seconds(10))); + ASSERT_TRUE(Aws::Crt::Io::TaskStatus::Canceled == taskStatusFuture.get()); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + ASSERT_INT_EQUALS(1, invocations.load()); + } + + return AWS_OP_SUCCESS; +} + +static int s_TestEventLoopScheduleDefaultHandleCancelIsNoop(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + + Aws::Crt::Io::ScheduledTask scheduledTask; + scheduledTask.Cancel(); + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(EventLoopScheduleRunsAfterDelay, s_TestEventLoopScheduleRunsAfterDelay) +AWS_TEST_CASE(EventLoopScheduleCanceledOnShutdown, s_TestEventLoopScheduleCanceledOnShutdown) +AWS_TEST_CASE(EventLoopScheduleCancelBeforeFire, s_TestEventLoopScheduleCancelBeforeFire) +AWS_TEST_CASE(EventLoopScheduleCancelAfterFireIsNoop, s_TestEventLoopScheduleCancelAfterFireIsNoop) +AWS_TEST_CASE(EventLoopScheduleCancelFromWithinTask, s_TestEventLoopScheduleCancelFromWithinTask) +AWS_TEST_CASE(EventLoopScheduleDoubleCancel, s_TestEventLoopScheduleDoubleCancel) +AWS_TEST_CASE(EventLoopScheduleDefaultHandleCancelIsNoop, s_TestEventLoopScheduleDefaultHandleCancelIsNoop)
