.. _program_listing_file_EventLoop_BaseEventLoop.cpp: Program Listing for File BaseEventLoop.cpp ========================================== |exhale_lsh| :ref:`Return to documentation for file ` (``EventLoop/BaseEventLoop.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include "netio3-backend/EventLoop/BaseEventLoop.hpp" #include netio3::EventSignalHandle netio3::BaseEventLoop::create_signal( const std::function& cb, bool useSemaphore) { const auto flags = [&useSemaphore] () -> int { if (useSemaphore) { return EFD_NONBLOCK | EFD_SEMAPHORE; } return EFD_NONBLOCK; }(); const auto fd = eventfd(0, flags); const auto etx = EventContext{ .fd = fd, .cb = [cb](int fd_cb) { std::uint64_t buf{}; constexpr static auto NBYTES = 8; if (NBYTES != read(fd_cb, &buf, sizeof(buf))) { ERS_DEBUG(1, std::format("Did not read 8 bytes. Instead: {}", buf)); } if (cb) { cb(fd_cb); } }, }; register_fd(etx); return EventSignalHandle{fd, shared_from_this()}; } void netio3::BaseEventLoop::remove_signal(const EventSignalHandle& handle) { remove_fd(handle.get_fd(), true, true); } netio3::EventTimerHandle netio3::BaseEventLoop::create_timer(const std::function& cb) { const auto fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); const auto etx = EventContext{.fd = fd, .cb = [cb](int fd_cb) { std::uint64_t buf{}; constexpr static auto NBYTES = 8; if (NBYTES != read(fd_cb, &buf, sizeof(buf))) { ERS_DEBUG(1, std::format("Did not read 8 bytes. Instead: {}", buf)); } if (cb) { cb(fd_cb); } }}; register_fd(etx); return EventTimerHandle{fd, shared_from_this()}; } void netio3::BaseEventLoop::remove_timer(const EventTimerHandle& handle) { remove_fd(handle.get_fd(), true); } void netio3::BaseEventLoop::update_flags(const int fd, const int new_flags) { const auto flags = fcntl(fd, F_GETFL) | new_flags; if (fcntl(fd, F_SETFL, flags) < 0) { ers::error(FailedUpdateFdFlags(ERS_HERE, fd, utility::error_message(errno))); } } void netio3::BaseEventLoop::wait_for_fd(const int fd, const std::chrono::milliseconds timeout, const std::function& finish_function) const { const auto now = std::chrono::steady_clock::now(); while (std::chrono::steady_clock::now() - now < timeout) { if (check_fd(fd)) { if (get_thread_id() == std::this_thread::get_id()) { finish_function(); return; } constexpr static auto WAIT_TIME = std::chrono::milliseconds{10}; std::this_thread::sleep_for(WAIT_TIME); } else { // Signal handled return; } } ers::warning(SkippedEvents(ERS_HERE, fd)); } bool netio3::BaseEventLoop::check_fd(const int fd) { auto pfd = pollfd{.fd = fd, .events = POLLIN, .revents = 0}; const auto poll_status = poll(&pfd, 1, 0); return poll_status > 0 && ((pfd.revents & POLLIN) != 0); }