54 EventHandler::Reason ) ;
55 void invalidate() noexcept ;
56 int fdmax(
int = 0 )
const ;
57 fd_set * operator()() ;
62 fd_set m_set_internal ;
63 fd_set m_set_external ;
73 G_EXCEPTION( Error ,
"select error" ) ;
78 std::string run()
override ;
79 bool running()
const override ;
80 void quit(
const std::string & )
override ;
85 void dropRead(
Descriptor fd )
noexcept override ;
86 void dropWrite(
Descriptor fd )
noexcept override ;
87 void dropOther(
Descriptor fd )
noexcept override ;
98 static void check(
int ) ;
102 std::string m_quit_reason ;
103 bool m_running{
false} ;
117fd_set * GNet::FdSet::operator()()
119 return &m_set_external ;
122void GNet::FdSet::invalidate() noexcept
127void GNet::FdSet::init(
const EventHandlerList & list )
140 FD_ZERO( &m_set_internal ) ;
141 const EventHandlerList::Iterator end = list.end() ;
142 for( EventHandlerList::Iterator p = list.begin() ; p != end ; ++p )
144 G_ASSERT( p.fd().valid() && p.fd().fd() >= 0 ) ;
145 Descriptor fd = p.fd() ;
146 if( fd.fd() < 0 ) continue ;
147 FD_SET( fd.fd() , &m_set_internal ) ;
148 if( (fd.fd()+1) > m_fdmax )
149 m_fdmax = (fd.fd()+1) ;
153 m_set_external = m_set_internal ;
156int GNet::FdSet::fdmax(
int n )
const
158 return n > m_fdmax ? n : m_fdmax ;
161void GNet::FdSet::raiseEvents( EventHandlerList & list ,
void (EventHandler::*method)() )
163 EventHandlerList::Lock lock( list ) ;
164 const EventHandlerList::Iterator end = list.end() ;
165 for( EventHandlerList::Iterator p = list.begin() ; p != end ; ++p )
167 Descriptor fd = p.fd() ;
168 if( fd.fd() >= 0 && FD_ISSET( fd.fd() , &m_set_external ) )
170 p.raiseEvent( method ) ;
175void GNet::FdSet::raiseEvents( EventHandlerList & list ,
void (EventHandler::*method)(EventHandler::Reason) ,
176 EventHandler::Reason reason )
178 EventHandlerList::Lock lock( list ) ;
179 const EventHandlerList::Iterator end = list.end() ;
180 for( EventHandlerList::Iterator p = list.begin() ; p != end ; ++p )
182 Descriptor fd = p.fd() ;
183 if( fd.fd() >= 0 && FD_ISSET( fd.fd() , &m_set_external ) )
185 p.raiseEvent( method , reason ) ;
194 return std::make_unique<EventLoopImp>() ;
199GNet::EventLoopImp::EventLoopImp() :
200 m_read_list(
"read") ,
201 m_write_list(
"write") ,
202 m_other_list(
"other")
206GNet::EventLoopImp::~EventLoopImp()
209std::string GNet::EventLoopImp::run()
216 std::string quit_reason = m_quit_reason ;
217 m_quit_reason.clear() ;
222bool GNet::EventLoopImp::running()
const
227void GNet::EventLoopImp::quit(
const std::string & reason )
230 m_quit_reason = reason ;
238void GNet::EventLoopImp::runOnce()
242 m_read_set.init( m_read_list ) ;
243 m_write_set.init( m_write_list ) ;
244 m_other_set.init( m_other_list ) ;
245 int n = m_read_set.fdmax( m_write_set.fdmax(m_other_set.fdmax()) ) ;
249 using Timeval =
struct timeval ;
251 Timeval * timeout_p = nullptr ;
252 bool timeout_immediate = false ;
257 bool timeout_infinite = interval_pair.second ;
258 timeout_immediate = !timeout_infinite && interval.
s() == 0 && interval.
us() == 0U ;
259 timeout.tv_sec = interval.
s() ;
260 timeout.tv_usec = interval.
us() ;
261 timeout_p = timeout_infinite ? nullptr : &timeout ;
268 if( timeout_p ==
nullptr || timeout.tv_sec > 0 )
271 timeout.tv_usec = 999999U ;
273 timeout_p = &timeout ;
278 int rc = ::select( n , m_read_set() , m_write_set() , m_other_set() , timeout_p ) ;
288 if( rc == 0 || timeout_immediate )
306 Timeval timeout_slow ;
307 timeout_slow.tv_sec = 0 ;
308 timeout_slow.tv_usec = 100000 ;
309 ::select( 0 ,
nullptr ,
nullptr ,
nullptr , &timeout_slow ) ;
313void GNet::EventLoopImp::addRead( Descriptor fd , EventHandler & handler , ExceptionSink es )
316 m_read_list.add( fd , &handler , es ) ;
317 m_read_set.invalidate() ;
320void GNet::EventLoopImp::addWrite( Descriptor fd , EventHandler & handler , ExceptionSink es )
323 m_write_list.add( fd , &handler , es ) ;
324 m_write_set.invalidate() ;
327void GNet::EventLoopImp::addOther( Descriptor fd , EventHandler & handler , ExceptionSink es )
330 m_other_list.add( fd , &handler , es ) ;
331 m_other_set.invalidate() ;
334void GNet::EventLoopImp::check(
int fd )
336 if( fd >= FD_SETSIZE )
337 throw EventLoop::Overflow(
"too many open file descriptors for select()" ) ;
340void GNet::EventLoopImp::dropRead( Descriptor fd )
noexcept
342 m_read_list.remove( fd ) ;
343 m_read_set.invalidate() ;
346void GNet::EventLoopImp::dropWrite( Descriptor fd )
noexcept
348 m_write_list.remove( fd ) ;
349 m_write_set.invalidate() ;
352void GNet::EventLoopImp::dropOther( Descriptor fd )
noexcept
354 m_other_list.remove( fd ) ;
355 m_other_set.invalidate() ;
358void GNet::EventLoopImp::disarm( ExceptionHandler * p )
noexcept
360 m_read_list.disarm( p ) ;
361 m_write_list.disarm( p ) ;
362 m_other_list.disarm( p ) ;
A class that encapsulates a network socket file descriptor and an associated windows event handle.
A class that maps from a file descriptor to an event handler and exception handler,...
A base class for classes that handle asynchronous events from the event loop.
virtual void readEvent()
Called for a read event.
virtual void writeEvent()
Called for a write event.
virtual void otherEvent(Reason)
Called for a socket-exception event, or a socket-close event on windows.
A concrete implementation of GNet::EventLoop using select() in its implementation.
An abstract base class for a singleton that keeps track of open sockets and their associated handlers...
static std::unique_ptr< EventLoop > create()
A factory method which creates an instance of a derived class on the heap.
An abstract interface for handling exceptions thrown out of event-loop callbacks (socket/future event...
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
An "fd_set" wrapper class used by GNet::EventLoopImp.
std::pair< G::TimeInterval, bool > interval() const
Returns the interval to the first timer expiry.
void doTimeouts()
Triggers the timeout callbacks of any expired timers.
static TimerList & instance()
Singleton access. Throws an exception if none.
static TimerList * ptr() noexcept
Singleton access. Returns nullptr if none.
static bool remove(const Path &path, std::nothrow_t) noexcept
Deletes the file or directory. Returns false on error.
static int errno_(const SignalSafe &=G::SignalSafe()) noexcept
Returns the process's current 'errno' value.
A class that sets a boolean variable to false at the end of its scope.
An empty structure that is used to indicate a signal-safe, reentrant implementation.
static std::string fromInt(int i)
Converts int 'i' to a string.
static bool enabled() noexcept
Returns true if test features are enabled.
An interval between two G::SystemTime values or two G::TimerTime values.
unsigned int s() const
Returns the number of seconds.
unsigned int us() const
Returns the fractional microseconds part.