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);
}