1 #include <lib/base/ebase.h>
7 #include <lib/base/eerror.h>
8 #include <lib/base/elock.h>
10 eSocketNotifier::eSocketNotifier(eMainloop *context, int fd, int requested, bool startnow): context(*context), fd(fd), state(0), requested(requested)
16 eSocketNotifier::~eSocketNotifier()
21 void eSocketNotifier::start()
26 context.addSocketNotifier(this);
30 void eSocketNotifier::stop()
33 context.removeSocketNotifier(this);
39 void eTimer::start(long msek, bool singleShot)
45 bSingleShot = singleShot;
47 gettimeofday(&nextActivation, 0);
48 nextActivation.tv_sec -= context.getTimerOffset();
49 nextActivation += (msek<0 ? 0 : msek);
50 // eDebug("this = %p\nnow sec = %d, usec = %d\nadd %d msec", this, nextActivation.tv_sec, nextActivation.tv_usec, msek);
51 // eDebug("next Activation sec = %d, usec = %d", nextActivation.tv_sec, nextActivation.tv_usec );
52 context.addTimer(this);
55 void eTimer::startLongTimer( int seconds )
60 bActive = bSingleShot = true;
62 gettimeofday(&nextActivation, 0);
63 nextActivation.tv_sec -= context.getTimerOffset();
64 // eDebug("this = %p\nnow sec = %d, usec = %d\nadd %d msec", this, nextActivation.tv_sec, nextActivation.tv_usec, msek);
66 nextActivation.tv_sec += seconds;
67 // eDebug("next Activation sec = %d, usec = %d", nextActivation.tv_sec, nextActivation.tv_usec );
68 context.addTimer(this);
76 context.removeTimer(this);
80 void eTimer::changeInterval(long msek)
82 if (bActive) // Timer is running?
84 context.removeTimer(this); // then stop
85 nextActivation -= interval; // sub old interval
88 bActive=true; // then activate Timer
90 interval = msek; // set new Interval
91 nextActivation += interval; // calc nextActivation
93 context.addTimer(this); // add Timer to context TimerList
96 void eTimer::activate() // Internal Funktion... called from eApplication
98 context.removeTimer(this);
102 nextActivation += interval;
103 context.addTimer(this);
111 inline void eTimer::recalc( int offset )
113 nextActivation.tv_sec += offset;
117 ePtrList<eMainloop> eMainloop::existing_loops;
119 void eMainloop::setTimerOffset( int difference )
121 singleLock s(recalcLock);
127 eDebug("time_offset %d avail.. add new offset %d than new is %d",
128 timer_offset, difference, timer_offset+difference);
129 timer_offset+=difference;
133 void eMainloop::addSocketNotifier(eSocketNotifier *sn)
135 notifiers.insert(std::pair<int,eSocketNotifier*> (sn->getFD(), sn));
138 void eMainloop::removeSocketNotifier(eSocketNotifier *sn)
140 notifiers.erase(sn->getFD());
143 void eMainloop::processOneEvent()
146 - we should use epoll(4)
147 - timer are checked twice. there was a strong reason for it, but i can't remember. (FIXME)
148 - for each time, we gettimeofday() and check wether the timer should fire.
149 we should do this all better - we know how long the poll last, so we know which
150 timers should fire. Problem is that a timer handler could have required so
151 much time that another timer fired.
153 A probably structure could look
157 time = gettimeofday()
158 timeout = calculate_pending_timers(time);
160 doPoll(timeout or infinite);
162 if (poll_had_results)
163 handle_poll_handler();
165 fire_timers(time + timeout)
168 the gettimeofday() call is required because fire_timers could last more
171 when poll did no timeout, we don't handle timers, as this will be done
172 in the next iteration (without adding overhead - we had to get the new
176 // first, process pending timers...
181 while (TimerList && (usec = timeout_usec( TimerList.begin()->getNextActivation() ) ) <= 0 )
183 TimerList.begin()->activate();
187 int fdAnz = notifiers.size();
191 std::map<int,eSocketNotifier*>::iterator it(notifiers.begin());
192 for (int i=0; i < fdAnz; i++, it++)
194 pfd[i].fd = it->first;
195 pfd[i].events = it->second->getRequested();
198 // to the poll. When there are no timers, we have an infinite timeout
199 int ret=poll(pfd, fdAnz, TimerList ? usec / 1000 : -1); // convert to ms
203 // eDebug("bin aussem poll raus und da war was");
204 for (int i=0; i < fdAnz ; i++)
206 if( notifiers.find(pfd[i].fd) == notifiers.end())
209 int req = notifiers[pfd[i].fd]->getRequested();
211 if ( pfd[i].revents & req )
213 notifiers[pfd[i].fd]->activate(pfd[i].revents);
217 else if (pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL))
218 eDebug("poll: unhandled POLLERR/HUP/NVAL for fd %d(%d)", pfd[i].fd,pfd[i].revents);
223 /* when we got a signal, we get EINTR. we do not care,
224 because we check current time in timers anyway. */
226 eDebug("poll made error");
230 int eMainloop::exec()
234 app_quit_now = false;
235 app_exit_loop = false;
241 void eMainloop::enter_loop()
244 // Status der vorhandenen Loop merken
245 bool old_exit_loop = app_exit_loop;
247 app_exit_loop = false;
249 while (!app_exit_loop && !app_quit_now)
252 // wiederherstellen der vorherigen app_exit_loop
253 app_exit_loop = old_exit_loop;
259 // do something here on exit the last loop
263 void eMainloop::exit_loop() // call this to leave the current loop
265 app_exit_loop = true;
268 void eMainloop::quit( int ret ) // call this to leave all loops
274 inline void eMainloop::doRecalcTimers()
276 singleLock s(recalcLock);
279 for (ePtrList<eTimer>::iterator it(TimerList); it != TimerList.end(); ++it )
280 it->recalc( timer_offset );
285 eApplication* eApp = 0;