X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/3392a6ecccfe92d342eebe58736d9e33f8332943..9fac5ff7371972cef663d456b96c68f51b5c2c01:/lib/base/ebase.cpp diff --git a/lib/base/ebase.cpp b/lib/base/ebase.cpp index 2ad023b9..fa5cff74 100644 --- a/lib/base/ebase.cpp +++ b/lib/base/ebase.cpp @@ -45,8 +45,8 @@ void eTimer::start(long msek, bool singleShot) bSingleShot = singleShot; interval = msek; gettimeofday(&nextActivation, 0); - nextActivation += (msek<0 ? 0 : msek); // eDebug("this = %p\nnow sec = %d, usec = %d\nadd %d msec", this, nextActivation.tv_sec, nextActivation.tv_usec, msek); + nextActivation += (msek<0 ? 0 : msek); // eDebug("next Activation sec = %d, usec = %d", nextActivation.tv_sec, nextActivation.tv_usec ); context.addTimer(this); } @@ -59,7 +59,7 @@ void eTimer::startLongTimer( int seconds ) bActive = bSingleShot = true; interval = 0; gettimeofday(&nextActivation, 0); -// eDebug("this = %p\nnow sec = %d, usec = %d\nadd %d msec", this, nextActivation.tv_sec, nextActivation.tv_usec, msek); +// eDebug("this = %p\nnow sec = %d, usec = %d\nadd %d sec", this, nextActivation.tv_sec, nextActivation.tv_usec, seconds); if ( seconds > 0 ) nextActivation.tv_sec += seconds; // eDebug("next Activation sec = %d, usec = %d", nextActivation.tv_sec, nextActivation.tv_usec ); @@ -126,45 +126,16 @@ void eMainloop::removeSocketNotifier(eSocketNotifier *sn) void eMainloop::processOneEvent() { - /* notes: - - we should use epoll(4) - - timer are checked twice. there was a strong reason for it, but i can't remember. (FIXME) - - for each time, we gettimeofday() and check wether the timer should fire. - we should do this all better - we know how long the poll last, so we know which - timers should fire. Problem is that a timer handler could have required so - much time that another timer fired. - - A probably structure could look - - while (1) - { - time = gettimeofday() - timeout = calculate_pending_timers(time); - - doPoll(timeout or infinite); - - if (poll_had_results) - handle_poll_handler(); - else - fire_timers(time + timeout) - } - - the gettimeofday() call is required because fire_timers could last more - than nothing. - - when poll did no timeout, we don't handle timers, as this will be done - in the next iteration (without adding overhead - we had to get the new - time anyway - */ - /* get current time */ timeval now; gettimeofday(&now, 0); + m_now_is_invalid = 0; int poll_timeout = -1; /* infinite in case of empty timer list */ if (m_timer_list) { + singleLock s(recalcLock); poll_timeout = timeval_to_usec(m_timer_list.begin()->getNextActivation() - now); /* if current timer already passed, don't delay infinite. */ if (poll_timeout < 0) @@ -210,14 +181,15 @@ void eMainloop::processOneEvent() } else if (pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) eFatal("poll: unhandled POLLERR/HUP/NVAL for fd %d(%d) -> FIX YOUR CODE", pfd[i].fd,pfd[i].revents); } + + ret = 1; /* poll did not timeout. */ } else if (ret < 0) { - /* when we got a signal, we get EINTR. we do not care, - because we check current time in timers anyway. */ + /* when we got a signal, we get EINTR. */ if (errno != EINTR) eDebug("poll made error (%m)"); else - ret = 0; + ret = -1; /* don't assume the timeout has passed when we got a signal */ } delete [] pfd; } @@ -225,8 +197,18 @@ void eMainloop::processOneEvent() /* when we not processed anything, check timers. */ if (!ret) { + /* we know that this time has passed. */ + now += poll_timeout; + + singleLock s(recalcLock); + + /* this will never change while we have the recalcLock */ + /* we can savely return here, the timer will be re-checked soon. */ + if (m_now_is_invalid) + return; + /* process all timers which are ready. first remove them out of the list. */ - while ((!m_timer_list.empty()) && (m_timer_list.begin()->getNextActivation() < now)) + while ((!m_timer_list.empty()) && (m_timer_list.begin()->getNextActivation() <= now)) m_timer_list.begin()->activate(); } } @@ -287,9 +269,14 @@ void eMainloop::quit( int ret ) // call this to leave all loops void eMainloop::addTimeOffset(int offset) { - singleLock s(recalcLock); - for (ePtrList::iterator it(m_timer_list); it != m_timer_list.end(); ++it ) - it->addTimeOffset(offset); + for (ePtrList::iterator it(eMainloop::existing_loops) + ;it != eMainloop::existing_loops.end(); ++it) + { + singleLock s(it->recalcLock); + it->m_now_is_invalid = 1; + for (ePtrList::iterator tit = it->m_timer_list.begin(); tit != it->m_timer_list.end(); ++tit ) + tit->addTimeOffset(offset); + } } eApplication* eApp = 0;