// EventLoop.cpp - 事件循环实现 #include "pch.h" #include "EventLoop.h" #include "Logger.h" namespace commkit { EventLoop::EventLoop() {} EventLoop::~EventLoop() { Stop(); } bool EventLoop::Start(HANDLE driver_handle, TOnData callback) { if (running_.load()) { return true; } if (driver_handle == INVALID_HANDLE_VALUE || !callback) { LOG_ERROR("EventLoop::Start invalid args"); return false; } driver_handle_ = driver_handle; callback_ = callback; running_.store(true); try { thread_ = std::thread(&EventLoop::Run, this); } catch (const std::exception& e) { LOG_ERROR(std::string("EventLoop thread create failed: ") + e.what()); running_.store(false); return false; } LOG_INFO("EventLoop started"); return true; } void EventLoop::Stop() { if (!running_.exchange(false)) { return; } // 关闭驱动句柄会阻塞的 ReadEvents 立即返回错误 // 此处仅设置标志,由 Run() 循环自行退出 // 注意:不能在此处 CloseHandle(driver_handle_),因为 Run() 可能正在使用 if (thread_.joinable()) { thread_.join(); } LOG_INFO("EventLoop stopped"); } void EventLoop::Run() { // 批量读取缓冲区:单次最多 COMMKIT_EVENT_BATCH 条事件 COMMKIT_EVENT batch[COMMKIT_EVENT_BATCH]; while (running_.load()) { DWORD returned = 0; // 阻塞式 IOCTL:驱动在无事件时会让 IRP pending // 当驱动有事件或被取消时返回 BOOL ok = DeviceIoControl( driver_handle_, IOCTL_COMMKIT_READ_EVENTS, nullptr, 0, batch, sizeof(batch), &returned, nullptr); if (!running_.load()) { break; } if (!ok) { DWORD err = ::GetLastError(); // 驱动关闭或句柄无效时退出循环 if (err == ERROR_INVALID_HANDLE || err == ERROR_OPERATION_ABORTED) { LOG_WARNING("EventLoop Run: driver handle closed, exiting"); break; } // 其他错误:短暂 sleep 后重试,避免空转 LOG_ERROR("EventLoop Run: DeviceIoControl failed, error=" + std::to_string(err)); std::this_thread::sleep_for(std::chrono::milliseconds(50)); continue; } // 处理返回的事件 DWORD count = returned / sizeof(COMMKIT_EVENT); for (DWORD i = 0; i < count; ++i) { const COMMKIT_EVENT& e = batch[i]; if (callback_) { // 调用用户注册的回调 // TimeStamp 是 100ns 单位,转换为 double(用户可根据需要自行处理) double timestamp = static_cast(e.TimeStamp); callback_(e.Sequence, timestamp, e.ComNumber, e.EventType, e.DataSize, const_cast(e.Data)); } } // 无事件时短暂 sleep,避免忙循环占满 CPU(驱动当前实现是立即返回而非 pending IRP) if (count == 0) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); } } } } // namespace commkit