]>
git.saurik.com Git - wxWidgets.git/blob - src/common/selectdispatcher.cpp
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 // Copyright: (c) 2006 Lukasz Michalski
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 // for compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
25 #if wxUSE_SELECT_DISPATCHER
27 #include "wx/private/selectdispatcher.h"
28 #include "wx/unix/private.h"
38 #define wxSelectDispatcher_Trace wxT("selectdispatcher")
40 // ============================================================================
42 // ============================================================================
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 int wxSelectSets::ms_flags
[wxSelectSets::Max
] =
55 const char *wxSelectSets::ms_names
[wxSelectSets::Max
] =
62 wxSelectSets::Callback
wxSelectSets::ms_handlers
[wxSelectSets::Max
] =
64 &wxFDIOHandler::OnReadWaiting
,
65 &wxFDIOHandler::OnWriteWaiting
,
66 &wxFDIOHandler::OnExceptionWaiting
,
69 wxSelectSets::wxSelectSets()
71 for ( int n
= 0; n
< Max
; n
++ )
77 bool wxSelectSets::HasFD(int fd
) const
79 for ( int n
= 0; n
< Max
; n
++ )
81 if ( wxFD_ISSET(fd
, (fd_set
*) &m_fds
[n
]) )
88 bool wxSelectSets::SetFD(int fd
, int flags
)
90 wxCHECK_MSG( fd
>= 0, false, wxT("invalid descriptor") );
92 for ( int n
= 0; n
< Max
; n
++ )
94 if ( flags
& ms_flags
[n
] )
96 wxFD_SET(fd
, &m_fds
[n
]);
98 else if ( wxFD_ISSET(fd
, (fd_set
*) &m_fds
[n
]) )
100 wxFD_CLR(fd
, &m_fds
[n
]);
107 int wxSelectSets::Select(int nfds
, struct timeval
*tv
)
109 return select(nfds
, &m_fds
[Read
], &m_fds
[Write
], &m_fds
[Except
], tv
);
112 bool wxSelectSets::Handle(int fd
, wxFDIOHandler
& handler
) const
114 for ( int n
= 0; n
< Max
; n
++ )
116 if ( wxFD_ISSET(fd
, (fd_set
*) &m_fds
[n
]) )
118 wxLogTrace(wxSelectDispatcher_Trace
,
119 wxT("Got %s event on fd %d"), ms_names
[n
], fd
);
120 (handler
.*ms_handlers
[n
])();
121 // callback can modify sets and destroy handler
122 // this forces that one event can be processed at one time
130 // ----------------------------------------------------------------------------
131 // wxSelectDispatcher
132 // ----------------------------------------------------------------------------
134 bool wxSelectDispatcher::RegisterFD(int fd
, wxFDIOHandler
*handler
, int flags
)
136 if ( !wxMappedFDIODispatcher::RegisterFD(fd
, handler
, flags
) )
139 if ( !m_sets
.SetFD(fd
, flags
) )
145 wxLogTrace(wxSelectDispatcher_Trace
,
146 wxT("Registered fd %d: input:%d, output:%d, exceptional:%d"), fd
, (flags
& wxFDIO_INPUT
) == wxFDIO_INPUT
, (flags
& wxFDIO_OUTPUT
), (flags
& wxFDIO_EXCEPTION
) == wxFDIO_EXCEPTION
);
150 bool wxSelectDispatcher::ModifyFD(int fd
, wxFDIOHandler
*handler
, int flags
)
152 if ( !wxMappedFDIODispatcher::ModifyFD(fd
, handler
, flags
) )
155 wxASSERT_MSG( fd
<= m_maxFD
, wxT("logic error: registered fd > m_maxFD?") );
157 wxLogTrace(wxSelectDispatcher_Trace
,
158 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
);
159 return m_sets
.SetFD(fd
, flags
);
162 bool wxSelectDispatcher::UnregisterFD(int fd
)
166 if ( !wxMappedFDIODispatcher::UnregisterFD(fd
) )
169 // remove the handler if we don't need it any more
170 if ( !m_sets
.HasFD(fd
) )
174 // need to find new max fd
176 for ( wxFDIOHandlerMap::const_iterator it
= m_handlers
.begin();
177 it
!= m_handlers
.end();
180 if ( it
->first
> m_maxFD
)
188 wxLogTrace(wxSelectDispatcher_Trace
,
189 wxT("Removed fd %d, current max: %d"), fd
, m_maxFD
);
193 int wxSelectDispatcher::ProcessSets(const wxSelectSets
& sets
)
196 for ( int fd
= 0; fd
<= m_maxFD
; fd
++ )
198 if ( !sets
.HasFD(fd
) )
201 wxFDIOHandler
* const handler
= FindHandler(fd
);
204 wxFAIL_MSG( wxT("NULL handler in wxSelectDispatcher?") );
208 if ( sets
.Handle(fd
, *handler
) )
215 int wxSelectDispatcher::DoSelect(wxSelectSets
& sets
, int timeout
) const
219 if ( timeout
!= TIMEOUT_INFINITE
)
222 tv
.tv_sec
= timeout
/ 1000;
223 tv
.tv_usec
= (timeout
% 1000)*1000;
230 int ret
= sets
.Select(m_maxFD
+ 1, ptv
);
232 // TODO: we need to restart select() in this case but for now just return
233 // as if timeout expired
234 if ( ret
== -1 && errno
== EINTR
)
240 bool wxSelectDispatcher::HasPending() const
242 wxSelectSets
sets(m_sets
);
243 return DoSelect(sets
, 0) > 0;
246 int wxSelectDispatcher::Dispatch(int timeout
)
248 wxSelectSets
sets(m_sets
);
249 switch ( DoSelect(sets
, timeout
) )
252 wxLogSysError(_("Failed to monitor I/O channels"));
256 // timeout expired without anything happening
260 return ProcessSets(sets
);
264 #endif // wxUSE_SELECT_DISPATCHER