Brief description of class still missing. More...
#include <EventLoop.h>
Public Member Functions | |
void | addEvent (Event *event) |
void | addStream (Stream *s) |
Timer::QueueItem * | addTimer (Timer *t) |
EventLoop () | |
void | exec () |
bool | isTerminated () const |
void | terminate () |
~EventLoop () | |
Static Public Member Functions | |
static EventLoop * | instance () |
static EventLoop * | mainInstance () |
Brief description of class still missing.
Full description of class still missing
Description of constructor still missing
References addStream(), GpCoreTools::PThread::currentThread(), GpCoreTools::PThread::setEventLoop(), and TRACE.
{ TRACE; PThread * t=PThread::currentThread(); if(t) { t->setEventLoop(this); } else { assert(!_mainLoop); _mainLoop=this; } // A way to force poll() to exit immediately _eventStream=new EventStream; addStream(_eventStream); _terminate=false; }
void GpCoreTools::EventLoop::addEvent | ( | Event * | event | ) | [inline] |
Referenced by GpCoreTools::EventStream::event().
{_events.push(event);}
void GpCoreTools::EventLoop::addStream | ( | Stream * | s | ) | [inline] |
Referenced by GpCoreTools::UnixServerStream::event(), GpCoreTools::TcpServerStream::event(), EventLoop(), and main().
{_streams.push_back(s);}
Timer::QueueItem * GpCoreTools::EventLoop::addTimer | ( | Timer * | t | ) |
References GpCoreTools::EventStream::send().
Referenced by exec(), and GpCoreTools::Timer::start().
void GpCoreTools::EventLoop::exec | ( | ) |
References addTimer(), GpCoreTools::Stream::eventTypes(), GpCoreTools::Stream::fileDescriptor(), TRACE, and GpCoreTools::Log::write().
Referenced by main().
{ TRACE; _terminate=false; Log::write(1, "start event loop\n"); // Init pollfd vector pollfd * pfds=(pollfd *)malloc((_streams.size())*sizeof(pollfd)); for(int i=_streams.size()-1;i>=0;i--) { pollfd& pfd=pfds[i]; Stream& s=*_streams.at(i); pfd.fd=s.fileDescriptor(); pfd.events=s.eventTypes(); //Log::write(8, "create stream %i events %x (POLLIN=%i, POLLPRI=%i)\n", i, pfd.events, POLLIN, POLLPRI); } // Main loop while(!_terminate) { // Calculate next timeout Timer::QueueItem * nextTimer=0; int timeout; if(_timers.size()==0) { timeout=-1; } else { while(!nextTimer && _timers.size()>0) { nextTimer=_timers.back(); if(!nextTimer->timer()) { // Get rid of stopped timers _timers.pop_back(); delete nextTimer; nextTimer=0; } } if(nextTimer) { timeout=nextTimer->timer()->timeout(); } else { timeout=-1; } } // Wait for next event or timeout unsigned int n=_streams.size(); //Log::write(6, "enter poll %i streams timeout %i\n", n, timeout); int nfd=poll(pfds, n, timeout); //Log::write(6, "exit poll %i\n", nfd); if(nfd==-1) { if(errno!=EINTR) { Log::write(0, "%s\n", strerror(errno)); } Log::write(1, "stop event loop\n"); return; } // Process next timer if(nextTimer && nextTimer->timer()) { if(nextTimer->timer()->timeout()==0) { _timers.pop_back(); if(nextTimer->timer()->exec() && nextTimer->timer()) { addTimer(nextTimer); } else { delete nextTimer; } } } // Process data exchange on fds if(nfd>0) { for(unsigned int i=0;i<n;i++) { _streams.at(i)->event(pfds[i].revents); } } // Process event queue while(!_events.empty()) { Event * event=_events.front(); event->exec(); delete event; _events.pop(); } // Update pollfd vector for new streams if(_streams.size()>n) { unsigned int newN=_streams.size(); pfds=(pollfd *)realloc(pfds, newN*sizeof(pollfd)); for(unsigned int i=n;i<newN;i++) { Stream& s=*_streams.at(i); pollfd& pfd=pfds[i]; pfd.fd=s.fileDescriptor(); pfd.events=s.eventTypes(); //Log::write(8, "enlarge stream %i events %x (POLLIN=%i, POLLPRI=%i)\n", i, pfd.events, POLLIN, POLLPRI); } n=newN; } // Remove dead streams for(unsigned int i=0;i<n;) { if(_streams.at(i)->isActive()) { i++; } else { n--; delete _streams.at(i); pfds[i].fd=pfds[n].fd; pfds[i].events=pfds[n].events; _streams.at(i)=_streams.at(n); //Log::write(8, "remove stream %i events %x (POLLIN=%i, POLLPRI=%i)\n", i, pfds[i].events, POLLIN, POLLPRI); } } if(n<_streams.size()) _streams.resize(n); } Log::write(1, "stop event loop\n"); }
EventLoop * GpCoreTools::EventLoop::instance | ( | ) | [static] |
References GpCoreTools::PThread::currentThread(), and GpCoreTools::PThread::eventLoop().
Referenced by GpCoreTools::ScreenClient::connect(), GpCoreTools::Serial::connect(), GpCoreTools::EventStream::event(), GpCoreTools::UnixServerStream::event(), GpCoreTools::TcpServerStream::event(), and GpCoreTools::Timer::start().
{ PThread * t=PThread::currentThread(); if(t) { return t->eventLoop(); } else { return _mainLoop; } }
bool GpCoreTools::EventLoop::isTerminated | ( | ) | const [inline] |
{return _terminate;}
static EventLoop* GpCoreTools::EventLoop::mainInstance | ( | ) | [inline, static] |
Referenced by GpCoreTools::DaemonApplication::childInterrupted().
{return _mainLoop;}
void GpCoreTools::EventLoop::terminate | ( | ) |
References GpCoreTools::EventStream::send().
Referenced by GpCoreTools::DaemonApplication::childInterrupted(), and GpCoreTools::PThread::stop().
{ // Do not use TRACE here because it uses a mutex which can be locked while this function // might be called inside a signal exception. _terminate=true; // Force poll() to exit immediately _eventStream->send(new NewTimerEvent); }