changed wxFDIODispatcher::UnregisterFD() to take only fd, without flags, and unregist...
[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 #include "wx/module.h"
27
28 #ifndef WX_PRECOMP
29 #include "wx/log.h"
30 #include "wx/intl.h"
31 #endif
32
33 #include <sys/epoll.h>
34 #include <errno.h>
35
36 #define wxEpollDispatcher_Trace wxT("epolldispatcher")
37
38 static wxEpollDispatcher *gs_epollDispatcher = NULL;
39
40 // ============================================================================
41 // implementation
42 // ============================================================================
43
44 // helper: return EPOLLxxx mask corresponding to the given flags (and also log
45 // debugging messages about it)
46 static uint32_t GetEpollMask(int flags, int fd)
47 {
48 uint32_t ep = 0;
49
50 if ( flags & wxFDIO_INPUT )
51 {
52 ep |= EPOLLIN;
53 wxLogTrace(wxEpollDispatcher_Trace,
54 _T("Registered fd %d for input events"), fd);
55 }
56
57 if ( flags & wxFDIO_OUTPUT )
58 {
59 ep |= EPOLLOUT;
60 wxLogTrace(wxEpollDispatcher_Trace,
61 _T("Registered fd %d for output events"), fd);
62 }
63
64 if ( flags & wxFDIO_EXCEPTION )
65 {
66 ep |= EPOLLERR | EPOLLHUP;
67 wxLogTrace(wxEpollDispatcher_Trace,
68 _T("Registered fd %d for exceptional events"), fd);
69 }
70
71 return ep;
72 }
73
74 // ----------------------------------------------------------------------------
75 // wxEpollDispatcher
76 // ----------------------------------------------------------------------------
77
78 wxEpollDispatcher::wxEpollDispatcher()
79 {
80 m_epollDescriptor = epoll_create(1024);
81 if ( m_epollDescriptor == -1 )
82 {
83 wxLogSysError(_("Failed to create epoll descriptor"));
84 }
85 }
86
87 bool wxEpollDispatcher::RegisterFD(int fd, wxFDIOHandler* handler, int flags)
88 {
89 epoll_event ev;
90 ev.events = GetEpollMask(flags, fd);
91 ev.data.ptr = handler;
92
93 const int ret = epoll_ctl(m_epollDescriptor, EPOLL_CTL_ADD, fd, &ev);
94 if ( ret != 0 )
95 {
96 wxLogSysError(_("Failed to add descriptor %d to epoll descriptor %d"),
97 fd, m_epollDescriptor);
98
99 return false;
100 }
101
102 return true;
103 }
104
105 bool wxEpollDispatcher::ModifyFD(int fd, wxFDIOHandler* handler, int flags)
106 {
107 epoll_event ev;
108 ev.events = GetEpollMask(flags, fd);
109 ev.data.ptr = handler;
110
111 const int ret = epoll_ctl(m_epollDescriptor, EPOLL_CTL_MOD, fd, &ev);
112 if ( ret != 0 )
113 {
114 wxLogSysError(_("Failed to modify descriptor %d in epoll descriptor %d"),
115 fd, m_epollDescriptor);
116
117 return false;
118 }
119
120 return true;
121 }
122
123 bool wxEpollDispatcher::UnregisterFD(int fd)
124 {
125 epoll_event ev;
126 ev.events = 0;
127 ev.data.ptr = NULL;
128
129 if ( epoll_ctl(m_epollDescriptor, EPOLL_CTL_DEL, fd, &ev) != 0 )
130 {
131 wxLogSysError(_("Failed to unregister descriptor %d from epoll descriptor %d"),
132 fd, m_epollDescriptor);
133 }
134
135 return true;
136 }
137
138 void wxEpollDispatcher::RunLoop(int timeout)
139 {
140 epoll_event events[16];
141
142 const int e_num = epoll_wait
143 (
144 m_epollDescriptor,
145 events,
146 WXSIZEOF(events),
147 timeout == TIMEOUT_INFINITE ? -1 : timeout
148 );
149
150 if ( e_num == -1 )
151 {
152 if ( errno != EINTR )
153 {
154 wxLogSysError(_("Waiting for IO on epoll descriptor %d failed"),
155 m_epollDescriptor);
156 return;
157 }
158 }
159
160 for ( epoll_event *p = events; p < events + e_num; p++ )
161 {
162 wxFDIOHandler * const handler = (wxFDIOHandler *)(p->data.ptr);
163 if ( !handler )
164 {
165 wxFAIL_MSG( _T("NULL handler in epoll_event?") );
166 continue;
167 }
168
169 if ( p->events & EPOLLIN )
170 handler->OnReadWaiting();
171
172 if ( p->events & EPOLLOUT )
173 handler->OnWriteWaiting();
174
175 if ( p->events & (EPOLLERR | EPOLLHUP) )
176 handler->OnExceptionWaiting();
177 }
178 }
179
180 /* static */
181 wxEpollDispatcher *wxEpollDispatcher::Get()
182 {
183 if ( !gs_epollDispatcher )
184 {
185 gs_epollDispatcher = new wxEpollDispatcher;
186 if ( !gs_epollDispatcher->IsOk() )
187 {
188 delete gs_epollDispatcher;
189 gs_epollDispatcher = NULL;
190 }
191 }
192
193 return gs_epollDispatcher;
194 }
195
196 // ----------------------------------------------------------------------------
197 // wxEpollDispatcherModule
198 // ----------------------------------------------------------------------------
199
200 class wxEpollDispatcherModule : public wxModule
201 {
202 public:
203 wxEpollDispatcherModule() { }
204
205 virtual bool OnInit() { return true; }
206 virtual void OnExit() { wxDELETE(gs_epollDispatcher); }
207
208 DECLARE_DYNAMIC_CLASS(wxEpollDispatcherModule)
209 };
210
211 IMPLEMENT_DYNAMIC_CLASS(wxEpollDispatcherModule, wxModule)
212
213 #endif // wxUSE_EPOLL_DISPATCHER