From 6ad527a66744eb9912e4418dadde25066472b0d8 Mon Sep 17 00:00:00 2001 From: kanonwy Date: Fri, 29 Nov 2024 19:35:55 +0800 Subject: [PATCH 1/4] Add more precise interface handleTimeoutMicroseconds --- lcm/lcm-cpp-impl.hpp | 9 +++++++++ lcm/lcm-cpp.hpp | 11 +++++++++++ lcm/lcm.c | 26 ++++++++++++++++++++++++++ lcm/lcm.h | 24 ++++++++++++++++++++++++ test/cpp/memq_test.cpp | 9 +++++++++ 5 files changed, 79 insertions(+) diff --git a/lcm/lcm-cpp-impl.hpp b/lcm/lcm-cpp-impl.hpp index 4da2ac1f7..83ee27633 100644 --- a/lcm/lcm-cpp-impl.hpp +++ b/lcm/lcm-cpp-impl.hpp @@ -215,6 +215,15 @@ inline int LCM::handleTimeout(int timeout_millis) return lcm_handle_timeout(this->lcm, timeout_millis); } +inline int LCM::handleTimeoutMicroseconds(int timeout_micros) +{ + if (!this->lcm) { + fprintf(stderr, "LCM instance not initialized. Ignoring call to handle()\n"); + return -1; + } + return lcm_handle_timeout_microseconds(this->lcm, timeout_micros); +} + template Subscription *LCM::subscribe(const std::string &channel, void (MessageHandlerClass::*handlerMethod)(const ReceiveBuffer *rbuf, diff --git a/lcm/lcm-cpp.hpp b/lcm/lcm-cpp.hpp index 0b95c4efc..5fde121e8 100644 --- a/lcm/lcm-cpp.hpp +++ b/lcm/lcm-cpp.hpp @@ -142,6 +142,17 @@ class LCM { */ inline int handleTimeout(int timeout_millis); + /** + * @brief Waits for and dispatches messages, with a timeout. + * + * New in LCM 1.1.0. + * + * @return >0 if a message was handled, 0 if the function timed out, + * and <0 if an error occured. + * @sa lcm_handle_timeout_microseconds() + */ + inline int handleTimeoutMicroseconds(int timeout_micros); + /** * @brief Subscribes a callback method of an object to a channel, with * automatic message decoding. diff --git a/lcm/lcm.c b/lcm/lcm.c index 1379a4314..e0cc6bc9e 100644 --- a/lcm/lcm.c +++ b/lcm/lcm.c @@ -237,6 +237,32 @@ int lcm_handle_timeout(lcm_t *lcm, int timeout_milis) } } +int lcm_handle_timeout_microseconds(lcm_t *lcm, int timeout_micros) +{ + fd_set fds; + FD_ZERO(&fds); + SOCKET lcm_fd = lcm_get_fileno(lcm); + FD_SET(lcm_fd, &fds); + + struct timeval timeout; + timeout.tv_sec = timeout_micros / 1000000; + timeout.tv_usec = timeout_micros % 1000000; + + if (timeout_micros < 0) { + return -1; + } + + int select_result = select(lcm_fd + 1, &fds, NULL, NULL, &timeout); + if (select_result > 0) { + int lcm_handle_result = lcm_handle(lcm); + return lcm_handle_result == 0 ? 1 : lcm_handle_result; + } else if (select_result == 0) { + return 0; + } else { + return select_result; + } +} + int lcm_get_fileno(lcm_t *lcm) { if (lcm->provider && lcm->vtable->get_fileno) diff --git a/lcm/lcm.h b/lcm/lcm.h index fbd592cb6..d85cd438c 100644 --- a/lcm/lcm.h +++ b/lcm/lcm.h @@ -322,6 +322,30 @@ int lcm_handle(lcm_t *lcm); LCM_EXPORT int lcm_handle_timeout(lcm_t *lcm, int timeout_millis); +/** + * @brief Wait for and dispatch the next incoming message, up to a time limit. + * + * This function is equivalent to lcm_handle(), but if no messages are received + * and handled by the time @p timeout_micros microseconds elapses, then the + * function returns. + * + * This function largely exists for convenience, and its behavior can be + * replicated by using lcm_fileno() and lcm_handle() in conjunction with + * select() or poll(). + * + * New in LCM 1.1.0. + * + * @param lcm the %LCM object + * @param timeout_micros the maximum amount of time to wait for a message, in + * microseconds. If 0, then dispatches any available messages and then + * returns immediately. Values less than 0 are not allowed. + * + * @return >0 if a message was handled, 0 if the function timed out, and <0 if + * an error occured. + */ +LCM_EXPORT +int lcm_handle_timeout_microseconds(lcm_t *lcm, int timeout_micros); + /** * @brief Adjusts the maximum number of received messages that can be queued up * for a subscription. diff --git a/test/cpp/memq_test.cpp b/test/cpp/memq_test.cpp index a1cfa1ad2..9d9c52809 100644 --- a/test/cpp/memq_test.cpp +++ b/test/cpp/memq_test.cpp @@ -99,6 +99,15 @@ TEST(LCM_CPP, MemqTimeout) // Invalid timeout specification should result in an error. EXPECT_GT(0, lcm.handleTimeout(-1)); + // No messages available. Call should timeout immediately. + EXPECT_EQ(0, lcm.handleTimeoutMicroseconds(0)); + + // No messages available. Call should timeout in a few ms. + EXPECT_EQ(0, lcm.handleTimeoutMicroseconds(10)); + + // Invalid timeout specification should result in an error. + EXPECT_GT(0, lcm.handleTimeoutMicroseconds(-1)); + // Subscribe to and publish on a channel. Expect that the message gets // handled with an ample timeout. bool msg_handled = false; From 13c76a24d5a4f4bdd88805e3775557e58a323447 Mon Sep 17 00:00:00 2001 From: kanonwyqwas <46067218+KanonWY@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:15:04 +0800 Subject: [PATCH 2/4] Update lcm/lcm.c horten the name Co-authored-by: Tim Perkins --- lcm/lcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcm/lcm.c b/lcm/lcm.c index e0cc6bc9e..90d1c0188 100644 --- a/lcm/lcm.c +++ b/lcm/lcm.c @@ -237,7 +237,7 @@ int lcm_handle_timeout(lcm_t *lcm, int timeout_milis) } } -int lcm_handle_timeout_microseconds(lcm_t *lcm, int timeout_micros) +int lcm_handle_timeout_us(lcm_t *lcm, int timeout_micros) { fd_set fds; FD_ZERO(&fds); From bd607a98122e91b46a548cb7a1e31354198f2eaa Mon Sep 17 00:00:00 2001 From: kanonwyqwas <46067218+KanonWY@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:15:38 +0800 Subject: [PATCH 3/4] Update lcm/lcm-cpp-impl.hpp shorten function name Co-authored-by: Tim Perkins --- lcm/lcm-cpp-impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcm/lcm-cpp-impl.hpp b/lcm/lcm-cpp-impl.hpp index 83ee27633..7b1411591 100644 --- a/lcm/lcm-cpp-impl.hpp +++ b/lcm/lcm-cpp-impl.hpp @@ -215,7 +215,7 @@ inline int LCM::handleTimeout(int timeout_millis) return lcm_handle_timeout(this->lcm, timeout_millis); } -inline int LCM::handleTimeoutMicroseconds(int timeout_micros) +inline int LCM::handleTimeoutUs(int timeout_micros) { if (!this->lcm) { fprintf(stderr, "LCM instance not initialized. Ignoring call to handle()\n"); From c9393c29def68f4f3cec12f9d544588e7c13a5c5 Mon Sep 17 00:00:00 2001 From: kanon Date: Fri, 29 Nov 2024 21:46:56 +0800 Subject: [PATCH 4/4] shorten the name and format --- lcm/lcm-cpp-impl.hpp | 2 +- lcm/lcm-cpp.hpp | 4 ++-- lcm/lcm.h | 2 +- test/cpp/memq_test.cpp | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lcm/lcm-cpp-impl.hpp b/lcm/lcm-cpp-impl.hpp index 7b1411591..377bb47c5 100644 --- a/lcm/lcm-cpp-impl.hpp +++ b/lcm/lcm-cpp-impl.hpp @@ -221,7 +221,7 @@ inline int LCM::handleTimeoutUs(int timeout_micros) fprintf(stderr, "LCM instance not initialized. Ignoring call to handle()\n"); return -1; } - return lcm_handle_timeout_microseconds(this->lcm, timeout_micros); + return lcm_handle_timeout_us(this->lcm, timeout_micros); } template diff --git a/lcm/lcm-cpp.hpp b/lcm/lcm-cpp.hpp index 5fde121e8..54aca6fb0 100644 --- a/lcm/lcm-cpp.hpp +++ b/lcm/lcm-cpp.hpp @@ -149,9 +149,9 @@ class LCM { * * @return >0 if a message was handled, 0 if the function timed out, * and <0 if an error occured. - * @sa lcm_handle_timeout_microseconds() + * @sa lcm_handle_timeout_us() */ - inline int handleTimeoutMicroseconds(int timeout_micros); + inline int handleTimeoutUs(int timeout_micros); /** * @brief Subscribes a callback method of an object to a channel, with diff --git a/lcm/lcm.h b/lcm/lcm.h index d85cd438c..1f8a7ed86 100644 --- a/lcm/lcm.h +++ b/lcm/lcm.h @@ -344,7 +344,7 @@ int lcm_handle_timeout(lcm_t *lcm, int timeout_millis); * an error occured. */ LCM_EXPORT -int lcm_handle_timeout_microseconds(lcm_t *lcm, int timeout_micros); +int lcm_handle_timeout_us(lcm_t *lcm, int timeout_micros); /** * @brief Adjusts the maximum number of received messages that can be queued up diff --git a/test/cpp/memq_test.cpp b/test/cpp/memq_test.cpp index 9d9c52809..3965f5ac1 100644 --- a/test/cpp/memq_test.cpp +++ b/test/cpp/memq_test.cpp @@ -100,13 +100,13 @@ TEST(LCM_CPP, MemqTimeout) EXPECT_GT(0, lcm.handleTimeout(-1)); // No messages available. Call should timeout immediately. - EXPECT_EQ(0, lcm.handleTimeoutMicroseconds(0)); + EXPECT_EQ(0, lcm.handleTimeoutUs(0)); // No messages available. Call should timeout in a few ms. - EXPECT_EQ(0, lcm.handleTimeoutMicroseconds(10)); + EXPECT_EQ(0, lcm.handleTimeoutUs(10)); // Invalid timeout specification should result in an error. - EXPECT_GT(0, lcm.handleTimeoutMicroseconds(-1)); + EXPECT_GT(0, lcm.handleTimeoutUs(-1)); // Subscribe to and publish on a channel. Expect that the message gets // handled with an ample timeout.