]> git.saurik.com Git - wxWidgets.git/blame - src/common/selectdispatcher.cpp
gcc signed/unsigned warning fix
[wxWidgets.git] / src / common / selectdispatcher.cpp
CommitLineData
30c45bdd
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/socketevtdispatch.cpp
3// Purpose: implements dispatcher for select() call
4// Author: Lukasz Michalski
5// Created: December 2006
6// RCS-ID: $Id$
7// Copyright: (c) 2006 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#include "wx/private/selectdispatcher.h"
23#include "wx/module.h"
24#include "wx/timer.h"
25#include "wx/unix/private.h"
26#include "wx/log.h"
27
28#ifndef WX_PRECOMP
29 #include "wx/hash.h"
30#endif
31
32#include <sys/time.h>
33#include <unistd.h>
34
35#ifdef HAVE_SYS_SELECT_H
36# include <sys/select.h>
37#endif
38
39#define wxSelectDispatcher_Trace wxT("selectdispatcher")
40
41// ============================================================================
42// implementation
43// ============================================================================
44
45// ----------------------------------------------------------------------------
46// wxSelectDispatcher
47// ----------------------------------------------------------------------------
48
49wxSelectDispatcher* wxSelectDispatcher::ms_instance = NULL;
50
51/* static */
52wxSelectDispatcher& wxSelectDispatcher::Get()
53{
54 if ( !ms_instance )
55 ms_instance = new wxSelectDispatcher;
56 return *ms_instance;
57}
58
59void
60wxSelectDispatcher::RegisterFD(int fd, wxFDIOHandler* handler, int flags)
61{
62 if ((flags & wxSelectInput) == wxSelectInput)
63 {
64 wxFD_SET(fd, &m_readset);
65 wxLogTrace(wxSelectDispatcher_Trace,wxT("Registered fd %d for input events"),fd);
66 };
67
68 if ((flags & wxSelectOutput) == wxSelectOutput)
69 {
70 wxFD_SET(fd, &m_writeset);
71 wxLogTrace(wxSelectDispatcher_Trace,wxT("Registered fd %d for output events"),fd);
72 }
73
74 if ((flags & wxSelectException) == wxSelectException)
75 {
76 wxFD_SET(fd, &m_exeptset);
77 wxLogTrace(wxSelectDispatcher_Trace,wxT("Registered fd %d for exception events"),fd);
78 };
79
80 m_handlers[fd] = handler;
81 if (fd > m_maxFD)
82 m_maxFD = fd;
83}
84
85wxFDIOHandler*
86wxSelectDispatcher::UnregisterFD(int fd, int flags)
87{
88 // GSocket likes to unregister -1 descriptor
89 if (fd == -1)
90 return NULL;
91
92 if ((flags & wxSelectInput) == wxSelectInput)
93 {
94 wxLogTrace(wxSelectDispatcher_Trace,wxT("Unregistered fd %d from input events"),fd);
95 wxFD_CLR(fd, &m_readset);
96 }
97
98 if ((flags & wxSelectOutput) == wxSelectOutput)
99 {
100 wxLogTrace(wxSelectDispatcher_Trace,wxT("Unregistered fd %d from output events"),fd);
101 wxFD_CLR(fd, &m_writeset);
102 }
103
104 if ((flags & wxSelectException) == wxSelectException)
105 {
106 wxLogTrace(wxSelectDispatcher_Trace,wxT("Unregistered fd %d from exeption events"),fd);
107 wxFD_CLR(fd, &m_exeptset);
108 };
109
110 wxFDIOHandler* ret = NULL;
111 wxFDIOHandlerMap::const_iterator it = m_handlers.find(fd);
112 if (it != m_handlers.end())
113 {
114 ret = it->second;
115 if (!wxFD_ISSET(fd,&m_readset) && !wxFD_ISSET(fd,&m_writeset) && !wxFD_ISSET(fd,&m_exeptset))
116 {
117 m_handlers.erase(it);
118 if ( m_handlers.empty() )
119 m_maxFD = 0;
120 };
121 };
122 return ret;
123}
124
125void wxSelectDispatcher::ProcessSets(fd_set* readset, fd_set* writeset, fd_set* exeptset, int max_fd)
126{
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++ )
131 {
132 wxFDIOHandler* handler = NULL;
133 if (wxFD_ISSET(i, readset))
134 {
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);
139 else
140 {
141 wxLogError(wxT("Lost fd in read fdset: %d, removing"),i);
142 wxFD_CLR(i,&m_readset);
143 };
144 };
145
146 if (wxFD_ISSET(i, writeset))
147 {
148 wxLogTrace(wxSelectDispatcher_Trace,wxT("Got write event on fd %d"),i);
149 if (handler == NULL)
150 handler = FindHandler(i);
151 if (handler != NULL && wxFD_ISSET(i,&m_writeset))
152 handler->OnWriteWaiting(i);
153 else
154 {
155 wxLogError(wxT("Lost fd in write fdset: %d, removing"),i);
156 wxFD_CLR(i,&m_writeset);
157 };
158 };
159
160 if (wxFD_ISSET(i, exeptset))
161 {
162 wxLogTrace(wxSelectDispatcher_Trace,wxT("Got exception event on fd %d"),i);
163 if (handler == NULL)
164 handler = FindHandler(i);
165 if (handler != NULL && wxFD_ISSET(i,&m_writeset))
166 handler->OnExceptionWaiting(i);
167 else
168 {
169 wxLogError(wxT("Lost fd in exept fdset: %d, removing"),i);
170 wxFD_CLR(i,&m_exeptset);
171 };
172 };
173 };
174}
175
176wxFDIOHandler* wxSelectDispatcher::FindHandler(int fd)
177{
178 wxFDIOHandlerMap::const_iterator it = m_handlers.find(fd);
179 if (it != m_handlers.end())
180 return it->second;
181 return NULL;
182};
183
184void wxSelectDispatcher::RunLoop(int timeout)
185{
186 struct timeval tv, *ptv = NULL;
187 if ( timeout != wxSELECT_TIMEOUT_INFINITE )
188 {
189 ptv = &tv;
190 tv.tv_sec = 0;
191 tv.tv_usec = timeout*10;
192 };
193
194 int ret;
195 do
196 {
197 fd_set readset = m_readset;
198 fd_set writeset = m_writeset;
199 fd_set exeptset = m_exeptset;
200 wxStopWatch sw;
201 if ( ptv )
202 sw.Start(ptv->tv_usec/10);
203 ret = select(m_maxFD+1, &readset, &writeset, &exeptset, ptv);
204 switch ( ret )
205 {
206 // TODO: handle unix signals here
207 case -1:
208 if ( ptv )
209 {
210 ptv->tv_sec = 0;
211 ptv->tv_usec = timeout - sw.Time()*10;
212 }
213 break;
214
215 // timeout
216 case 0:
217 break;
218
219 default:
220 ProcessSets(&readset, &writeset, &exeptset, m_maxFD+1);
221 };
222 } while (ret != 0);
223}
224
225// ----------------------------------------------------------------------------
226// wxSelectDispatcherModule
227// ----------------------------------------------------------------------------
228
229class wxSelectDispatcherModule: public wxModule
230{
231public:
232 bool OnInit() { wxLog::AddTraceMask(wxSelectDispatcher_Trace); return true; }
233 void OnExit() { wxDELETE(wxSelectDispatcher::ms_instance); }
234
235private:
236 DECLARE_DYNAMIC_CLASS(wxSelectDispatcherModule)
237};
238
239IMPLEMENT_DYNAMIC_CLASS(wxSelectDispatcherModule, wxModule)
240