int MainLoop::run() { while (m_epoll != -1 && (m_monitors.size() != 0 || m_timers.size() != 0)) { // Get desired timeout int timeout = -1; TimerMap::const_iterator timer = m_timers.begin(); if (timer != m_timers.end()) { timeout = timer->second->timeout(); } // Wait for events epoll_event events[32]; int count = ::epoll_wait(m_epoll, events, sizeof(events) / sizeof(events[0]), timeout); if (count == -1 && errno == EINTR) continue; if (count == -1) break; #ifdef MAINLOOP_THREADS std::unique_lock<std::mutex> lock(m_mutex); #endif // MAINLOOP_THREADS // Handle events for (int i = 0; i != count; ++i) { auto it = m_monitors.find(events[i].data.fd); if (it == m_monitors.end()) continue; Monitor *monitor = it->second; if (monitor->callback) { Direction dir; switch (events[i].events & (EPOLLIN|EPOLLOUT)) { case EPOLLIN: dir = In; break; case EPOLLOUT: dir = Out; break; case EPOLLIN | EPOLLOUT: dir = InOut; break; default: dir = Error; } #ifdef MAINLOOP_THREADS lock.unlock(); #endif // MAINLOOP_THREADS monitor->callback(dir); #ifdef MAINLOOP_THREADS lock.lock(); #endif // MAINLOOP_THREADS } } // Handle expired timers unsigned long long int t = Timer::currentTime(); for (TimerMap::iterator it = m_timers.begin(); it != m_timers.end() && it->first <= t; it = m_timers.begin()) { Timer *timer = it->second; m_timers.erase(it); #ifdef MAINLOOP_THREADS lock.unlock(); #endif // MAINLOOP_THREADS timer->callback()(); #ifdef MAINLOOP_THREADS lock.lock(); #endif // MAIN_LOOP_THREADS } } return m_exitCode; }