]>
git.saurik.com Git - wxWidgets.git/blob - src/unix/epolldispatcher.cpp
   1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/epolldispatcher.cpp 
   3 // Purpose:     implements dispatcher for epoll_wait() call 
   4 // Author:      Lukasz Michalski 
   7 // Copyright:   (c) 2007 Lukasz Michalski 
   8 // License:     wxWindows licence 
   9 /////////////////////////////////////////////////////////////////////////////// 
  11 // ============================================================================ 
  13 // ============================================================================ 
  15 // ---------------------------------------------------------------------------- 
  17 // ---------------------------------------------------------------------------- 
  19 // for compilers that support precompilation, includes "wx.h". 
  20 #include "wx/wxprec.h" 
  22 #if wxUSE_EPOLL_DISPATCHER 
  24 #include "wx/unix/private/epolldispatcher.h" 
  25 #include "wx/unix/private.h" 
  26 #include "wx/stopwatch.h" 
  33 #include <sys/epoll.h> 
  37 #define wxEpollDispatcher_Trace wxT("epolldispatcher") 
  39 // ============================================================================ 
  41 // ============================================================================ 
  43 // helper: return EPOLLxxx mask corresponding to the given flags (and also log 
  44 // debugging messages about it) 
  45 static uint32_t GetEpollMask(int flags
, int WXUNUSED_UNLESS_DEBUG(fd
)) 
  49     if ( flags 
& wxFDIO_INPUT 
) 
  52         wxLogTrace(wxEpollDispatcher_Trace
, 
  53                    _T("Registered fd %d for input events"), fd
); 
  56     if ( flags 
& wxFDIO_OUTPUT 
) 
  59         wxLogTrace(wxEpollDispatcher_Trace
, 
  60                    _T("Registered fd %d for output events"), fd
); 
  63     if ( flags 
& wxFDIO_EXCEPTION 
) 
  65         ep 
|= EPOLLERR 
| EPOLLHUP
; 
  66         wxLogTrace(wxEpollDispatcher_Trace
, 
  67                    _T("Registered fd %d for exceptional events"), fd
); 
  73 // ---------------------------------------------------------------------------- 
  75 // ---------------------------------------------------------------------------- 
  78 wxEpollDispatcher 
*wxEpollDispatcher::Create() 
  80     int epollDescriptor 
= epoll_create(1024); 
  81     if ( epollDescriptor 
== -1 ) 
  83         wxLogSysError(_("Failed to create epoll descriptor")); 
  86     wxLogTrace(wxEpollDispatcher_Trace
, 
  87                    _T("Epoll fd %d created"), epollDescriptor
); 
  88     return new wxEpollDispatcher(epollDescriptor
); 
  91 wxEpollDispatcher::wxEpollDispatcher(int epollDescriptor
) 
  93     wxASSERT_MSG( epollDescriptor 
!= -1, _T("invalid descriptor") ); 
  95     m_epollDescriptor 
= epollDescriptor
; 
  98 wxEpollDispatcher::~wxEpollDispatcher() 
 100     if ( close(m_epollDescriptor
) != 0 ) 
 102         wxLogSysError(_("Error closing epoll descriptor")); 
 106 bool wxEpollDispatcher::RegisterFD(int fd
, wxFDIOHandler
* handler
, int flags
) 
 109     ev
.events 
= GetEpollMask(flags
, fd
); 
 110     ev
.data
.ptr 
= handler
; 
 112     const int ret 
= epoll_ctl(m_epollDescriptor
, EPOLL_CTL_ADD
, fd
, &ev
); 
 115         wxLogSysError(_("Failed to add descriptor %d to epoll descriptor %d"), 
 116                       fd
, m_epollDescriptor
); 
 120     wxLogTrace(wxEpollDispatcher_Trace
, 
 121                _T("Added fd %d (handler %p) to epoll %d"), fd
, handler
, m_epollDescriptor
); 
 126 bool wxEpollDispatcher::ModifyFD(int fd
, wxFDIOHandler
* handler
, int flags
) 
 129     ev
.events 
= GetEpollMask(flags
, fd
); 
 130     ev
.data
.ptr 
= handler
; 
 132     const int ret 
= epoll_ctl(m_epollDescriptor
, EPOLL_CTL_MOD
, fd
, &ev
); 
 135         wxLogSysError(_("Failed to modify descriptor %d in epoll descriptor %d"), 
 136                       fd
, m_epollDescriptor
); 
 141     wxLogTrace(wxEpollDispatcher_Trace
, 
 142                 _T("Modified fd %d (handler: %p) on epoll %d"), fd
, handler
, m_epollDescriptor
); 
 146 bool wxEpollDispatcher::UnregisterFD(int fd
) 
 152     if ( epoll_ctl(m_epollDescriptor
, EPOLL_CTL_DEL
, fd
, &ev
) != 0 ) 
 154         wxLogSysError(_("Failed to unregister descriptor %d from epoll descriptor %d"), 
 155                       fd
, m_epollDescriptor
); 
 157     wxLogTrace(wxEpollDispatcher_Trace
, 
 158                 _T("removed fd %d from %d"), fd
, m_epollDescriptor
); 
 163 wxEpollDispatcher::DoPoll(epoll_event 
*events
, int numEvents
, int timeout
) const 
 165     // the code below relies on TIMEOUT_INFINITE being -1 so that we can pass 
 166     // timeout value directly to epoll_wait() which interprets -1 as meaning to 
 167     // wait forever and would need to be changed if the value of 
 168     // TIMEOUT_INFINITE ever changes 
 169     wxCOMPILE_TIME_ASSERT( TIMEOUT_INFINITE 
== -1, UpdateThisCode 
); 
 171     wxMilliClock_t timeEnd
; 
 173         timeEnd 
= wxGetLocalTimeMillis(); 
 178         rc 
= epoll_wait(m_epollDescriptor
, events
, numEvents
, timeout
); 
 179         if ( rc 
!= -1 || errno 
!= EINTR 
) 
 182         // we got interrupted, update the timeout and restart 
 185             timeout 
= wxMilliClockToLong(timeEnd 
- wxGetLocalTimeMillis()); 
 194 bool wxEpollDispatcher::HasPending() const 
 197     return DoPoll(&event
, 1, 0) == 1; 
 200 int wxEpollDispatcher::Dispatch(int timeout
) 
 202     epoll_event events
[16]; 
 204     const int rc 
= DoPoll(events
, WXSIZEOF(events
), timeout
); 
 208         wxLogSysError(_("Waiting for IO on epoll descriptor %d failed"), 
 214     for ( epoll_event 
*p 
= events
; p 
< events 
+ rc
; p
++ ) 
 216         wxFDIOHandler 
* const handler 
= (wxFDIOHandler 
*)(p
->data
.ptr
); 
 219             wxFAIL_MSG( _T("NULL handler in epoll_event?") ); 
 223         // note that for compatibility with wxSelectDispatcher we call 
 224         // OnReadWaiting() on EPOLLHUP as this is what epoll_wait() returns 
 225         // when the write end of a pipe is closed while with select() the 
 226         // remaining pipe end becomes ready for reading when this happens 
 227         if ( p
->events 
& (EPOLLIN 
| EPOLLHUP
) ) 
 228             handler
->OnReadWaiting(); 
 229         else if ( p
->events 
& EPOLLOUT 
) 
 230             handler
->OnWriteWaiting(); 
 231         else if ( p
->events 
& EPOLLERR 
) 
 232             handler
->OnExceptionWaiting(); 
 242 #endif // wxUSE_EPOLL_DISPATCHER