#include "LinuxEvent.h" #include #include #include #include #include // 初始化静态成员 std::mutex LinuxEvent::s_namedEventsMutex; std::unordered_map> LinuxEvent::s_namedEvents; LinuxEvent::LinuxEvent(EventType type, bool initialState) : m_type(type), m_state(initialState) { m_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (m_fd == -1) { throw std::system_error(errno, std::system_category(), "eventfd creation failed"); } if (initialState) { SetEvent(); } } LinuxEvent::~LinuxEvent() { if (m_fd != -1) { close(m_fd); m_fd = -1; } // 从命名事件映射中移除(仅当有名称时) if (!m_name.empty()) { std::lock_guard lock(s_namedEventsMutex); s_namedEvents.erase(m_name); } } void LinuxEvent::SetEvent() { if (this == nullptr) { // 关键空指针检查 std::cerr << getLogPrefix() << "LinuxEvent::SetEvent called with NULL pointer! Possible invalid object or early destruction." << std::endl; return; // 避免继续执行导致崩溃 } std::lock_guard lock(m_mutex); std::cout << getLogPrefix() << "SetEvent: Lock acquired. Current state: " << m_state << std::endl; const uint64_t value = 1; ssize_t result = write(m_fd, &value, sizeof(value)); if (result == -1) { if (errno == EAGAIN) { std::cout << getLogPrefix() << "SetEvent: Write would block (EAGAIN). Eventfd counter full?" << std::endl; } else { std::cerr << getLogPrefix() << "SetEvent: WRITE FAILED! errno=" << errno << " (" << strerror(errno) << ")" << std::endl; throw std::system_error(errno, std::system_category(), "eventfd write failed"); } } else if (result != sizeof(value)) { std::cerr << getLogPrefix() << "SetEvent: PARTIAL WRITE! " << result << "/" << sizeof(value) << " bytes written" << std::endl; } else { std::cout << getLogPrefix() << "SetEvent: Successfully wrote event value=" << value << std::endl; } m_state = true; std::cout << getLogPrefix() << "SetEvent: State set to TRUE" << std::endl; } void LinuxEvent::ResetEvent() { std::lock_guard lock(m_mutex); uint64_t value; ssize_t bytesRead; // 清空所有事件计数 while (true) { bytesRead = read(m_fd, &value, sizeof(value)); if (bytesRead == sizeof(value)) { // 成功读取一个事件值 std::cout << "ResetEvent: consumed event value = " << value << std::endl; } else if (bytesRead == -1 && errno == EAGAIN) { // 没有更多数据可读 std::cout << "ResetEvent: eventfd drained" << std::endl; break; } else if (bytesRead == -1) { // 其他错误 std::cerr << "ResetEvent: read error, errno = " << errno << " (" << strerror(errno) << ")" << std::endl; break; } else { // 读取字节数异常(不应该发生) std::cerr << "ResetEvent: unexpected read size: " << bytesRead << std::endl; break; } } m_state = false; std::cout << "ResetEvent: state reset to false" << std::endl; } bool LinuxEvent::IsSet() const { std::lock_guard lock(m_mutex); return m_state; } int LinuxEvent::GetFD() const { return m_fd; } bool LinuxEvent::Wait(unsigned long timeoutMs) { std::cout << getLogPrefix() << "Wait: Entering. Timeout: " << (timeoutMs == static_cast(-1) ? "INFINITE" : std::to_string(timeoutMs) + "ms") << ", Current state: " << m_state << std::endl; int epollFd = epoll_create1(0); if (epollFd == -1) { std::cerr << getLogPrefix() << "Wait: epoll_create1 FAILED! errno=" << errno << " (" << strerror(errno) << ")" << std::endl; throw std::system_error(errno, std::system_category(), "epoll_create1 failed"); } std::cout << getLogPrefix() << "Wait: epoll instance created (fd=" << epollFd << ")" << std::endl; struct epoll_event ev; ev.events = EPOLLIN; ev.data.fd = m_fd; if (epoll_ctl(epollFd, EPOLL_CTL_ADD, m_fd, &ev) == -1) { std::cerr << getLogPrefix() << "Wait: epoll_ctl(ADD) FAILED! fd=" << m_fd << ", errno=" << errno << " (" << strerror(errno) << ")" << std::endl; close(epollFd); throw std::system_error(errno, std::system_category(), "epoll_ctl failed"); } std::cout << getLogPrefix() << "Wait: Added eventfd (fd=" << m_fd << ") to epoll instance" << std::endl; int ready = 0; struct epoll_event events[1]; int timeout = (timeoutMs == static_cast(-1)) ? -1 : static_cast(timeoutMs); std::cout << getLogPrefix() << "Wait: Blocking on epoll_wait (timeout=" << timeout << "ms)..." << std::endl; ready = epoll_wait(epollFd, events, 1, timeout); if (ready == -1) { std::cerr << getLogPrefix() << "Wait: epoll_wait FAILED! errno=" << errno << " (" << strerror(errno) << ")" << std::endl; } close(epollFd); std::cout << getLogPrefix() << "Wait: Closed epoll instance" << std::endl; if (ready > 0) { std::cout << getLogPrefix() << "Wait: EVENT SIGNALED! Ready FDs: " << ready << std::endl; if (m_type == AUTO_RESET) { uint64_t value; if (read(m_fd, &value, sizeof(value)) == -1 && errno != EAGAIN) { throw std::system_error(errno, std::system_category(), "eventfd read failed in Wait"); } m_state = false; } return true; } else if (ready == 0) { std::cout << getLogPrefix() << "Wait: TIMEOUT reached" << std::endl; } else { std::cerr << getLogPrefix() << "Wait: UNEXPECTED epoll_wait result: " << ready << std::endl; } return false; } int LinuxEvent::WaitForMultipleEvents(LinuxEvent** events, int count, unsigned long timeoutMs) { if (count <= 0) return -1; int epollFd = epoll_create1(0); if (epollFd == -1) { throw std::system_error(errno, std::system_category(), "epoll_create1 failed"); } // 添加所有事件到epoll for (int i = 0; i < count; i++) { struct epoll_event ev; ev.events = EPOLLIN; ev.data.u32 = i; // 存储事件索引 if (epoll_ctl(epollFd, EPOLL_CTL_ADD, events[i]->GetFD(), &ev) == -1) { close(epollFd); throw std::system_error(errno, std::system_category(), "epoll_ctl add failed"); } } // 等待事件 int maxEvents = std::min(count, 1024); std::vector epollEvents(maxEvents); int timeout = (timeoutMs == static_cast(-1)) ? -1 : static_cast(timeoutMs); int ready = epoll_wait(epollFd, epollEvents.data(), maxEvents, timeout); int result = -1; if (ready > 0) { // 找到索引最小的事件 int minIndex = count; for (int i = 0; i < ready; i++) { if (static_cast(epollEvents[i].data.u32) < minIndex) { minIndex = epollEvents[i].data.u32; } } result = minIndex; } // 清理 for (int i = 0; i < count; i++) { epoll_ctl(epollFd, EPOLL_CTL_DEL, events[i]->GetFD(), nullptr); } close(epollFd); return result; } int LinuxEvent::WaitForMultipleEvents(std::vector>& events, unsigned long timeoutMs) { int count = events.size(); if (count <= 0) return -1; int epollFd = epoll_create1(0); if (epollFd == -1) { throw std::system_error(errno, std::system_category(), "epoll_create1失败"); } // 添加所有事件到epoll for (int i = 0; i < count; i++) { struct epoll_event ev; ev.events = EPOLLIN; ev.data.u32 = i; // 存储事件索引 if (epoll_ctl(epollFd, EPOLL_CTL_ADD, events[i]->GetFD(), &ev) == -1) { close(epollFd); throw std::system_error(errno, std::system_category(), "epoll_ctl添加失败"); } } // 等待事件 int maxEvents = std::min(count, 1024); std::vector epollEvents(maxEvents); int timeout = (timeoutMs == static_cast(-1)) ? -1 : static_cast(timeoutMs); int ready = epoll_wait(epollFd, epollEvents.data(), maxEvents, timeout); int result = -1; if (ready > 0) { // 找到索引最小的事件 int minIndex = count; for (int i = 0; i < ready; i++) { if (static_cast(epollEvents[i].data.u32) < minIndex) { minIndex = epollEvents[i].data.u32; } } result = minIndex; } // 清理 for (int i = 0; i < count; i++) { epoll_ctl(epollFd, EPOLL_CTL_DEL, events[i]->GetFD(), nullptr); } close(epollFd); return result; } std::shared_ptr LinuxEvent::CreateEvent(EventType type, bool initialState, const char* name) { // 如果未提供名称或名称为空字符串,创建未命名事件 if (name == nullptr || *name == '\0') { return std::make_shared(type, initialState); } std::string eventName(name); std::lock_guard lock(s_namedEventsMutex); // 检查是否已存在同名事件 auto it = s_namedEvents.find(eventName); if (it != s_namedEvents.end()) { if (auto existing = it->second.lock()) { return existing; } } // 创建新命名事件 auto newEvent = std::make_shared(type, initialState); newEvent->m_name = eventName; s_namedEvents[eventName] = newEvent; return newEvent; } std::shared_ptr LinuxEvent::OpenEvent(const char* name, bool inheritHandle) { if (name == nullptr || *name == '\0') { throw std::invalid_argument("Invalid event name"); } CleanupNamedEvents(); std::string eventName(name); std::lock_guard lock(s_namedEventsMutex); auto it = s_namedEvents.find(eventName); if (it == s_namedEvents.end()) { return nullptr; // 未找到 } if (auto event = it->second.lock()) { return event; } // 弱引用已过期,从映射中移除 s_namedEvents.erase(it); return nullptr; } void LinuxEvent::CleanupNamedEvents() { std::lock_guard lock(s_namedEventsMutex); for (auto it = s_namedEvents.begin(); it != s_namedEvents.end(); ) { if (it->second.expired()) { it = s_namedEvents.erase(it); } else { ++it; } } }