LinuxEvent.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #include "LinuxEvent.h"
  2. // 初始化静态成员
  3. std::mutex LinuxEvent::s_namedEventsMutex;
  4. std::unordered_map<std::string, std::weak_ptr<LinuxEvent>> LinuxEvent::s_namedEvents;
  5. std::atomic<uint64_t> LinuxEvent::s_objectCounter(0);
  6. std::string LinuxEvent::getCurrentTimestamp() const {
  7. auto now = std::chrono::system_clock::now();
  8. auto in_time_t = std::chrono::system_clock::to_time_t(now);
  9. auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
  10. now.time_since_epoch()) % 1000;
  11. std::stringstream ss;
  12. ss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %H:%M:%S")
  13. << '.' << std::setfill('0') << std::setw(3) << ms.count();
  14. return ss.str();
  15. }
  16. std::string LinuxEvent::getLogPrefix() const {
  17. std::stringstream ss;
  18. ss << "[" << getCurrentTimestamp() << "][Event#" << m_objectId;
  19. if (!m_name.empty()) ss << ":" << m_name;
  20. ss << "][FD:" << m_fd << "] ";
  21. return ss.str();
  22. }
  23. LinuxEvent::LinuxEvent(EventType type)
  24. : m_type(type), m_state(false),
  25. m_objectId(s_objectCounter.fetch_add(1, std::memory_order_relaxed)) {
  26. m_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
  27. if (m_fd == -1) {
  28. throw std::system_error(errno, std::system_category(), "eventfd creation failed");
  29. }
  30. }
  31. LinuxEvent::~LinuxEvent() {
  32. m_destructing.store(true);
  33. std::lock_guard<std::mutex> lock(m_mutex);
  34. if (m_fd != -1) {
  35. close(m_fd);
  36. m_fd = -1;
  37. }
  38. // 从命名事件映射中移除(仅当有名称时)
  39. if (!m_name.empty()) {
  40. std::lock_guard<std::mutex> lock(s_namedEventsMutex);
  41. auto it = s_namedEvents.find(m_name);
  42. if (it != s_namedEvents.end() && it->second.expired()) {
  43. s_namedEvents.erase(it);
  44. }
  45. }
  46. }
  47. void LinuxEvent::Initialize(bool initialState) {
  48. /*std::cout << getLogPrefix() << "Initialize. Initial state: "
  49. << initialState << std::endl;*/
  50. if (initialState) {
  51. // 直接操作 eventfd,不通过 SetEvent()
  52. const uint64_t value = 1;
  53. ssize_t result = write(m_fd, &value, sizeof(value));
  54. if (result != sizeof(value)) {
  55. throw std::system_error(errno, std::system_category(), "eventfd initial write failed");
  56. }
  57. m_state.store(true);
  58. }
  59. }
  60. void LinuxEvent::SetEvent() {
  61. if (this == nullptr) { // 关键空指针检查
  62. std::cerr << "[CRITICAL] SetEvent called with NULL pointer!" << std::endl;
  63. return;
  64. }
  65. auto self = shared_from_this();
  66. std::lock_guard<std::mutex> lock(m_mutex);
  67. // 检查析构状态
  68. if (m_destructing.load()) {
  69. std::cerr << getLogPrefix() << "SetEvent ABORTED: Object is being destroyed" << std::endl;
  70. return;
  71. }
  72. const uint64_t value = 1;
  73. ssize_t result = write(m_fd, &value, sizeof(value));
  74. if (result == -1 && errno != EAGAIN) {
  75. throw std::system_error(errno, std::system_category(), "eventfd write failed");
  76. }
  77. m_state.store(true);
  78. }
  79. void LinuxEvent::ResetEvent() {
  80. auto self = shared_from_this();
  81. std::lock_guard<std::mutex> lock(m_mutex);
  82. if (m_destructing.load()) {
  83. std::cerr << getLogPrefix() << "ResetEvent ABORTED: Object is being destroyed" << std::endl;
  84. return;
  85. }
  86. uint64_t value;
  87. while (read(m_fd, &value, sizeof(value)) == sizeof(value));
  88. m_state.store(false);
  89. }
  90. bool LinuxEvent::IsSet() const {
  91. std::lock_guard<std::mutex> lock(m_mutex);
  92. return m_state;
  93. }
  94. int LinuxEvent::GetFD() const {
  95. return m_fd;
  96. }
  97. bool LinuxEvent::Wait(unsigned long timeoutMs) {
  98. auto self = shared_from_this();
  99. if (m_destructing.load() || m_fd == -1) {
  100. return false;
  101. }
  102. struct pollfd pfd = { .fd = m_fd, .events = POLLIN };
  103. int timeout = (timeoutMs == static_cast<unsigned long>(-1)) ? -1 : static_cast<int>(timeoutMs);
  104. int ready, retry = 0;
  105. do {
  106. ready = poll(&pfd, 1, timeout);
  107. if (ready == -1 && errno == EINTR && retry < 5) {
  108. retry++;
  109. continue;
  110. }
  111. break;
  112. } while (true);
  113. if (ready <= 0) {
  114. return false; // 超时或错误
  115. }
  116. // 自动重置类型需要读取事件
  117. if (m_type == AUTO_RESET) {
  118. std::lock_guard<std::mutex> lock(m_mutex);
  119. uint64_t value;
  120. if (read(m_fd, &value, sizeof(value)) == sizeof(value)) {
  121. m_state.store(false);
  122. }
  123. }
  124. return true;
  125. }
  126. int LinuxEvent::WaitForMultipleEvents(LinuxEvent** events, int count, unsigned long timeoutMs) {
  127. if (count <= 0 || !events) return -1;
  128. // 使用智能指针管理动态数组
  129. auto pfds = std::make_unique<struct pollfd[]>(count);
  130. for (int i = 0; i < count; ++i) {
  131. if (!events[i]) return -1;
  132. pfds[i] = { .fd = events[i]->GetFD(), .events = POLLIN };
  133. }
  134. int timeout = (timeoutMs == static_cast<unsigned long>(-1)) ? -1 : static_cast<int>(timeoutMs);
  135. int ready = poll(pfds.get(), count, timeout);
  136. if (ready <= 0) return -1;
  137. // 返回第一个就绪的事件索引
  138. for (int i = 0; i < count; ++i) {
  139. if (pfds[i].revents & POLLIN) {
  140. if (events[i]->m_type == AUTO_RESET) {
  141. uint64_t value;
  142. read(events[i]->GetFD(), &value, sizeof(value)); // 重置事件
  143. events[i]->m_state.store(false);
  144. }
  145. return i;
  146. }
  147. }
  148. return -1;
  149. }
  150. int LinuxEvent::WaitForMultipleEvents(std::vector<std::shared_ptr<LinuxEvent>>& events, unsigned long timeoutMs) {
  151. int count = events.size();
  152. if (count <= 0) return -1;
  153. // 使用智能指针管理动态数组
  154. auto pfds = std::make_unique<struct pollfd[]>(count);
  155. for (int i = 0; i < count; ++i) {
  156. if (!events[i]) return -1;
  157. if (events[i]->m_destructing.load()) {
  158. return -1;
  159. }
  160. pfds[i] = { .fd = events[i]->GetFD(), .events = POLLIN };
  161. }
  162. int timeout = (timeoutMs == static_cast<unsigned long>(-1)) ? -1 : static_cast<int>(timeoutMs);
  163. int ready = poll(pfds.get(), count, timeout);
  164. if (ready <= 0) return -1;
  165. for (int i = 0; i < count; ++i) {
  166. if (pfds[i].revents & POLLIN) {
  167. if (events[i]->m_type == AUTO_RESET) {
  168. uint64_t value;
  169. read(events[i]->GetFD(), &value, sizeof(value)); // 重置事件
  170. std::lock_guard<std::mutex> lock(events[i]->m_mutex);
  171. events[i]->m_state.store(false);
  172. }
  173. return i;
  174. }
  175. }
  176. return -1;
  177. }
  178. std::shared_ptr<LinuxEvent> LinuxEvent::CreateEvent(EventType type, bool initialState, const char* name) {
  179. auto event = std::make_shared<LinuxEvent>(type);
  180. event->m_name = name ? name : "";
  181. event->Initialize(initialState);
  182. if (!event->m_name.empty()) {
  183. std::lock_guard<std::mutex> lock(s_namedEventsMutex);
  184. s_namedEvents[event->m_name] = event;
  185. }
  186. return event;
  187. }
  188. std::shared_ptr<LinuxEvent> LinuxEvent::OpenEvent(const char* name, bool inheritHandle) {
  189. if (name == nullptr || *name == '\0') {
  190. std::cerr << "OpenEvent: Invalid event name" << std::endl;
  191. throw std::invalid_argument("Invalid event name");
  192. }
  193. CleanupNamedEvents();
  194. std::string eventName(name);
  195. std::lock_guard<std::mutex> lock(s_namedEventsMutex);
  196. auto it = s_namedEvents.find(eventName);
  197. if (it == s_namedEvents.end()) {
  198. return nullptr; // 未找到
  199. }
  200. if (auto event = it->second.lock()) {
  201. return event;
  202. }
  203. // 弱引用已过期,从映射中移除
  204. s_namedEvents.erase(it);
  205. return nullptr;
  206. }
  207. void LinuxEvent::CleanupNamedEvents() {
  208. std::lock_guard<std::mutex> lock(s_namedEventsMutex);
  209. size_t count = 0;
  210. for (auto it = s_namedEvents.begin(); it != s_namedEvents.end(); ) {
  211. if (it->second.expired()) {
  212. it = s_namedEvents.erase(it);
  213. count++;
  214. } else {
  215. ++it;
  216. }
  217. }
  218. std::cout << "CleanupNamedEvents: Removed " << count << " expired events" << std::endl;
  219. }