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