31 namespace EventHandlerListImp
36 bool operator()(
const Value & p1 ,
const Value & p2 )
noexcept
38 return p1.m_fd < p2.m_fd ;
53 G_ASSERT( handler !=
nullptr ) ;
if( handler ==
nullptr ) return ;
54 G_ASSERT( es.
eh() !=
nullptr ) ;
if( es.
eh() ==
nullptr ) return ;
56 G_DEBUG(
"GNet::EventHandlerList::add: " << m_type <<
"-list: " <<
"adding " << fd << (m_lock?
" (pending)":
"") ) ;
57 addImp( m_lock?m_pending_list:m_list , fd , handler , es ) ;
62 namespace imp = EventHandlerListImp ;
63 using Range = std::pair<List::iterator,List::iterator> ;
64 Range range = std::equal_range( list.begin() , list.end() , List::value_type(fd) , imp::fdless() ) ;
65 if( range.first == range.second )
66 list.insert( range.first , List::value_type(fd,handler,es) ) ;
68 *range.first = List::value_type(fd,handler,es) ;
73 G_DEBUG(
"GNet::EventHandlerList::remove: " << m_type <<
"-list: " <<
"removing " << fd ) ;
76 if( disable(m_list,fd) ) m_has_garbage = true ;
77 disable( m_pending_list , fd ) ;
81 remove( m_list , fd ) ;
85bool GNet::EventHandlerList::disable( List & list ,
Descriptor fd )
noexcept
87 namespace imp = EventHandlerListImp ;
88 using Range = std::pair<List::iterator,List::iterator> ;
89 Range range = std::equal_range( list.begin() , list.end() , List::value_type(fd) , imp::fdless() ) ;
90 const bool found = range.first != range.second ;
93 (*range.first).m_event_handler =
nullptr ;
100 namespace imp = EventHandlerListImp ;
101 using Range = std::pair<List::iterator,List::iterator> ;
102 Range range = std::equal_range( list.begin() , list.end() , List::value_type(fd) , imp::fdless() ) ;
103 const bool found = range.first != range.second ;
105 list.erase( range.first ) ;
111 disarm( m_list , eh ) ;
112 disarm( m_pending_list , eh ) ;
117 for(
auto & value : list )
119 if( value.m_es.eh() == eh )
126 namespace imp = EventHandlerListImp ;
127 using Range = std::pair<List::const_iterator,List::const_iterator> ;
128 Range range = std::equal_range( m_list.begin() , m_list.end() , List::value_type(fd) , imp::fdless() ) ;
129 return range.first == range.second ?
Iterator(m_list.end(),m_list.end()) :
Iterator(range.first,m_list.end()) ;
134 namespace imp = EventHandlerListImp ;
135 using Range = std::pair<List::const_iterator,List::const_iterator> ;
136 Range range = std::equal_range( m_pending_list.begin() , m_pending_list.end() ,
137 List::value_type(fd) , imp::fdless() ) ;
138 if( range.first == range.second )
139 range = std::equal_range( m_list.begin() , m_list.end() , List::value_type(fd) , imp::fdless() ) ;
140 return range.first != range.second && (*range.first).m_event_handler !=
nullptr ;
145 return m_list.size() ;
150 getHandles( m_list , out ) ;
151 getHandles( m_pending_list , out ) ;
156 using iterator = std::vector<HANDLE>::iterator ;
157 using Range = std::pair<iterator,iterator> ;
158 for(
const auto & value : list )
160 HANDLE h = value.m_fd.h() ;
161 if( !h || value.m_event_handler ==
nullptr ) continue ;
162 Range range = std::equal_range( out.begin() , out.end() , h ) ;
163 if( range.first == range.second )
164 out.insert( range.first , h ) ;
175 G_ASSERT( m_lock != 0U ) ;
177 bool updated = false ;
180 updated = !m_pending_list.empty() || m_has_garbage ;
187void GNet::EventHandlerList::commitPending()
189 const List::iterator end = m_pending_list.end() ;
190 for(
auto p = m_pending_list.begin() ; p != end ; ++p )
192 if( (*p).m_event_handler !=
nullptr )
194 G_DEBUG(
"GNet::EventHandlerList::commitPending: " << m_type <<
"-list: " <<
"commiting " << (*p).m_fd ) ;
195 addImp( m_list , (*p).m_fd , (*p).m_event_handler , (*p).m_es ) ;
198 m_pending_list.clear() ;
201void GNet::EventHandlerList::collectGarbage()
205 m_has_garbage = false ;
206 for(
auto p = m_list.begin() ; p != m_list.end() ; )
208 if( (*p).m_event_handler ==
nullptr )
209 p = m_list.erase( p ) ;
218void GNet::EventHandlerList::Iterator::raiseEvent(
void (EventHandler::*method)() )
221 EventLoggingContext set_logging_context( (m_p!=m_end&&handler()&&es().set()) ? es().esrc() :
nullptr ) ;
224 if( m_p != m_end && handler() !=
nullptr )
225 (handler()->*method)() ;
229 if( m_p != m_end && es().
set() )
230 es().
call( e ,
true ) ;
234 catch( std::exception & e )
236 if( m_p != m_end && es().
set() )
237 es().
call( e ,
false ) ;
243void GNet::EventHandlerList::Iterator::raiseEvent(
void (EventHandler::*method)(EventHandler::Reason) ,
244 EventHandler::Reason reason )
246 EventLoggingContext set_logging_context( (m_p!=m_end&&handler()&&es().set()) ? es().esrc() :
nullptr ) ;
249 if( m_p != m_end && handler() !=
nullptr )
250 (handler()->*method)( reason ) ;
254 if( m_p != m_end && es().
set() )
255 es().
call( e ,
true ) ;
259 catch( std::exception & e )
261 if( m_p != m_end && es().
set() )
262 es().
call( e ,
false ) ;
270GNet::EventHandlerList::Lock::Lock( EventHandlerList & list ,
bool * invalid_p ) :
272 m_invalid_p(invalid_p)
277GNet::EventHandlerList::Lock::~Lock()
279 if( m_list.unlock() && m_invalid_p !=
nullptr )
280 *m_invalid_p = true ;
A class that encapsulates a network socket file descriptor and an associated windows event handle.
An exception class that is detected by GNet::EventHandlerList and results in onException() being call...
Iterator find(Descriptor fd) const
Finds an entry in the list.
void lock()
To be called at the start of an begin()/end() iteration if the list might change during the iteration...
bool unlock()
Called at the end of a begin()/end() iteration to match a call to lock().
std::size_t size() const noexcept
Returns the size of the list, ignoring any changes while lock()ed.
EventHandlerList(const std::string &type)
Constructor.
void disarm(ExceptionHandler *) noexcept
Resets any matching ExceptionHandler pointers, so exceptions thrown out of the relevant file descript...
bool contains(Descriptor fd) const noexcept
Returns true if the list, taking account of any pending changes, contains the given descriptor.
void getHandles(std::vector< HANDLE > &) const
Adds unique, non-zero Descriptor handles to the given sorted list, including any add()ed while lock()...
void remove(Descriptor fd) noexcept
Removes a file-descriptor from the list.
void add(Descriptor fd, EventHandler *handler, ExceptionSink)
Adds a file-descriptor/handler tuple to the list.
A base class for classes that handle asynchronous events from the event loop.
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.
ExceptionHandler * eh() const noexcept
Returns the exception handler pointer.
void call(std::exception &e, bool done)
Calls the exception handler's onException() method.
bool set() const noexcept
Returns true if eh() is not null.
A functor that compares two file descriptors.
An iterator for GNet::EventHandlerList.
A tuple for GNet::EventHandlerList.