1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/socketevtdispatch.cpp
3 // Purpose: implements dispatcher for select() call
4 // Author: Lukasz Michalski
5 // Created: December 2006
7 // Copyright: (c) 2006 Lukasz Michalski
8 // License: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
22 #include "wx/private/selectdispatcher.h"
23 #include "wx/module.h"
25 #include "wx/unix/private.h"
35 #ifdef HAVE_SYS_SELECT_H
36 # include <sys/select.h>
39 #define wxSelectDispatcher_Trace wxT("selectdispatcher")
41 // ============================================================================
43 // ============================================================================
45 // ----------------------------------------------------------------------------
47 // ----------------------------------------------------------------------------
49 wxSelectDispatcher
* wxSelectDispatcher::ms_instance
= NULL
;
52 wxSelectDispatcher
& wxSelectDispatcher::Get()
55 ms_instance
= new wxSelectDispatcher
;
60 wxSelectDispatcher::RegisterFD(int fd
, wxFDIOHandler
* handler
, int flags
)
62 if ((flags
& wxSelectInput
) == wxSelectInput
)
64 wxFD_SET(fd
, &m_readset
);
65 wxLogTrace(wxSelectDispatcher_Trace
,wxT("Registered fd %d for input events"),fd
);
68 if ((flags
& wxSelectOutput
) == wxSelectOutput
)
70 wxFD_SET(fd
, &m_writeset
);
71 wxLogTrace(wxSelectDispatcher_Trace
,wxT("Registered fd %d for output events"),fd
);
74 if ((flags
& wxSelectException
) == wxSelectException
)
76 wxFD_SET(fd
, &m_exeptset
);
77 wxLogTrace(wxSelectDispatcher_Trace
,wxT("Registered fd %d for exception events"),fd
);
80 m_handlers
[fd
] = handler
;
86 wxSelectDispatcher::UnregisterFD(int fd
, int flags
)
88 // GSocket likes to unregister -1 descriptor
92 if ((flags
& wxSelectInput
) == wxSelectInput
)
94 wxLogTrace(wxSelectDispatcher_Trace
,wxT("Unregistered fd %d from input events"),fd
);
95 wxFD_CLR(fd
, &m_readset
);
98 if ((flags
& wxSelectOutput
) == wxSelectOutput
)
100 wxLogTrace(wxSelectDispatcher_Trace
,wxT("Unregistered fd %d from output events"),fd
);
101 wxFD_CLR(fd
, &m_writeset
);
104 if ((flags
& wxSelectException
) == wxSelectException
)
106 wxLogTrace(wxSelectDispatcher_Trace
,wxT("Unregistered fd %d from exeption events"),fd
);
107 wxFD_CLR(fd
, &m_exeptset
);
110 wxFDIOHandler
* ret
= NULL
;
111 wxFDIOHandlerMap::const_iterator it
= m_handlers
.find(fd
);
112 if (it
!= m_handlers
.end())
115 if (!wxFD_ISSET(fd
,&m_readset
) && !wxFD_ISSET(fd
,&m_writeset
) && !wxFD_ISSET(fd
,&m_exeptset
))
117 m_handlers
.erase(it
);
118 if ( m_handlers
.empty() )
125 void wxSelectDispatcher::ProcessSets(fd_set
* readset
, fd_set
* writeset
, fd_set
* exeptset
, int max_fd
)
127 // it is safe to remove handler from onXXX methods,
128 // if you unregister descriptor first.
129 wxFDIOHandlerMap::const_iterator it
= m_handlers
.begin();
130 for ( int i
= 0; i
< max_fd
; i
++ )
132 wxFDIOHandler
* handler
= NULL
;
133 if (wxFD_ISSET(i
, readset
))
135 wxLogTrace(wxSelectDispatcher_Trace
,wxT("Got read event on fd %d"),i
);
136 handler
= FindHandler(i
);
137 if (handler
!= NULL
&& wxFD_ISSET(i
,&m_readset
))
138 handler
->OnReadWaiting(i
);
141 wxLogError(wxT("Lost fd in read fdset: %d, removing"),i
);
142 wxFD_CLR(i
,&m_readset
);
146 if (wxFD_ISSET(i
, writeset
))
148 wxLogTrace(wxSelectDispatcher_Trace
,wxT("Got write event on fd %d"),i
);
150 handler
= FindHandler(i
);
151 if (handler
!= NULL
&& wxFD_ISSET(i
,&m_writeset
))
152 handler
->OnWriteWaiting(i
);
155 wxLogError(wxT("Lost fd in write fdset: %d, removing"),i
);
156 wxFD_CLR(i
,&m_writeset
);
160 if (wxFD_ISSET(i
, exeptset
))
162 wxLogTrace(wxSelectDispatcher_Trace
,wxT("Got exception event on fd %d"),i
);
164 handler
= FindHandler(i
);
165 if (handler
!= NULL
&& wxFD_ISSET(i
,&m_writeset
))
166 handler
->OnExceptionWaiting(i
);
169 wxLogError(wxT("Lost fd in exept fdset: %d, removing"),i
);
170 wxFD_CLR(i
,&m_exeptset
);
176 wxFDIOHandler
* wxSelectDispatcher::FindHandler(int fd
)
178 wxFDIOHandlerMap::const_iterator it
= m_handlers
.find(fd
);
179 if (it
!= m_handlers
.end())
184 void wxSelectDispatcher::RunLoop(int timeout
)
186 struct timeval tv
, *ptv
= NULL
;
187 if ( timeout
!= wxSELECT_TIMEOUT_INFINITE
)
191 tv
.tv_usec
= timeout
*10;
197 fd_set readset
= m_readset
;
198 fd_set writeset
= m_writeset
;
199 fd_set exeptset
= m_exeptset
;
201 if ( ptv
&& timeout
)
202 sw
.Start(ptv
->tv_usec
/10);
203 ret
= select(m_maxFD
+1, &readset
, &writeset
, &exeptset
, ptv
);
206 // TODO: handle unix signals here
210 // it doesn't make sense to remain here
217 ptv
->tv_usec
= timeout
- sw
.Time()*10;
226 ProcessSets(&readset
, &writeset
, &exeptset
, m_maxFD
+1);
231 // ----------------------------------------------------------------------------
232 // wxSelectDispatcherModule
233 // ----------------------------------------------------------------------------
235 class wxSelectDispatcherModule
: public wxModule
238 bool OnInit() { wxLog::AddTraceMask(wxSelectDispatcher_Trace
); return true; }
239 void OnExit() { wxDELETE(wxSelectDispatcher::ms_instance
); }
242 DECLARE_DYNAMIC_CLASS(wxSelectDispatcherModule
)
245 IMPLEMENT_DYNAMIC_CLASS(wxSelectDispatcherModule
, wxModule
)