bool EventLoop::stopping() { MSG msg; return Scheduler::stopping() && !PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) && nextTimer() == ~0ull; }
void EventLoop::onTimerInsertedAtFront() { unsigned long long next = nextTimer(); MORDOR_ASSERT(next != ~0ull); UINT uElapse = (UINT)((next / 1000) + 1); uElapse = std::max<UINT>(USER_TIMER_MINIMUM, uElapse); uElapse = std::min<UINT>(USER_TIMER_MAXIMUM, uElapse); if (!SetTimer(m_messageWindow, 1, uElapse, NULL)) MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("SetTimer"); }
bool IOManagerEPoll::stopping(unsigned long long &nextTimeout) { nextTimeout = nextTimer(); if (nextTimeout == ~0ull && Scheduler::stopping()) { boost::mutex::scoped_lock lock(m_mutex); if (m_pendingEvents.empty()) { return true; } } return false; }
void EventsManager::pollEvents(bool skipTimers) { if (checkForNextFrameCounter()) { nextFrame(); } if (checkForNextTimerUpdate() && !skipTimers) nextTimer(); _vm->_sound->checkSoundQueue(); _wheelUp = _wheelDown = false; Common::Event event; while (g_system->getEventManager()->pollEvent(event)) { switch (event.type) { case Common::EVENT_QUIT: case Common::EVENT_RTL: return; case Common::EVENT_KEYDOWN: // Check for debugger if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL)) { // Attach to the debugger _vm->_debugger->attach(); _vm->_debugger->onFrame(); } else { keyControl(event.kbd.keycode, true); } return; case Common::EVENT_KEYUP: keyControl(event.kbd.keycode, false); return; case Common::EVENT_MOUSEMOVE: _mousePos = event.mouse; _mouseCol = _mousePos.x / 8; _mouseRow = _mousePos.y / 8; break; case Common::EVENT_LBUTTONDOWN: _leftButton = true; return; case Common::EVENT_LBUTTONUP: _leftButton = false; return; case Common::EVENT_RBUTTONDOWN: _rightButton = true; return; case Common::EVENT_RBUTTONUP: _rightButton = false; return; case Common::EVENT_MBUTTONDOWN: _middleButton = true; return; case Common::EVENT_MBUTTONUP: _middleButton = false; return; case Common::EVENT_WHEELUP: _wheelUp = true; return; case Common::EVENT_WHEELDOWN: _wheelDown = true; return; default: break; } } }
void IOManagerEPoll::idle() { epoll_event events[64]; while (true) { unsigned long long nextTimeout; if (stopping(nextTimeout)) return; int rc = -1; errno = EINTR; while (rc < 0 && errno == EINTR) { int timeout = -1; if (nextTimeout != ~0ull) timeout = (int)(nextTimeout / 1000) + 1; rc = epoll_wait(m_epfd, events, 64, timeout); if (rc < 0 && errno == EINTR) nextTimeout = nextTimer(); } MORDOR_LOG_LEVEL(g_log, rc < 0 ? Log::ERROR : Log::VERBOSE) << this << " epoll_wait(" << m_epfd << "): " << rc << " (" << errno << ")"; if (rc < 0) MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("epoll_wait"); std::vector<boost::function<void ()> > expired = processTimers(); schedule(expired.begin(), expired.end()); for(int i = 0; i < rc; ++i) { epoll_event &event = events[i]; if (event.data.fd == m_tickleFds[0]) { unsigned char dummy; int rc2 = read(m_tickleFds[0], &dummy, 1); MORDOR_VERIFY(rc2 == 1); MORDOR_LOG_VERBOSE(g_log) << this << " received tickle"; continue; } bool err = event.events & (EPOLLERR | EPOLLHUP); boost::mutex::scoped_lock lock(m_mutex); std::map<int, AsyncEvent>::iterator it = m_pendingEvents.find(event.data.fd); if (it == m_pendingEvents.end()) continue; AsyncEvent &e = it->second; MORDOR_LOG_TRACE(g_log) << " epoll_event {" << (epoll_events_t)event.events << ", " << event.data.fd << "}, registered for " << (epoll_events_t)e.event.events; if ((event.events & EPOLLERR) && (e.event.events & EPOLLERR)) { if (e.m_dgError) e.m_schedulerError->schedule(e.m_dgError); else e.m_schedulerError->schedule(e.m_fiberError); // Block other events from firing e.m_dgError = NULL; e.m_fiberError.reset(); e.m_dgIn = NULL; e.m_fiberIn.reset(); e.m_dgOut = NULL; e.m_fiberOut.reset(); event.events = 0; e.event.events = 0; } if ((event.events & EPOLLHUP) && (e.event.events & EPOLLHUP)) { if (e.m_dgClose) e.m_schedulerError->schedule(e.m_dgClose); else e.m_schedulerError->schedule(e.m_fiberClose); // Block write event from firing e.m_dgOut = NULL; e.m_fiberOut.reset(); e.m_dgClose = NULL; e.m_fiberClose.reset(); event.events &= EPOLLOUT; e.event.events &= EPOLLOUT; err = false; } if (((event.events & EPOLLIN) || err) && (e.event.events & EPOLLIN)) { if (e.m_dgIn) e.m_schedulerIn->schedule(e.m_dgIn); else e.m_schedulerIn->schedule(e.m_fiberIn); e.m_dgIn = NULL; e.m_fiberIn.reset(); event.events |= EPOLLIN; } if (((event.events & EPOLLOUT) || err) && (e.event.events & EPOLLOUT)) { if (e.m_dgOut) e.m_schedulerOut->schedule(e.m_dgOut); else e.m_schedulerOut->schedule(e.m_fiberOut); e.m_dgOut = NULL; e.m_fiberOut.reset(); event.events |= EPOLLOUT; } e.event.events &= ~event.events; int op = e.event.events == 0 ? EPOLL_CTL_DEL : EPOLL_CTL_MOD; int rc2 = epoll_ctl(m_epfd, op, event.data.fd, &e.event); MORDOR_LOG_LEVEL(g_log, rc2 ? Log::ERROR : Log::VERBOSE) << this << " epoll_ctl(" << m_epfd << ", " << (epoll_ctl_op_t)op << ", " << event.data.fd << ", " << (epoll_events_t)e.event.events << "): " << rc2 << " (" << errno << ")"; if (rc2) MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("epoll_ctl"); if (op == EPOLL_CTL_DEL) m_pendingEvents.erase(it); } Fiber::yield(); } }