From: Felix Domke Date: Thu, 5 Jan 2006 21:34:48 +0000 (+0000) Subject: make our event loop compatible to my new twisted reactor core X-Git-Tag: 2.6.0~4512 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/d026012d8ba6198d879df68cb4bf6c92c95a633a make our event loop compatible to my new twisted reactor core --- diff --git a/lib/base/ebase.cpp b/lib/base/ebase.cpp index fa5cff74..ffd35ece 100644 --- a/lib/base/ebase.cpp +++ b/lib/base/ebase.cpp @@ -121,11 +121,17 @@ void eMainloop::addSocketNotifier(eSocketNotifier *sn) void eMainloop::removeSocketNotifier(eSocketNotifier *sn) { - notifiers.erase(sn->getFD()); + for (std::multimap::iterator i = notifiers.find(sn->getFD()); + i != notifiers.end(); + ++i) + if (i->second == sn) + return notifiers.erase(i); + eFatal("removed socket notifier which is not present"); } -void eMainloop::processOneEvent() +int eMainloop::processOneEvent(unsigned int user_timeout) { + int return_reason = 0; /* get current time */ timeval now; gettimeofday(&now, 0); @@ -145,41 +151,69 @@ void eMainloop::processOneEvent() poll_timeout /= 1000; } + if ((user_timeout > 0) && (poll_timeout > user_timeout)) + { + poll_timeout = user_timeout; + return_reason = 1; + } + int ret = 0; - + if (poll_timeout) { + + std::multimap::iterator it; + std::map fd_merged; + std::map::const_iterator fd_merged_it; + + for (it = notifiers.begin(); it != notifiers.end(); ++it) + fd_merged[it->first] |= it->second->getRequested(); + + fd_merged_it = fd_merged.begin(); + + int fdcount = fd_merged.size(); + // 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++) + + for (int i=0; i < fdcount; i++, fd_merged_it++) { - pfd[i].fd = it->first; - pfd[i].events = it->second->getRequested(); + pfd[i].fd = fd_merged_it->first; + pfd[i].events = fd_merged_it->second; } ret = poll(pfd, fdcount, poll_timeout); - + /* ret > 0 means that there are some active poll entries. */ if (ret > 0) { + return_reason = 0; for (int i=0; i < fdcount ; i++) { - if (notifiers.find(pfd[i].fd) == notifiers.end()) - continue; + it = notifiers.begin(); + + int handled = 0; - int req = notifiers[pfd[i].fd]->getRequested(); + std::multimap::iterator + l = notifiers.lower_bound(pfd[i].fd), + u = notifiers.upper_bound(pfd[i].fd); - if (pfd[i].revents & req) + ePtrList n; + + for (; l != u; ++l) + n.push_back(l->second); + + for (ePtrList::iterator li(n.begin()); li != n.end(); ++li) { - notifiers[pfd[i].fd]->activate(pfd[i].revents); + int req = li->getRequested(); + + handled |= req; - 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 (pfd[i].revents & req) + (*li)->activate(pfd[i].revents); + } + if ((pfd[i].revents&~handled) & (POLLERR|POLLHUP|POLLNVAL)) + eFatal("poll: unhandled POLLERR/HUP/NVAL for fd %d(%d)", pfd[i].fd, pfd[i].revents); } ret = 1; /* poll did not timeout. */ @@ -189,7 +223,10 @@ void eMainloop::processOneEvent() if (errno != EINTR) eDebug("poll made error (%m)"); else + { + return_reason = 2; ret = -1; /* don't assume the timeout has passed when we got a signal */ + } } delete [] pfd; } @@ -205,12 +242,14 @@ void eMainloop::processOneEvent() /* 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; + return 0; /* 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(); } + + return return_reason; } void eMainloop::addTimer(eTimer* e) @@ -223,47 +262,29 @@ void eMainloop::removeTimer(eTimer* e) m_timer_list.remove(e); } -int eMainloop::exec() +int eMainloop::iterate(unsigned int user_timeout) { - if (!loop_level) - { - app_quit_now = false; - app_exit_loop = false; - enter_loop(); - } - return retval; -} - -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; - - if (!loop_level) - { - // do something here on exit the last loop - } + int ret = 0; + + do + { + if (app_quit_now) break; + ret = processOneEvent(user_timeout); + } while (ret == 0); + + return ret; } -void eMainloop::exit_loop() // call this to leave the current loop +int eMainloop::runLoop() { - app_exit_loop = true; + while (!app_quit_now) + iterate(); + return retval; } -void eMainloop::quit( int ret ) // call this to leave all loops +void eMainloop::quit(int ret) { - retval=ret; + retval = ret; app_quit_now = true; } diff --git a/lib/base/ebase.h b/lib/base/ebase.h index d4709418..fffe252f 100644 --- a/lib/base/ebase.h +++ b/lib/base/ebase.h @@ -16,6 +16,7 @@ class eApplication; extern eApplication* eApp; +#ifndef SWIG /* TODO: remove these inlines. */ static inline bool operator<( const timeval &t1, const timeval &t2 ) { @@ -123,6 +124,7 @@ static inline int timeval_to_usec(const timeval &t1) { return t1.tv_sec*1000000 + t1.tv_usec; } +#endif class eMainloop; @@ -138,11 +140,13 @@ class eSocketNotifier { public: enum { Read=POLLIN, Write=POLLOUT, Priority=POLLPRI, Error=POLLERR, Hungup=POLLHUP }; +#ifndef SWIG private: eMainloop &context; int fd; int state; int requested; // requested events (POLLIN, ...) +#endif public: /** * \brief Constructs a eSocketNotifier. @@ -171,18 +175,19 @@ class eTimer; // werden in einer mainloop verarbeitet class eMainloop { +#ifndef SWIG friend class eTimer; friend class eSocketNotifier; - std::map notifiers; + std::multimap notifiers; ePtrList m_timer_list; - bool app_exit_loop; bool app_quit_now; int loop_level; - void processOneEvent(); + int processOneEvent(unsigned int user_timeout); int retval; pthread_mutex_t recalcLock; int m_now_is_invalid; +#endif public: static void addTimeOffset(int offset); void addSocketNotifier(eSocketNotifier *sn); @@ -190,7 +195,10 @@ public: void addTimer(eTimer* e); void removeTimer(eTimer* e); +#ifndef SWIG static ePtrList existing_loops; +#endif + eMainloop() :app_quit_now(0),loop_level(0),retval(0) { @@ -205,11 +213,20 @@ public: } int looplevel() { return loop_level; } - /* OBSOLETE. DONT USE. */ - int exec(); // recursive enter the loop +#ifndef SWIG void quit(int ret=0); // leave all pending loops (recursive leave()) - void enter_loop(); - void exit_loop(); +#endif + + /* a user supplied timeout. enter_loop will return with: + 0 - no timeout, no signal + 1 - timeout + 2 - signal + */ + int iterate(unsigned int timeout=0); + + /* run will iterate endlessly until the app is quit, and return + the exit code */ + int runLoop(); }; /** @@ -240,12 +257,14 @@ public: */ class eTimer { +#ifndef SWIG friend class eMainloop; eMainloop &context; timeval nextActivation; long interval; bool bSingleShot; bool bActive; +#endif public: /** * \brief Constructs a timer. @@ -265,7 +284,9 @@ public: void start(long msec, bool b=false); void stop(); void changeInterval(long msek); +#ifndef SWIG bool operator<(const eTimer& t) const { return nextActivation < t.nextActivation; } +#endif void startLongTimer( int seconds ); void addTimeOffset(int); }; diff --git a/lib/dvb/epgcache.cpp b/lib/dvb/epgcache.cpp index 13b0bf2e..ec2c1172 100644 --- a/lib/dvb/epgcache.cpp +++ b/lib/dvb/epgcache.cpp @@ -623,7 +623,7 @@ void eEPGCache::thread() nice(4); load(); cleanLoop(); - exec(); + run(); save(); } diff --git a/lib/python/enigma_python.i b/lib/python/enigma_python.i index 54a5bcf3..16ca40cf 100644 --- a/lib/python/enigma_python.i +++ b/lib/python/enigma_python.i @@ -84,6 +84,7 @@ extern void runMainloop(); extern void quitMainloop(int exit_code); extern void setLCD(const char *c); extern void setLCDClock(const char *c); +extern eApplication *getApplication(); extern PSignal1 &keyPressedSignal(); %} @@ -124,6 +125,10 @@ typedef long time_t; %include %include %include + +%immutable eTimer::timeout; +%immutable eSocketNotifier::activated; +%include %include %include %include @@ -213,20 +218,6 @@ public: $1 = $input->get(); } -/************** base **************/ - -%immutable eTimer::timeout; - -class eTimer -{ -public: - eTimer(eMainloop *context = eApp); - PSignal0 timeout; - - void start(long msec, bool singleShot=false); - void stop(); - void changeInterval(long msek); -}; /************** debug **************/ @@ -234,6 +225,7 @@ void runMainloop(); void quitMainloop(int exit_code); void setLCD(const char*); void setLCDClock(const char*); +eApplication *getApplication(); %immutable keyPressed; PSignal1 &keyPressedSignal(); diff --git a/main/enigma.cpp b/main/enigma.cpp index 2003a452..a3770b86 100644 --- a/main/enigma.cpp +++ b/main/enigma.cpp @@ -236,8 +236,6 @@ int main(int argc, char **argv) python.execute("mytest", "__main__"); -// eApp->exec(); - return exit_code; } @@ -246,9 +244,14 @@ eWidgetDesktop *getDesktop() return wdsk; } +eApplication *getApplication() +{ + return eApp; +} + void runMainloop() { - exit_code = eApp->exec(); + exit_code = eApp->runLoop(); } void quitMainloop(int exitCode)