create the single global IO dispatcher in wxFDIODispatcher; don't use wxSelectDispatc...
[wxWidgets.git] / src / unix / epolldispatcher.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/epolldispatcher.cpp
3 // Purpose: implements dispatcher for epoll_wait() call
4 // Author: Lukasz Michalski
5 // Created: April 2007
6 // RCS-ID: $Id$
7 // Copyright: (c) 2007 Lukasz Michalski
8 // License: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef wxUSE_EPOLL_DISPATCHER
23
24 #include "wx/unix/private/epolldispatcher.h"
25 #include "wx/unix/private.h"
26
27 #ifndef WX_PRECOMP
28 #include "wx/log.h"
29 #include "wx/intl.h"
30 #endif
31
32 #include <sys/epoll.h>
33 #include <errno.h>
34
35 #define wxEpollDispatcher_Trace wxT("epolldispatcher")
36
37 // ============================================================================
38 // implementation
39 // ============================================================================
40
41 // helper: return EPOLLxxx mask corresponding to the given flags (and also log
42 // debugging messages about it)
43 static uint32_t GetEpollMask(int flags, int fd)
44 {
45 uint32_t ep = 0;
46
47 if ( flags & wxFDIO_INPUT )
48 {
49 ep |= EPOLLIN;
50 wxLogTrace(wxEpollDispatcher_Trace,
51 _T("Registered fd %d for input events"), fd);
52 }
53
54 if ( flags & wxFDIO_OUTPUT )
55 {
56 ep |= EPOLLOUT;
57 wxLogTrace(wxEpollDispatcher_Trace,
58 _T("Registered fd %d for output events"), fd);
59 }
60
61 if ( flags & wxFDIO_EXCEPTION )
62 {
63 ep |= EPOLLERR | EPOLLHUP;
64 wxLogTrace(wxEpollDispatcher_Trace,
65 _T("Registered fd %d for exceptional events"), fd);
66 }
67
68 return ep;
69 }
70
71 // ----------------------------------------------------------------------------
72 // wxEpollDispatcher
73 // ----------------------------------------------------------------------------
74
75 /* static */
76 wxEpollDispatcher *wxEpollDispatcher::Create()
77 {
78 int epollDescriptor = epoll_create(1024);
79 if ( epollDescriptor == -1 )
80 {
81 wxLogSysError(_("Failed to create epoll descriptor"));
82 return NULL;
83 }
84
85 return new wxEpollDispatcher(epollDescriptor);
86 }
87
88 wxEpollDispatcher::wxEpollDispatcher(int epollDescriptor)
89 {
90 wxASSERT_MSG( epollDescriptor != -1, _T("invalid descriptor") );
91
92 m_epollDescriptor = epollDescriptor;
93 }
94
95 bool wxEpollDispatcher::RegisterFD(int fd, wxFDIOHandler* handler, int flags)
96 {
97 epoll_event ev;
98 ev.events = GetEpollMask(flags, fd);
99 ev.data.ptr = handler;
100
101 const int ret = epoll_ctl(m_epollDescriptor, EPOLL_CTL_ADD, fd, &ev);
102 if ( ret != 0 )
103 {
104 wxLogSysError(_("Failed to add descriptor %d to epoll descriptor %d"),
105 fd, m_epollDescriptor);
106
107 return false;
108 }
109
110 return true;
111 }
112
113 bool wxEpollDispatcher::ModifyFD(int fd, wxFDIOHandler* handler, int flags)
114 {
115 epoll_event ev;
116 ev.events = GetEpollMask(flags, fd);
117 ev.data.ptr = handler;
118
119 const int ret = epoll_ctl(m_epollDescriptor, EPOLL_CTL_MOD, fd, &ev);
120 if ( ret != 0 )
121 {
122 wxLogSysError(_("Failed to modify descriptor %d in epoll descriptor %d"),
123 fd, m_epollDescriptor);
124
125 return false;
126 }
127
128 return true;
129 }
130
131 bool wxEpollDispatcher::UnregisterFD(int fd)
132 {
133 epoll_event ev;
134 ev.events = 0;
135 ev.data.ptr = NULL;
136
137 if ( epoll_ctl(m_epollDescriptor, EPOLL_CTL_DEL, fd, &ev) != 0 )
138 {
139 wxLogSysError(_("Failed to unregister descriptor %d from epoll descriptor %d"),
140 fd, m_epollDescriptor);
141 }
142
143 return true;
144 }
145
146 void wxEpollDispatcher::Dispatch(int timeout)
147 {
148 epoll_event events[16];
149
150 const int e_num = epoll_wait
151 (
152 m_epollDescriptor,
153 events,
154 WXSIZEOF(events),
155 timeout == TIMEOUT_INFINITE ? -1 : timeout
156 );
157
158 if ( e_num == -1 )
159 {
160 if ( errno != EINTR )
161 {
162 wxLogSysError(_("Waiting for IO on epoll descriptor %d failed"),
163 m_epollDescriptor);
164 return;
165 }
166 }
167
168 for ( epoll_event *p = events; p < events + e_num; p++ )
169 {
170 wxFDIOHandler * const handler = (wxFDIOHandler *)(p->data.ptr);
171 if ( !handler )
172 {
173 wxFAIL_MSG( _T("NULL handler in epoll_event?") );
174 continue;
175 }
176
177 if ( p->events & EPOLLIN )
178 handler->OnReadWaiting();
179 else if ( p->events & EPOLLOUT )
180 handler->OnWriteWaiting();
181 else if ( p->events & (EPOLLERR | EPOLLHUP) )
182 handler->OnExceptionWaiting();
183 }
184 }
185
186 #endif // wxUSE_EPOLL_DISPATCHER