]>
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 // Licence: 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 fd
)
47 wxUnusedVar(fd
); // unused if wxLogTrace() disabled
51 if ( flags
& wxFDIO_INPUT
)
54 wxLogTrace(wxEpollDispatcher_Trace
,
55 wxT("Registered fd %d for input events"), fd
);
58 if ( flags
& wxFDIO_OUTPUT
)
61 wxLogTrace(wxEpollDispatcher_Trace
,
62 wxT("Registered fd %d for output events"), fd
);
65 if ( flags
& wxFDIO_EXCEPTION
)
67 ep
|= EPOLLERR
| EPOLLHUP
;
68 wxLogTrace(wxEpollDispatcher_Trace
,
69 wxT("Registered fd %d for exceptional events"), fd
);
75 // ----------------------------------------------------------------------------
77 // ----------------------------------------------------------------------------
80 wxEpollDispatcher
*wxEpollDispatcher::Create()
82 int epollDescriptor
= epoll_create(1024);
83 if ( epollDescriptor
== -1 )
85 wxLogSysError(_("Failed to create epoll descriptor"));
88 wxLogTrace(wxEpollDispatcher_Trace
,
89 wxT("Epoll fd %d created"), epollDescriptor
);
90 return new wxEpollDispatcher(epollDescriptor
);
93 wxEpollDispatcher::wxEpollDispatcher(int epollDescriptor
)
95 wxASSERT_MSG( epollDescriptor
!= -1, wxT("invalid descriptor") );
97 m_epollDescriptor
= epollDescriptor
;
100 wxEpollDispatcher::~wxEpollDispatcher()
102 if ( close(m_epollDescriptor
) != 0 )
104 wxLogSysError(_("Error closing epoll descriptor"));
108 bool wxEpollDispatcher::RegisterFD(int fd
, wxFDIOHandler
* handler
, int flags
)
111 ev
.events
= GetEpollMask(flags
, fd
);
112 ev
.data
.ptr
= handler
;
114 const int ret
= epoll_ctl(m_epollDescriptor
, EPOLL_CTL_ADD
, fd
, &ev
);
117 wxLogSysError(_("Failed to add descriptor %d to epoll descriptor %d"),
118 fd
, m_epollDescriptor
);
122 wxLogTrace(wxEpollDispatcher_Trace
,
123 wxT("Added fd %d (handler %p) to epoll %d"), fd
, handler
, m_epollDescriptor
);
128 bool wxEpollDispatcher::ModifyFD(int fd
, wxFDIOHandler
* handler
, int flags
)
131 ev
.events
= GetEpollMask(flags
, fd
);
132 ev
.data
.ptr
= handler
;
134 const int ret
= epoll_ctl(m_epollDescriptor
, EPOLL_CTL_MOD
, fd
, &ev
);
137 wxLogSysError(_("Failed to modify descriptor %d in epoll descriptor %d"),
138 fd
, m_epollDescriptor
);
143 wxLogTrace(wxEpollDispatcher_Trace
,
144 wxT("Modified fd %d (handler: %p) on epoll %d"), fd
, handler
, m_epollDescriptor
);
148 bool wxEpollDispatcher::UnregisterFD(int fd
)
154 if ( epoll_ctl(m_epollDescriptor
, EPOLL_CTL_DEL
, fd
, &ev
) != 0 )
156 wxLogSysError(_("Failed to unregister descriptor %d from epoll descriptor %d"),
157 fd
, m_epollDescriptor
);
159 wxLogTrace(wxEpollDispatcher_Trace
,
160 wxT("removed fd %d from %d"), fd
, m_epollDescriptor
);
165 wxEpollDispatcher::DoPoll(epoll_event
*events
, int numEvents
, int timeout
) const
167 // the code below relies on TIMEOUT_INFINITE being -1 so that we can pass
168 // timeout value directly to epoll_wait() which interprets -1 as meaning to
169 // wait forever and would need to be changed if the value of
170 // TIMEOUT_INFINITE ever changes
171 wxCOMPILE_TIME_ASSERT( TIMEOUT_INFINITE
== -1, UpdateThisCode
);
173 wxMilliClock_t timeEnd
;
175 timeEnd
= wxGetLocalTimeMillis();
180 rc
= epoll_wait(m_epollDescriptor
, events
, numEvents
, timeout
);
181 if ( rc
!= -1 || errno
!= EINTR
)
184 // we got interrupted, update the timeout and restart
187 timeout
= wxMilliClockToLong(timeEnd
- wxGetLocalTimeMillis());
196 bool wxEpollDispatcher::HasPending() const
200 // NB: it's not really clear if epoll_wait() can return a number greater
201 // than the number of events passed to it but just in case it can, use
202 // >= instead of == here, see #10397
203 return DoPoll(&event
, 1, 0) >= 1;
206 int wxEpollDispatcher::Dispatch(int timeout
)
208 epoll_event events
[16];
210 const int rc
= DoPoll(events
, WXSIZEOF(events
), timeout
);
214 wxLogSysError(_("Waiting for IO on epoll descriptor %d failed"),
220 for ( epoll_event
*p
= events
; p
< events
+ rc
; p
++ )
222 wxFDIOHandler
* const handler
= (wxFDIOHandler
*)(p
->data
.ptr
);
225 wxFAIL_MSG( wxT("NULL handler in epoll_event?") );
229 // note that for compatibility with wxSelectDispatcher we call
230 // OnReadWaiting() on EPOLLHUP as this is what epoll_wait() returns
231 // when the write end of a pipe is closed while with select() the
232 // remaining pipe end becomes ready for reading when this happens
233 if ( p
->events
& (EPOLLIN
| EPOLLHUP
) )
234 handler
->OnReadWaiting();
235 else if ( p
->events
& EPOLLOUT
)
236 handler
->OnWriteWaiting();
237 else if ( p
->events
& EPOLLERR
)
238 handler
->OnExceptionWaiting();
248 #endif // wxUSE_EPOLL_DISPATCHER