]> git.saurik.com Git - wxWidgets.git/blame - src/common/socketevtdispatch.cpp
fix bug with not updating the last line correctly when a group was deleted and recrea...
[wxWidgets.git] / src / common / socketevtdispatch.cpp
CommitLineData
6b44a335
VS
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/socketevtdispatch.cpp
3// Purpose: implements wxSocketEventDispatcher for platforms with no
4// socket events notification
5// Author: Angel Vidal
6// Modified by:
7// Created: 08.24.06
8// RCS-ID: $Id$
9// Copyright: (c) 2006 Angel vidal
10// License: wxWindows licence
11///////////////////////////////////////////////////////////////////////////////
12
13// ============================================================================
14// declarations
15// ============================================================================
16
17// ----------------------------------------------------------------------------
18// headers
19// ----------------------------------------------------------------------------
20
21// for compilers that support precompilation, includes "wx.h".
22#include "wx/wxprec.h"
23
24#if wxUSE_SOCKETS
25
26#include "wx/private/socketevtdispatch.h"
27#include "wx/module.h"
28#include "wx/unix/private.h"
29#include "wx/gsocket.h"
30#include "wx/unix/gsockunx.h"
31
32#ifndef WX_PRECOMP
33 #include "wx/hash.h"
34#endif
35
36#include <sys/time.h>
37#include <unistd.h>
38
39#ifdef HAVE_SYS_SELECT_H
40# include <sys/select.h>
41#endif
42
43// ============================================================================
44// implementation
45// ============================================================================
46
47// ----------------------------------------------------------------------------
48// wxSocketEventDispatcherEntry
49// ----------------------------------------------------------------------------
50
51class wxSocketEventDispatcherEntry: public wxObject
52{
53 public:
54 wxSocketEventDispatcherEntry()
55 {
56 m_fdInput = -1; m_fdOutput = -1;
57 m_socket = NULL;
58 }
59
60 int m_fdInput;
61 int m_fdOutput;
62 GSocket* m_socket;
63};
64
65// ----------------------------------------------------------------------------
66// wxSocketEventDispatcher
67// ----------------------------------------------------------------------------
68
69wxSocketEventDispatcher* wxSocketEventDispatcher::ms_instance = NULL;
70
71/* static */
72wxSocketEventDispatcher& wxSocketEventDispatcher::Get()
73{
74 if ( !ms_instance )
75 ms_instance = new wxSocketEventDispatcher;
76 return *ms_instance;
77}
78
79wxSocketEventDispatcherEntry* wxSocketEventDispatcher::FindEntry(int fd)
80{
81 wxSocketEventDispatcherEntry* entry =
82 (wxSocketEventDispatcherEntry*) wxHashTable::Get(fd);
83 return entry;
84}
85
86void
87wxSocketEventDispatcher::RegisterCallback(int fd,
88 wxSocketEventDispatcherType socketType,
89 GSocket* socket)
90{
91 wxSocketEventDispatcherEntry* entry = FindEntry(fd);
92 if (!entry)
93 {
94 entry = new wxSocketEventDispatcherEntry();
95 Put(fd, entry);
96 }
97
98 if (socketType == wxSocketEventDispatcherInput)
99 entry->m_fdInput = fd;
100 else
101 entry->m_fdOutput = fd;
102
103 entry->m_socket = socket;
104}
105
106void
107wxSocketEventDispatcher::UnregisterCallback(int fd,
108 wxSocketEventDispatcherType socketType)
109{
110 wxSocketEventDispatcherEntry* entry = FindEntry(fd);
111 if (entry)
112 {
113 if (socketType == wxSocketEventDispatcherInput)
114 entry->m_fdInput = -1;
115 else
116 entry->m_fdOutput = -1;
117
118 if (entry->m_fdInput == -1 && entry->m_fdOutput == -1)
119 {
120 entry->m_socket = NULL;
121 Delete(fd);
122 delete entry;
123 }
124 }
125}
126
127int wxSocketEventDispatcher::FillSets(fd_set* readset, fd_set* writeset)
128{
129 int max_fd = 0;
130
131 wxFD_ZERO(readset);
132 wxFD_ZERO(writeset);
133
134 BeginFind();
135 wxHashTable::compatibility_iterator node = Next();
136 while (node)
137 {
138 wxSocketEventDispatcherEntry* entry =
139 (wxSocketEventDispatcherEntry*) node->GetData();
140
141 if (entry->m_fdInput != -1)
142 {
143 wxFD_SET(entry->m_fdInput, readset);
144 if (entry->m_fdInput > max_fd)
145 max_fd = entry->m_fdInput;
146 }
147
148 if (entry->m_fdOutput != -1)
149 {
150 wxFD_SET(entry->m_fdOutput, writeset);
151 if (entry->m_fdOutput > max_fd)
152 max_fd = entry->m_fdOutput;
153 }
154
155 node = Next();
156 }
157
158 return max_fd;
159}
160
161void wxSocketEventDispatcher::AddEvents(fd_set* readset, fd_set* writeset)
162{
163 BeginFind();
164 wxHashTable::compatibility_iterator node = Next();
165 while (node)
166 {
167 // We have to store the next node here, because the event processing can
168 // destroy the object before we call Next()
169
170 wxHashTable::compatibility_iterator next_node = Next();
171
172 wxSocketEventDispatcherEntry* entry =
173 (wxSocketEventDispatcherEntry*) node->GetData();
174
175 wxCHECK_RET(entry->m_socket, wxT("Critical: Processing a NULL socket in wxSocketEventDispatcher"));
176
177 if (entry->m_fdInput != -1 && wxFD_ISSET(entry->m_fdInput, readset))
178 entry->m_socket->Detected_Read();
179
180 if (entry->m_fdOutput != -1 && wxFD_ISSET(entry->m_fdOutput, writeset))
181 entry->m_socket->Detected_Write();;
182
183 node = next_node;
184 }
185}
186
187void wxSocketEventDispatcher::RunLoop(int timeout)
188{
189 struct timeval tv;
190 tv.tv_sec = 0;
191 tv.tv_usec = timeout;
192 fd_set readset;
193 fd_set writeset;
194
195 int max_fd = FillSets( &readset, &writeset);
196 if (select( max_fd+1, &readset, &writeset, NULL, &tv ) == 0)
197 {
198 // No socket input/output. Don't add events.
199 return;
200 }
201 else
202 {
203 AddEvents(&readset, &writeset);
204 }
205}
206
207// ----------------------------------------------------------------------------
208// wxSocketEventDispatcherModule
209// ----------------------------------------------------------------------------
210
211class wxSocketEventDispatcherModule: public wxModule
212{
213public:
214 bool OnInit() { return true; }
215 void OnExit() { wxDELETE(wxSocketEventDispatcher::ms_instance); }
216
217private:
218 DECLARE_DYNAMIC_CLASS(wxSocketEventDispatcherModule)
219};
220
221IMPLEMENT_DYNAMIC_CLASS(wxSocketEventDispatcherModule, wxModule)
222
223
224// ----------------------------------------------------------------------------
225// GSocket interface
226// ----------------------------------------------------------------------------
227
228bool GSocketGUIFunctionsTableConcrete::CanUseEventLoop()
229{
230 return true;
231}
232
233bool GSocketGUIFunctionsTableConcrete::OnInit(void)
234{
235 return 1;
236}
237
238void GSocketGUIFunctionsTableConcrete::OnExit(void)
239{
240}
241
242bool GSocketGUIFunctionsTableConcrete::Init_Socket(GSocket *socket)
243{
244 int *m_id;
245
246 socket->m_gui_dependent = (char *)malloc(sizeof(int)*2);
247 m_id = (int *)(socket->m_gui_dependent);
248
249 m_id[0] = -1;
250 m_id[1] = -1;
251
252 return true;
253}
254
255void GSocketGUIFunctionsTableConcrete::Destroy_Socket(GSocket *socket)
256{
257 free(socket->m_gui_dependent);
258}
259
260void GSocketGUIFunctionsTableConcrete::Install_Callback(GSocket *socket,
261 GSocketEvent event)
262{
263 int *m_id = (int *)(socket->m_gui_dependent);
264 int c;
265
266 if (socket->m_fd == -1)
267 return;
268
269 switch (event)
270 {
271 case GSOCK_LOST: /* fall-through */
272 case GSOCK_INPUT: c = 0; break;
273 case GSOCK_OUTPUT: c = 1; break;
274 case GSOCK_CONNECTION: c = ((socket->m_server) ? 0 : 1); break;
275 default: return;
276 }
277
278#if 0
279 if (m_id[c] != -1)
280 XtRemoveInput(m_id[c]);
281#endif /* 0 */
282
283 if (c == 0)
284 {
285 m_id[0] = socket->m_fd;
286
287 wxSocketEventDispatcher::Get().RegisterCallback(
288 socket->m_fd, wxSocketEventDispatcherInput, socket);
289 }
290 else
291 {
292 m_id[1] = socket->m_fd;
293
294 wxSocketEventDispatcher::Get().RegisterCallback(
295 socket->m_fd, wxSocketEventDispatcherOutput, socket);
296 }
297}
298
299void GSocketGUIFunctionsTableConcrete::Uninstall_Callback(GSocket *socket,
300 GSocketEvent event)
301{
302 int *m_id = (int *)(socket->m_gui_dependent);
303 int c;
304
305 switch (event)
306 {
307 case GSOCK_LOST: /* fall-through */
308 case GSOCK_INPUT: c = 0; break;
309 case GSOCK_OUTPUT: c = 1; break;
310 case GSOCK_CONNECTION: c = ((socket->m_server) ? 0 : 1); break;
311 default: return;
312 }
313
314 if (m_id[c] != -1)
315 {
316 if (c == 0)
317 wxSocketEventDispatcher::Get().UnregisterCallback(
318 m_id[c], wxSocketEventDispatcherInput);
319 else
320 wxSocketEventDispatcher::Get().UnregisterCallback(
321 m_id[c], wxSocketEventDispatcherOutput);
322 }
323
324 m_id[c] = -1;
325}
326
327void GSocketGUIFunctionsTableConcrete::Enable_Events(GSocket *socket)
328{
329 Install_Callback(socket, GSOCK_INPUT);
330 Install_Callback(socket, GSOCK_OUTPUT);
331}
332
333void GSocketGUIFunctionsTableConcrete::Disable_Events(GSocket *socket)
334{
335 Uninstall_Callback(socket, GSOCK_INPUT);
336 Uninstall_Callback(socket, GSOCK_OUTPUT);
337}
338
339#endif // wxUSE_SOCKETS