31 #include <sys/types.h>
53 int fdmax(
int = 0 )
const ;
54 fd_set * operator()() ;
59 fd_set m_set_internal ;
60 fd_set m_set_external ;
70 G_EXCEPTION( Error ,
"select() error" ) ;
73 virtual std::string run()
override ;
74 virtual bool running()
const override ;
75 virtual void quit( std::string )
override ;
80 virtual void dropRead(
Descriptor fd )
override ;
81 virtual void dropWrite(
Descriptor fd )
override ;
82 virtual void dropException(
Descriptor fd )
override ;
83 virtual std::string report()
const override ;
93 std::string m_quit_reason ;
100 FdSet m_exception_set ;
110 EventHandlerList & m_list ;
111 explicit Lock( EventHandlerList & list ) ;
115 Lock(
const Lock & ) ;
116 void operator=(
const Lock & ) ;
121 GNet::Lock::Lock( EventHandlerList & list ) :
134 GNet::FdSet::FdSet() :
140 fd_set * GNet::FdSet::operator()()
142 return &m_set_external ;
145 void GNet::FdSet::invalidate()
150 void GNet::FdSet::init(
const EventHandlerList & list )
165 FD_ZERO( &m_set_internal ) ;
166 const EventHandlerList::Iterator end = list.end() ;
167 for( EventHandlerList::Iterator p = list.begin() ; p != end ; ++p )
169 Descriptor fd = p.fd() ;
170 G_ASSERT( fd.valid() && fd.fd() >= 0 ) ;
171 if( fd.fd() < 0 )
continue ;
172 FD_SET( fd.fd() , &m_set_internal ) ;
173 if( (fd.fd()+1) > m_fdmax )
174 m_fdmax = (fd.fd()+1) ;
178 m_set_external = m_set_internal ;
181 int GNet::FdSet::fdmax(
int n )
const
183 return n > m_fdmax ? n : m_fdmax ;
186 void GNet::FdSet::raiseEvents( EventHandlerList & list ,
void (EventHandler::*method)() )
190 GNet::Lock lock( list ) ;
191 const EventHandlerList::Iterator end = list.end() ;
192 for( EventHandlerList::Iterator p = list.begin() ; p != end ; ++p )
194 Descriptor fd = p.fd() ;
195 if( fd.fd() >= 0 && FD_ISSET( fd.fd() , &m_set_external ) )
197 EventHandler * h = p.handler() ;
199 raiseEvent( h , method ) ;
204 void GNet::FdSet::raiseEvent( EventHandler * h ,
void (EventHandler::*method)() )
210 catch( std::exception & e )
212 h->onException( e ) ;
220 return new EventLoopImp ;
225 GNet::EventLoopImp::EventLoopImp() :
228 m_read_list(
"read") ,
229 m_write_list(
"write") ,
230 m_exception_list(
"exception")
234 GNet::EventLoopImp::~EventLoopImp()
238 std::string GNet::EventLoopImp::run()
240 EventLoop::Running running( m_running ) ;
245 std::string quit_reason = m_quit_reason ;
246 m_quit_reason.clear() ;
251 bool GNet::EventLoopImp::running()
const
256 void GNet::EventLoopImp::quit( std::string reason )
259 m_quit_reason = reason ;
267 void GNet::EventLoopImp::runOnce()
271 m_read_set.init( m_read_list ) ;
272 m_write_set.init( m_write_list ) ;
273 m_exception_set.init( m_exception_list ) ;
274 int n = m_read_set.fdmax( m_write_set.fdmax(m_exception_set.fdmax()) ) ;
278 typedef struct timeval Timeval ;
280 Timeval * timeout_p = nullptr ;
281 bool timeout_immediate = false ;
284 bool timeout_infinite = false ;
286 timeout_immediate = !timeout_infinite && interval.s == 0 && interval.us == 0U ;
287 timeout.tv_sec = interval.s ;
288 timeout.tv_usec = interval.us ;
289 timeout_p = timeout_infinite ?
nullptr : &timeout ;
296 if( timeout_p ==
nullptr || timeout.tv_sec > 0 )
299 timeout.tv_usec = 999999 ;
301 timeout_p = &timeout ;
306 int rc = ::select( n , m_read_set() , m_write_set() , m_exception_set() , timeout_p ) ;
316 if( rc == 0 || timeout_immediate )
334 Timeval timeout_slow ;
335 timeout_slow.tv_sec = 0 ;
336 timeout_slow.tv_usec = 100000 ;
337 ::select( 0 ,
nullptr ,
nullptr ,
nullptr , &timeout_slow ) ;
341 void GNet::EventLoopImp::addRead( Descriptor fd , EventHandler & handler )
343 m_read_list.add( fd , & handler ) ;
344 m_read_set.invalidate() ;
347 void GNet::EventLoopImp::addWrite( Descriptor fd , EventHandler & handler )
349 m_write_list.add( fd , & handler ) ;
350 m_write_set.invalidate() ;
353 void GNet::EventLoopImp::addException( Descriptor fd , EventHandler & handler )
355 m_exception_list.add( fd , & handler ) ;
356 m_exception_set.invalidate() ;
359 void GNet::EventLoopImp::dropRead( Descriptor fd )
361 m_read_list.remove( fd ) ;
362 m_read_set.invalidate() ;
365 void GNet::EventLoopImp::dropWrite( Descriptor fd )
367 m_write_list.remove( fd ) ;
368 m_write_set.invalidate() ;
371 void GNet::EventLoopImp::dropException( Descriptor fd )
373 m_exception_list.remove( fd ) ;
374 m_exception_set.invalidate() ;
382 std::string GNet::EventLoopImp::report()
const
384 return std::string() ;
A subsecond-resolution timestamp based on a time_t.
An empty structure that is used to indicate a signal-safe, reentrant implementation.
An abstract base class for a singleton that keeps track of open sockets and their associated handlers...
virtual void readEvent()
Called for a read event.
A class that encapsulates a network file descriptor and hides knowledge of its o/s-spefific error val...
static std::string fromInt(int i)
Converts int 'i' to a string.
A concrete implementation of GNet::EventLoop using select() in its implementation.
static EventLoop * create()
A factory method which creates an instance of a derived class on the heap.
static TimerList & instance()
Singleton access. Throws an exception if none.
An "fd_set" wrapper class used by GNet::EventLoopImp.
G::EpochTime interval(bool &infinite) const
Returns the interval to the first timer expiry.
virtual void writeEvent()
Called for a write event.
static bool enabled()
Returns true if test features are enabled.
void doTimeouts()
Triggers the timeout callbacks of any expired timers.
A base class for classes that handle asynchronous events from the event loop.
static bool remove(const Path &path, const NoThrow &)
Deletes the file or directory. Returns false on error.
An overload discriminator class for File methods.
virtual void exceptionEvent()
Called for a socket-exception event.
A class that maps from a file descriptor to an event handler, used in the implemention of classes der...