X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/9202d4248dd7df2f6e5eb53b4154c8297ec9b1d1..6dbbf2167e1a8ca25dd2cd8e20bef82686b28f61:/lib/base/ebase.cpp diff --git a/lib/base/ebase.cpp b/lib/base/ebase.cpp index b62452d4..7951f6e7 100644 --- a/lib/base/ebase.cpp +++ b/lib/base/ebase.cpp @@ -5,6 +5,7 @@ #include #include +#include eSocketNotifier::eSocketNotifier(eMainloop *context, int fd, int requested, bool startnow): context(*context), fd(fd), state(0), requested(requested) { @@ -43,16 +44,30 @@ void eTimer::start(long msek, bool singleShot) bActive = true; bSingleShot = singleShot; interval = msek; - gettimeofday(&nextActivation, 0); -// eDebug("this = %p\nnow sec = %d, usec = %d\nadd %d msec", this, nextActivation.tv_sec, nextActivation.tv_usec, 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); +// eDebug("next Activation sec = %d, usec = %d", nextActivation.tv_sec, nextActivation.tv_usec ); + context.addTimer(this); +} + +void eTimer::startLongTimer( int seconds ) +{ + if (bActive) + stop(); + + 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); + if ( seconds > 0 ) + nextActivation.tv_sec += seconds; // eDebug("next Activation sec = %d, usec = %d", nextActivation.tv_sec, nextActivation.tv_usec ); context.addTimer(this); } void eTimer::stop() -{ - eDebug("stop timer"); +{ if (bActive) { bActive=false; @@ -68,7 +83,7 @@ void eTimer::changeInterval(long msek) nextActivation -= interval; // sub old interval } else - bActive=true; // then activate Timer + bActive=true; // then activate Timer interval = msek; // set new Interval nextActivation += interval; // calc nextActivation @@ -76,12 +91,8 @@ void eTimer::changeInterval(long msek) context.addTimer(this); // add Timer to context TimerList } -void eTimer::activate() // Internal Function... called from eApplication +void eTimer::activate() // Internal Funktion... called from eApplication { - timeval now; - gettimeofday(&now, 0); -// eDebug("this = %p\nnow sec = %d, usec = %d\nnextActivation sec = %d, usec = %d", this, now.tv_sec, now.tv_usec, nextActivation.tv_sec, nextActivation.tv_usec ); -// eDebug("Timer emitted"); context.removeTimer(this); if (!bSingleShot) @@ -95,7 +106,13 @@ void eTimer::activate() // Internal Function... called from eApplication /*emit*/ timeout(); } +void eTimer::addTimeOffset( int offset ) +{ + nextActivation.tv_sec += offset; +} + // mainloop +ePtrList eMainloop::existing_loops; void eMainloop::addSocketNotifier(eSocketNotifier *sn) { @@ -116,124 +133,153 @@ void eMainloop::processOneEvent() 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 */ - // first, process pending timers... - long usec=0; - - while (TimerList && (usec = timeout_usec( TimerList.begin()->getNextActivation() ) ) <= 0 ) - TimerList.begin()->activate(); - - // build the poll aray - int fdAnz = notifiers.size(); - pollfd* pfd = new pollfd[fdAnz]; // make new pollfd array - - std::map::iterator it(notifiers.begin()); - for (int i=0; i < fdAnz; i++, it++) + /* get current time */ + timeval now; + gettimeofday(&now, 0); + + int poll_timeout = -1; /* infinite in case of empty timer list */ + + if (m_timer_list) { - pfd[i].fd = it->first; - pfd[i].events = it->second->getRequested(); + 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) + poll_timeout = 0; + + /* convert us to ms */ + poll_timeout /= 1000; } + + int ret = 0; - // to the poll. When there are no timers, we have an infinite timeout - int ret=poll(pfd, fdAnz, TimerList ? usec / 1000 : -1); // convert to us - - if (ret>0) + if (poll_timeout) { - for (int i=0; i < fdAnz ; i++) + // build the poll aray + int fdcount = notifiers.size(); + pollfd* pfd = new pollfd[fdcount]; // make new pollfd array + + std::map::iterator it(notifiers.begin()); + for (int i=0; i < fdcount; i++, it++) { - if( notifiers.find(pfd[i].fd) == notifiers.end()) - continue; + pfd[i].fd = it->first; + pfd[i].events = it->second->getRequested(); + } - int req = notifiers[pfd[i].fd]->getRequested(); + ret = poll(pfd, fdcount, poll_timeout); - if ( pfd[i].revents & req ) + /* ret > 0 means that there are some active poll entries. */ + if (ret > 0) + { + for (int i=0; i < fdcount ; i++) { - notifiers[pfd[i].fd]->activate(pfd[i].revents); - - if (!--ret) - break; - } 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); + if (notifiers.find(pfd[i].fd) == notifiers.end()) + continue; + + int req = notifiers[pfd[i].fd]->getRequested(); + + if (pfd[i].revents & req) + { + notifiers[pfd[i].fd]->activate(pfd[i].revents); + + if (!--ret) + break; + } 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); + } + } else if (ret < 0) + { + /* when we got a signal, we get EINTR. we do not care, + because we check current time in timers anyway. */ + if (errno != EINTR) + eDebug("poll made error (%m)"); + else + ret = 0; } - } else if (ret<0) + delete [] pfd; + } + + /* when we not processed anything, check timers. */ + if (!ret) { - /* when we got a signal, we get EINTR. we do not care, - because we check current time in timers anyway. */ - if (errno != EINTR) - eDebug("poll made error (%m)"); - } + singleLock s(recalcLock); - // check timer... - while ( TimerList && timeout_usec( TimerList.begin()->getNextActivation() ) <= 0 ) - TimerList.begin()->activate(); + /* process all timers which are ready. first remove them out of the list. */ + while ((!m_timer_list.empty()) && (m_timer_list.begin()->getNextActivation() < now)) + m_timer_list.begin()->activate(); + } +} - delete [] pfd; +void eMainloop::addTimer(eTimer* e) +{ + m_timer_list.insert_in_order(e); } +void eMainloop::removeTimer(eTimer* e) +{ + m_timer_list.remove(e); +} int eMainloop::exec() { if (!loop_level) { app_quit_now = false; + app_exit_loop = false; enter_loop(); } return retval; } - /* use with care! better: don't use it anymore. it was used for gui stuff, but - doesn't allow multiple paths (or active dialogs, if you want it that way.) */ void eMainloop::enter_loop() { loop_level++; - // Status der vorhandenen Loop merken bool old_exit_loop = app_exit_loop; - + app_exit_loop = false; while (!app_exit_loop && !app_quit_now) - { processOneEvent(); - } // wiederherstellen der vorherigen app_exit_loop app_exit_loop = old_exit_loop; - loop_level--; + --loop_level; if (!loop_level) { - // do something here on exit the last loop + // do something here on exit the last loop } } void eMainloop::exit_loop() // call this to leave the current loop { - app_exit_loop = true; + app_exit_loop = true; } void eMainloop::quit( int ret ) // call this to leave all loops @@ -242,4 +288,15 @@ void eMainloop::quit( int ret ) // call this to leave all loops app_quit_now = true; } +void eMainloop::addTimeOffset(int offset) +{ + for (ePtrList::iterator it(eMainloop::existing_loops) + ;it != eMainloop::existing_loops.end(); ++it) + { + singleLock s(it->recalcLock); + for (ePtrList::iterator tit = it->m_timer_list.begin(); tit != it->m_timer_list.end(); ++tit ) + tit->addTimeOffset(offset); + } +} + eApplication* eApp = 0;