From 2abbd1a9443fd8858a93265df6ca7c792fb16137 Mon Sep 17 00:00:00 2001 From: Charles Cabergs Date: Fri, 6 Mar 2026 22:54:47 +0100 Subject: [PATCH 1/3] Add poller_t::wait --- tests/poller.cpp | 13 +++++++++++++ zmq.hpp | 12 ++++++++++++ 2 files changed, 25 insertions(+) diff --git a/tests/poller.cpp b/tests/poller.cpp index e32592d2..17def08b 100644 --- a/tests/poller.cpp +++ b/tests/poller.cpp @@ -178,6 +178,19 @@ TEST_CASE("poller remove registered non empty", "[poller]") const std::string hi_str = "Hi"; + +TEST_CASE("poller wait", "[poller]") +{ + common_server_client_setup s; + CHECK_NOTHROW(s.client.send(zmq::message_t{hi_str}, zmq::send_flags::none)); + zmq::poller_t poller; + int i = 42; + CHECK_NOTHROW(poller.add(s.server, zmq::event_flags::pollin, &i)); + auto event = poller.wait(); + CHECK(s.server == event.socket); + CHECK(&i == event.user_data); +} + TEST_CASE("poller poll basic", "[poller]") { common_server_client_setup s; diff --git a/zmq.hpp b/zmq.hpp index 2e3fc2f5..81ddbc6c 100644 --- a/zmq.hpp +++ b/zmq.hpp @@ -2762,6 +2762,18 @@ template class poller_t } } + event_type wait(std::chrono::milliseconds timeout = std::chrono::milliseconds{ + -1}) + { + event_type event; + int rc = zmq_poller_wait(poller_ptr.get(), + reinterpret_cast(&event), + static_cast(timeout.count())); + if (rc == -1) + throw error_t(); + return event; + } + template size_t wait_all(Sequence &poller_events, const std::chrono::milliseconds timeout) { From c615553d727bbc03b4476c714b6f33c1ebf5a479 Mon Sep 17 00:00:00 2001 From: Charles Cabergs Date: Mon, 9 Mar 2026 21:21:02 +0100 Subject: [PATCH 2/3] Update poller_t::wait to return an optional which is nullopt on a timeout --- tests/poller.cpp | 15 +++++++++++++-- zmq.hpp | 17 +++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/tests/poller.cpp b/tests/poller.cpp index 17def08b..25387544 100644 --- a/tests/poller.cpp +++ b/tests/poller.cpp @@ -187,8 +187,19 @@ TEST_CASE("poller wait", "[poller]") int i = 42; CHECK_NOTHROW(poller.add(s.server, zmq::event_flags::pollin, &i)); auto event = poller.wait(); - CHECK(s.server == event.socket); - CHECK(&i == event.user_data); + CHECK(event.has_value()); + CHECK(s.server == event.value().socket); + CHECK(&i == event.value().user_data); +} + +TEST_CASE("poller wait timeout", "[poller]") +{ + common_server_client_setup s; + // No message sent so it will timeout + zmq::poller_t poller; + CHECK_NOTHROW(poller.add(s.server, zmq::event_flags::pollin, nullptr)); + auto event = poller.wait(std::chrono::milliseconds{3}); + CHECK(!event.has_value()); } TEST_CASE("poller poll basic", "[poller]") diff --git a/zmq.hpp b/zmq.hpp index 81ddbc6c..937357e6 100644 --- a/zmq.hpp +++ b/zmq.hpp @@ -2698,6 +2698,11 @@ template class poller_t { public: using event_type = poller_event; +#if CPPZMQ_HAS_OPTIONAL + using wait_result_t = std::optional; +#else + using wait_result_t = detail::trivial_optional; +#endif poller_t() : poller_ptr(zmq_poller_new()) { @@ -2762,15 +2767,19 @@ template class poller_t } } - event_type wait(std::chrono::milliseconds timeout = std::chrono::milliseconds{ - -1}) + wait_result_t wait(std::chrono::milliseconds timeout = std::chrono::milliseconds{ + -1}) { event_type event; int rc = zmq_poller_wait(poller_ptr.get(), reinterpret_cast(&event), static_cast(timeout.count())); - if (rc == -1) - throw error_t(); + if (rc == -1) { + if (zmq_errno() == EAGAIN) + return {}; + else + throw error_t(); + } return event; } From 0627db25d845729ec1ae72e5a5501589eebe8025 Mon Sep 17 00:00:00 2001 From: Charles Cabergs Date: Mon, 9 Mar 2026 22:26:58 +0100 Subject: [PATCH 3/3] Update poller_t::wait to return std::optional since the trivial optional implementation can only handle trivial types --- tests/poller.cpp | 3 ++- zmq.hpp | 11 ++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/poller.cpp b/tests/poller.cpp index 25387544..6307143a 100644 --- a/tests/poller.cpp +++ b/tests/poller.cpp @@ -178,7 +178,7 @@ TEST_CASE("poller remove registered non empty", "[poller]") const std::string hi_str = "Hi"; - +#if CPPZMQ_HAS_OPTIONAL TEST_CASE("poller wait", "[poller]") { common_server_client_setup s; @@ -201,6 +201,7 @@ TEST_CASE("poller wait timeout", "[poller]") auto event = poller.wait(std::chrono::milliseconds{3}); CHECK(!event.has_value()); } +#endif TEST_CASE("poller poll basic", "[poller]") { diff --git a/zmq.hpp b/zmq.hpp index 937357e6..778dcbb2 100644 --- a/zmq.hpp +++ b/zmq.hpp @@ -2698,11 +2698,6 @@ template class poller_t { public: using event_type = poller_event; -#if CPPZMQ_HAS_OPTIONAL - using wait_result_t = std::optional; -#else - using wait_result_t = detail::trivial_optional; -#endif poller_t() : poller_ptr(zmq_poller_new()) { @@ -2767,8 +2762,9 @@ template class poller_t } } - wait_result_t wait(std::chrono::milliseconds timeout = std::chrono::milliseconds{ - -1}) +#if CPPZMQ_HAS_OPTIONAL + std::optional + wait(std::chrono::milliseconds timeout = std::chrono::milliseconds{-1}) { event_type event; int rc = zmq_poller_wait(poller_ptr.get(), @@ -2782,6 +2778,7 @@ template class poller_t } return event; } +#endif template size_t wait_all(Sequence &poller_events, const std::chrono::milliseconds timeout)