]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/selectdispatcher.cpp
Fix harmless gcc warning about uninitialized mask in PNG saving code.
[wxWidgets.git] / src / common / selectdispatcher.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/selectdispatcher.cpp
3// Purpose: implements dispatcher for select() call
4// Author: Lukasz Michalski and Vadim Zeitlin
5// Created: December 2006
6// RCS-ID: $Id$
7// Copyright: (c) 2006 Lukasz Michalski
8// Licence: 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 __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#if wxUSE_SELECT_DISPATCHER
27
28#include "wx/private/selectdispatcher.h"
29#include "wx/unix/private.h"
30
31#ifndef WX_PRECOMP
32 #include "wx/hash.h"
33 #include "wx/log.h"
34 #include "wx/intl.h"
35#endif
36
37#include <errno.h>
38
39#define wxSelectDispatcher_Trace wxT("selectdispatcher")
40
41// ============================================================================
42// implementation
43// ============================================================================
44
45// ----------------------------------------------------------------------------
46// wxSelectSets
47// ----------------------------------------------------------------------------
48
49int wxSelectSets::ms_flags[wxSelectSets::Max] =
50{
51 wxFDIO_INPUT,
52 wxFDIO_OUTPUT,
53 wxFDIO_EXCEPTION,
54};
55
56const char *wxSelectSets::ms_names[wxSelectSets::Max] =
57{
58 "input",
59 "output",
60 "exceptional",
61};
62
63wxSelectSets::Callback wxSelectSets::ms_handlers[wxSelectSets::Max] =
64{
65 &wxFDIOHandler::OnReadWaiting,
66 &wxFDIOHandler::OnWriteWaiting,
67 &wxFDIOHandler::OnExceptionWaiting,
68};
69
70wxSelectSets::wxSelectSets()
71{
72 for ( int n = 0; n < Max; n++ )
73 {
74 wxFD_ZERO(&m_fds[n]);
75 }
76}
77
78bool wxSelectSets::HasFD(int fd) const
79{
80 for ( int n = 0; n < Max; n++ )
81 {
82 if ( wxFD_ISSET(fd, (fd_set*) &m_fds[n]) )
83 return true;
84 }
85
86 return false;
87}
88
89bool wxSelectSets::SetFD(int fd, int flags)
90{
91 wxCHECK_MSG( fd >= 0, false, wxT("invalid descriptor") );
92
93 for ( int n = 0; n < Max; n++ )
94 {
95 if ( flags & ms_flags[n] )
96 {
97 wxFD_SET(fd, &m_fds[n]);
98 }
99 else if ( wxFD_ISSET(fd, (fd_set*) &m_fds[n]) )
100 {
101 wxFD_CLR(fd, &m_fds[n]);
102 }
103 }
104
105 return true;
106}
107
108int wxSelectSets::Select(int nfds, struct timeval *tv)
109{
110 return select(nfds, &m_fds[Read], &m_fds[Write], &m_fds[Except], tv);
111}
112
113bool wxSelectSets::Handle(int fd, wxFDIOHandler& handler) const
114{
115 for ( int n = 0; n < Max; n++ )
116 {
117 if ( wxFD_ISSET(fd, (fd_set*) &m_fds[n]) )
118 {
119 wxLogTrace(wxSelectDispatcher_Trace,
120 wxT("Got %s event on fd %d"), ms_names[n], fd);
121 (handler.*ms_handlers[n])();
122 // callback can modify sets and destroy handler
123 // this forces that one event can be processed at one time
124 return true;
125 }
126 }
127
128 return false;
129}
130
131// ----------------------------------------------------------------------------
132// wxSelectDispatcher
133// ----------------------------------------------------------------------------
134
135bool wxSelectDispatcher::RegisterFD(int fd, wxFDIOHandler *handler, int flags)
136{
137 if ( !wxMappedFDIODispatcher::RegisterFD(fd, handler, flags) )
138 return false;
139
140 if ( !m_sets.SetFD(fd, flags) )
141 return false;
142
143 if ( fd > m_maxFD )
144 m_maxFD = fd;
145
146 wxLogTrace(wxSelectDispatcher_Trace,
147 wxT("Registered fd %d: input:%d, output:%d, exceptional:%d"), fd, (flags & wxFDIO_INPUT) == wxFDIO_INPUT, (flags & wxFDIO_OUTPUT), (flags & wxFDIO_EXCEPTION) == wxFDIO_EXCEPTION);
148 return true;
149}
150
151bool wxSelectDispatcher::ModifyFD(int fd, wxFDIOHandler *handler, int flags)
152{
153 if ( !wxMappedFDIODispatcher::ModifyFD(fd, handler, flags) )
154 return false;
155
156 wxASSERT_MSG( fd <= m_maxFD, wxT("logic error: registered fd > m_maxFD?") );
157
158 wxLogTrace(wxSelectDispatcher_Trace,
159 wxT("Modified fd %d: input:%d, output:%d, exceptional:%d"), fd, (flags & wxFDIO_INPUT) == wxFDIO_INPUT, (flags & wxFDIO_OUTPUT) == wxFDIO_OUTPUT, (flags & wxFDIO_EXCEPTION) == wxFDIO_EXCEPTION);
160 return m_sets.SetFD(fd, flags);
161}
162
163bool wxSelectDispatcher::UnregisterFD(int fd)
164{
165 m_sets.ClearFD(fd);
166
167 if ( !wxMappedFDIODispatcher::UnregisterFD(fd) )
168 return false;
169
170 // remove the handler if we don't need it any more
171 if ( !m_sets.HasFD(fd) )
172 {
173 if ( fd == m_maxFD )
174 {
175 // need to find new max fd
176 m_maxFD = -1;
177 for ( wxFDIOHandlerMap::const_iterator it = m_handlers.begin();
178 it != m_handlers.end();
179 ++it )
180 {
181 if ( it->first > m_maxFD )
182 {
183 m_maxFD = it->first;
184 }
185 }
186 }
187 }
188
189 wxLogTrace(wxSelectDispatcher_Trace,
190 wxT("Removed fd %d, current max: %d"), fd, m_maxFD);
191 return true;
192}
193
194int wxSelectDispatcher::ProcessSets(const wxSelectSets& sets)
195{
196 int numEvents = 0;
197 for ( int fd = 0; fd <= m_maxFD; fd++ )
198 {
199 if ( !sets.HasFD(fd) )
200 continue;
201
202 wxFDIOHandler * const handler = FindHandler(fd);
203 if ( !handler )
204 {
205 wxFAIL_MSG( wxT("NULL handler in wxSelectDispatcher?") );
206 continue;
207 }
208
209 if ( sets.Handle(fd, *handler) )
210 numEvents++;
211 }
212
213 return numEvents;
214}
215
216int wxSelectDispatcher::DoSelect(wxSelectSets& sets, int timeout) const
217{
218 struct timeval tv,
219 *ptv;
220 if ( timeout != TIMEOUT_INFINITE )
221 {
222 ptv = &tv;
223 tv.tv_sec = timeout / 1000;
224 tv.tv_usec = (timeout % 1000)*1000;
225 }
226 else // no timeout
227 {
228 ptv = NULL;
229 }
230
231 int ret = sets.Select(m_maxFD + 1, ptv);
232
233 // TODO: we need to restart select() in this case but for now just return
234 // as if timeout expired
235 if ( ret == -1 && errno == EINTR )
236 ret = 0;
237
238 return ret;
239}
240
241bool wxSelectDispatcher::HasPending() const
242{
243 wxSelectSets sets(m_sets);
244 return DoSelect(sets, 0) > 0;
245}
246
247int wxSelectDispatcher::Dispatch(int timeout)
248{
249 wxSelectSets sets(m_sets);
250 switch ( DoSelect(sets, timeout) )
251 {
252 case -1:
253 wxLogSysError(_("Failed to monitor I/O channels"));
254 return -1;
255
256 case 0:
257 // timeout expired without anything happening
258 return 0;
259
260 default:
261 return ProcessSets(sets);
262 }
263}
264
265#endif // wxUSE_SELECT_DISPATCHER