TYPE_SELECT = 1,
TYPE_EPOLL = 2, // Linux OS (Linux like OS) only
TYPE_KQUEUE = 3, // BSD OS (BSD like OS) only
+ TYPE_POLL = 4,
};
/// @brief Constructor.
#include <config.h>
#include <util/fd_event_handler_factory.h>
+#include <util/poll_event_handler.h>
#include <util/select_event_handler.h>
namespace isc {
FDEventHandlerPtr FDEventHandlerFactory::factoryFDEventHandler() {
// todo: use configuration to initialize the FDEventHandler.
- return (FDEventHandlerPtr(new SelectEventHandler()));
+ return (FDEventHandlerPtr(new PollEventHandler()));
}
} // end of namespace isc::util
'memory_segment_local.cc',
'multi_threading_mgr.cc',
'pid_file.cc',
+ 'poll_event_handler.cc',
'ready_check.cc',
'reconnect_ctl.cc',
'select_event_handler.cc',
'optional.h',
'pid_file.h',
'pointer_util.h',
+ 'poll_event_handler.h',
'range_utilities.h',
'readwrite_mutex.h',
'ready_check.h',
--- /dev/null
+// Copyright (C) 2025 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <exceptions/exceptions.h>
+#include <util/poll_event_handler.h>
+
+namespace isc {
+namespace util {
+
+PollEventHandler::PollEventHandler() : FDEventHandler(TYPE_POLL) {
+ clear();
+}
+
+void PollEventHandler::add(int fd, bool read /* = true */, bool write /* = false */) {
+ if (fd < 0) {
+ isc_throw(BadValue, "invalid negative value for fd");
+ }
+ struct pollfd data;
+ memset(&data, 0, sizeof(data));
+ data.fd = fd;
+ if (read) {
+ // Add this socket to read events
+ data.events |= POLLIN;
+ }
+ if (write) {
+ // Add this socket to write events
+ data.events |= POLLOUT;
+ }
+ data_.push_back(data);
+}
+
+int PollEventHandler::waitEvent(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
+ // Sanity check for microsecond timeout.
+ if (timeout_usec >= 1000000) {
+ isc_throw(BadValue, "fractional timeout must be shorter than"
+ " one million microseconds");
+ }
+ int timeout = timeout_sec * 1000 + timeout_usec / 1000;
+ map_.clear();
+ for (size_t i = 0; i < data_.size(); ++i) {
+ map_[data_[i].fd] = &data_[i];
+ }
+ return (poll(data_.data(), data_.size(), timeout));
+}
+
+bool PollEventHandler::readReady(int fd) {
+ if (map_.find(fd) == map_.end()) {
+ return (false);
+ }
+ return (map_[fd]->revents & POLLIN);
+}
+
+bool PollEventHandler::writeReady(int fd) {
+ if (map_.find(fd) == map_.end()) {
+ return (false);
+ }
+ return (map_[fd]->revents & POLLOUT);
+}
+
+void PollEventHandler::clear() {
+ data_.clear();
+ map_.clear();
+}
+
+} // end of namespace isc::util
+} // end of namespace isc
--- /dev/null
+// Copyright (C) 2025 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef POLL_EVENT_HANDLER_H
+#define POLL_EVENT_HANDLER_H
+
+#include <util/fd_event_handler.h>
+
+#include <sys/poll.h>
+
+namespace isc {
+namespace util {
+
+/// @brief File descriptor event handler class handles events for registered
+/// file descriptors. This class uses the OS select syscall for event handling.
+class PollEventHandler : public FDEventHandler {
+public:
+ /// @brief Constructor.
+ PollEventHandler();
+
+ /// @brief Destructor.
+ virtual ~PollEventHandler() = default;
+
+ /// @brief Add file descriptor to watch for events.
+ ///
+ /// @param fd The file descriptor.
+ /// @param read The flag indicating if the file descriptor should be
+ /// registered for read ready events.
+ /// @param write The flag indicating if the file descriptor should be
+ /// registered for write ready events.
+ void add(int fd, bool read = true, bool write = false);
+
+ /// @brief Wait for events on registered file descriptors.
+ ///
+ /// @param timeout_sec The wait timeout in seconds.
+ /// @param timeout_usec The wait timeout in micro seconds
+ /// @return -1 on error, 0 if no data is available (timeout expired),
+ /// 1 if data is ready.
+ int waitEvent(uint32_t timeout_sec, uint32_t timeout_usec = 0);
+
+ /// @brief Check if file descriptor is ready for read operation.
+ ///
+ /// @param fd The file descriptor.
+ ///
+ /// @return True if file descriptor is ready for reading.
+ bool readReady(int fd);
+
+ /// @brief Check if file descriptor is ready for write operation.
+ ///
+ /// @param fd The file descriptor.
+ ///
+ /// @return True if file descriptor is ready for writing.
+ bool writeReady(int fd);
+
+ /// @brief Clear registered file descriptors.
+ void clear();
+
+private:
+ /// @brief The poll file descriptors data.
+ std::vector<struct pollfd> data_;
+
+ /// @brief The map with file descriptor to data reference.
+ std::unordered_map<int, struct pollfd*> map_;
+};
+
+} // namespace isc::util;
+} // namespace isc
+
+#endif // POLL_EVENT_HANDLER_H
// and process passed parameters.
TEST(FDEventHandlerFactory, factory) {
FDEventHandlerPtr handler = FDEventHandlerFactory::factoryFDEventHandler();
- EXPECT_EQ(handler->type(), FDEventHandler::TYPE_SELECT);
- EXPECT_THROW(handler->add(FD_SETSIZE), BadValue);
+ if (handler->type() == FDEventHandler::TYPE_SELECT) {
+ EXPECT_THROW(handler->add(FD_SETSIZE), BadValue);
+ }
}
} // end of anonymous namespace
#include <exceptions/exceptions.h>
#include <util/fd_event_handler.h>
+#include <util/poll_event_handler.h>
#include <util/select_event_handler.h>
#include <gtest/gtest.h>
'multi_threading_mgr_unittest.cc',
'optional_unittest.cc',
'pid_file_unittest.cc',
+ 'poll_event_handler_unittests.cc',
'range_utilities_unittest.cc',
'readwrite_mutex_unittest.cc',
'run_unittests.cc',
--- /dev/null
+// Copyright (C) 2025 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#define FDEventHandlerType PollEventHandler
+#define FDEventHandlerTest PollEventHandlerTest
+
+#include <fd_event_handler_unittests.h>
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
+#include <util/fd_event_handler_factory.h>
#include <util/ready_check.h>
#include <util/watch_socket.h>
ASSERT_NO_THROW(watch->clearReady());
// Verify the select_fd fails as socket is invalid/closed.
- EXPECT_EQ(-1, selectCheck(select_fd));
+ if (FDEventHandlerFactory::factoryFDEventHandler()->type() == FDEventHandler::TYPE_SELECT) {
+ EXPECT_EQ(-1, selectCheck(select_fd));
+ } else {
+ EXPECT_EQ(1, selectCheck(select_fd));
+ }
// Verify that subsequent attempts to mark it will fail.
ASSERT_THROW(watch->markReady(), WatchSocketError);
// Verify the select_fd does not evaluate to ready.
EXPECT_FALSE(watch->isReady());
- EXPECT_NE(1, selectCheck(select_fd));
+ if (FDEventHandlerFactory::factoryFDEventHandler()->type() == FDEventHandler::TYPE_SELECT) {
+ EXPECT_NE(1, selectCheck(select_fd));
+ } else {
+ EXPECT_EQ(1, selectCheck(select_fd));
+ }
// Verify that getSelectFd() returns INVALID.
ASSERT_EQ(WatchSocket::SOCKET_NOT_VALID, watch->getSelectFd());