do not require a running event loop, even under MSW, for the sockets to work: if the user code doesn't use events there is no reason for it to run the event loop, especially as it's not needed under the other platforms; instead use the same Select() implementation as under Unix under MSW too and, to avoid duplicating it, put it into the new GSocketBase class

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@56923 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-11-23 00:11:09 +00:00
parent b245cbc587
commit f0db5d7587
7 changed files with 202 additions and 212 deletions

View File

@@ -154,6 +154,50 @@ private:
static GSocketManager *ms_manager; static GSocketManager *ms_manager;
}; };
/*
Base class providing functionality common to BSD and Winsock sockets.
TODO: merge this in wxSocket itself, there is no reason to maintain the
separation between wxSocket and GSocket.
*/
class GSocketBase
{
public:
GSocketEventFlags Select(GSocketEventFlags flags);
#ifdef __WINDOWS__
SOCKET m_fd;
#else
int m_fd;
#endif
bool m_ok;
int m_initialRecvBufferSize;
int m_initialSendBufferSize;
GAddress *m_local;
GAddress *m_peer;
GSocketError m_error;
bool m_non_blocking;
bool m_server;
bool m_stream;
bool m_establishing;
bool m_reusable;
bool m_broadcast;
bool m_dobind;
#ifdef __WINDOWS__
struct timeval m_timeout;
#else
unsigned long m_timeout;
#endif
GSocketEventFlags m_detected;
GSocketCallback m_cbacks[GSOCK_MAX_EVENT];
char *m_data[GSOCK_MAX_EVENT];
};
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
#include "wx/msw/gsockmsw.h" #include "wx/msw/gsockmsw.h"
#else #else
@@ -246,6 +290,50 @@ GSocketError _GAddress_Init_UNIX(GAddress *address);
GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path); GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path);
GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf); GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf);
// standard linux headers produce many warnings when used with icc
#if defined(__INTELC__) && defined(__LINUX__)
inline void wxFD_ZERO(fd_set *fds)
{
#pragma warning(push)
#pragma warning(disable:593)
FD_ZERO(fds);
#pragma warning(pop)
}
inline void wxFD_SET(int fd, fd_set *fds)
{
#pragma warning(push, 1)
#pragma warning(disable:1469)
FD_SET(fd, fds);
#pragma warning(pop)
}
inline bool wxFD_ISSET(int fd, fd_set *fds)
{
#pragma warning(push, 1)
#pragma warning(disable:1469)
return FD_ISSET(fd, fds);
#pragma warning(pop)
}
inline bool wxFD_CLR(int fd, fd_set *fds)
{
#pragma warning(push, 1)
#pragma warning(disable:1469)
return FD_CLR(fd, fds);
#pragma warning(pop)
}
#else // !__INTELC__
#define wxFD_ZERO(fds) FD_ZERO(fds)
#define wxFD_SET(fd, fds) FD_SET(fd, fds)
#define wxFD_ISSET(fd, fds) FD_ISSET(fd, fds)
#define wxFD_CLR(fd, fds) FD_CLR(fd, fds)
#endif // __INTELC__/!__INTELC__
// this is for Windows where configure doesn't define this
#ifndef SOCKOPTLEN_T
#define SOCKOPTLEN_T int
#endif
#endif /* wxUSE_SOCKETS */ #endif /* wxUSE_SOCKETS */
#endif /* _WX_GSOCKET_H_ */ #endif /* _WX_GSOCKET_H_ */

View File

@@ -24,7 +24,7 @@
#endif #endif
/* Definition of GSocket */ /* Definition of GSocket */
class GSocket class GSocket : public GSocketBase
{ {
public: public:
GSocket(); GSocket();
@@ -47,7 +47,6 @@ public:
GSocketError SetNonOriented(); GSocketError SetNonOriented();
int Read(char *buffer, int size); int Read(char *buffer, int size);
int Write(const char *buffer, int size); int Write(const char *buffer, int size);
GSocketEventFlags Select(GSocketEventFlags flags);
void SetNonBlocking(bool non_block); void SetNonBlocking(bool non_block);
void SetTimeout(unsigned long millis); void SetTimeout(unsigned long millis);
GSocketError WXDLLIMPEXP_NET GetError(); GSocketError WXDLLIMPEXP_NET GetError();
@@ -73,31 +72,10 @@ protected:
int Recv_Dgram(char *buffer, int size); int Recv_Dgram(char *buffer, int size);
int Send_Stream(const char *buffer, int size); int Send_Stream(const char *buffer, int size);
int Send_Dgram(const char *buffer, int size); int Send_Dgram(const char *buffer, int size);
bool m_ok;
int m_initialRecvBufferSize;
int m_initialSendBufferSize;
/* TODO: Make these protected */ /* TODO: Make these protected */
public: public:
SOCKET m_fd;
GAddress *m_local;
GAddress *m_peer;
GSocketError m_error;
/* Attributes */
bool m_non_blocking;
bool m_server;
bool m_stream;
bool m_establishing;
bool m_reusable;
bool m_broadcast;
bool m_dobind;
struct timeval m_timeout;
/* Callbacks */
GSocketEventFlags m_detected;
GSocketCallback m_cbacks[GSOCK_MAX_EVENT];
char *m_data[GSOCK_MAX_EVENT];
int m_msgnumber; int m_msgnumber;
}; };

View File

@@ -13,7 +13,7 @@
class wxGSocketIOHandler; class wxGSocketIOHandler;
class GSocket class GSocket : public GSocketBase
{ {
public: public:
GSocket(); GSocket();
@@ -34,7 +34,6 @@ public:
GSocketError SetNonOriented(); GSocketError SetNonOriented();
int Read(char *buffer, int size); int Read(char *buffer, int size);
int Write(const char *buffer, int size); int Write(const char *buffer, int size);
GSocketEventFlags Select(GSocketEventFlags flags);
void SetNonBlocking(bool non_block); void SetNonBlocking(bool non_block);
void SetTimeout(unsigned long millisec); void SetTimeout(unsigned long millisec);
GSocketError WXDLLIMPEXP_NET GetError(); GSocketError WXDLLIMPEXP_NET GetError();
@@ -66,35 +65,14 @@ protected:
int Recv_Dgram(char *buffer, int size); int Recv_Dgram(char *buffer, int size);
int Send_Stream(const char *buffer, int size); int Send_Stream(const char *buffer, int size);
int Send_Dgram(const char *buffer, int size); int Send_Dgram(const char *buffer, int size);
bool m_ok;
int m_initialRecvBufferSize;
int m_initialSendBufferSize;
public: public:
/* DFE: We can't protect these data member until the GUI code is updated */ /* DFE: We can't protect these data member until the GUI code is updated */
/* protected: */ /* protected: */
int m_fd;
wxGSocketIOHandler *m_handler; wxGSocketIOHandler *m_handler;
GAddress *m_local;
GAddress *m_peer;
GSocketError m_error;
bool m_non_blocking;
bool m_server;
bool m_stream;
bool m_establishing;
bool m_reusable;
bool m_broadcast;
bool m_dobind;
unsigned long m_timeout;
// true if socket should fire events // true if socket should fire events
bool m_use_events; bool m_use_events;
/* Callbacks */
GSocketEventFlags m_detected;
GSocketCallback m_cbacks[GSOCK_MAX_EVENT];
char *m_data[GSOCK_MAX_EVENT];
// pointer for storing extra (usually GUI-specific) data // pointer for storing extra (usually GUI-specific) data
void *m_gui_dependent; void *m_gui_dependent;
}; };

View File

@@ -11,45 +11,9 @@
#ifndef _WX_UNIX_PRIVATE_H_ #ifndef _WX_UNIX_PRIVATE_H_
#define _WX_UNIX_PRIVATE_H_ #define _WX_UNIX_PRIVATE_H_
// standard linux headers produce many warnings when used with icc // this file is currently empty as its original contents was moved to
#if defined(__INTELC__) && defined(__LINUX__) // include/wx/gsocket.h but let's keep it for now in case we need it for
inline void wxFD_ZERO(fd_set *fds) // something again in the future
{
#pragma warning(push)
#pragma warning(disable:593)
FD_ZERO(fds);
#pragma warning(pop)
}
inline void wxFD_SET(int fd, fd_set *fds)
{
#pragma warning(push, 1)
#pragma warning(disable:1469)
FD_SET(fd, fds);
#pragma warning(pop)
}
inline bool wxFD_ISSET(int fd, fd_set *fds)
{
#pragma warning(push, 1)
#pragma warning(disable:1469)
return FD_ISSET(fd, fds);
#pragma warning(pop)
}
inline bool wxFD_CLR(int fd, fd_set *fds)
{
#pragma warning(push, 1)
#pragma warning(disable:1469)
return FD_CLR(fd, fds);
#pragma warning(pop)
}
#else // !__INTELC__
#define wxFD_ZERO(fds) FD_ZERO(fds)
#define wxFD_SET(fd, fds) FD_SET(fd, fds)
#define wxFD_ISSET(fd, fds) FD_ISSET(fd, fds)
#define wxFD_CLR(fd, fds) FD_CLR(fd, fds)
#endif // __INTELC__/!__INTELC__
#endif // _WX_UNIX_PRIVATE_H_ #endif // _WX_UNIX_PRIVATE_H_

View File

@@ -720,6 +720,112 @@ wxSocketBase& wxSocketBase::Discard()
// Wait functions // Wait functions
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
/* GSocket_Select:
* Polls the socket to determine its status. This function will
* check for the events specified in the 'flags' parameter, and
* it will return a mask indicating which operations can be
* performed. This function won't block, regardless of the
* mode (blocking | nonblocking) of the socket.
*/
GSocketEventFlags GSocketBase::Select(GSocketEventFlags flags)
{
assert(this);
GSocketEventFlags result = 0;
fd_set readfds;
fd_set writefds;
fd_set exceptfds;
struct timeval tv;
if (m_fd == -1)
return (GSOCK_LOST_FLAG & flags);
/* Do not use a static struct, Linux can garble it */
tv.tv_sec = 0;
tv.tv_usec = 0;
wxFD_ZERO(&readfds);
wxFD_ZERO(&writefds);
wxFD_ZERO(&exceptfds);
wxFD_SET(m_fd, &readfds);
if (flags & GSOCK_OUTPUT_FLAG || flags & GSOCK_CONNECTION_FLAG)
wxFD_SET(m_fd, &writefds);
wxFD_SET(m_fd, &exceptfds);
/* Check 'sticky' CONNECTION flag first */
result |= GSOCK_CONNECTION_FLAG & m_detected;
/* If we have already detected a LOST event, then don't try
* to do any further processing.
*/
if ((m_detected & GSOCK_LOST_FLAG) != 0)
{
m_establishing = false;
return (GSOCK_LOST_FLAG & flags);
}
/* Try select now */
if (select(m_fd + 1, &readfds, &writefds, &exceptfds, &tv) < 0)
{
/* What to do here? */
return (result & flags);
}
/* Check for exceptions and errors */
if (wxFD_ISSET(m_fd, &exceptfds))
{
m_establishing = false;
m_detected = GSOCK_LOST_FLAG;
/* LOST event: Abort any further processing */
return (GSOCK_LOST_FLAG & flags);
}
/* Check for readability */
if (wxFD_ISSET(m_fd, &readfds))
{
result |= GSOCK_INPUT_FLAG;
if (m_server && m_stream)
{
/* This is a TCP server socket that detected a connection.
While the INPUT_FLAG is also set, it doesn't matter on
this kind of sockets, as we can only Accept() from them. */
m_detected |= GSOCK_CONNECTION_FLAG;
}
}
/* Check for writability */
if (wxFD_ISSET(m_fd, &writefds))
{
if (m_establishing && !m_server)
{
int error;
SOCKOPTLEN_T len = sizeof(error);
m_establishing = false;
getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
if (error)
{
m_detected = GSOCK_LOST_FLAG;
/* LOST event: Abort any further processing */
return (GSOCK_LOST_FLAG & flags);
}
else
{
m_detected |= GSOCK_CONNECTION_FLAG;
}
}
else
{
result |= GSOCK_OUTPUT_FLAG;
}
}
return (result | m_detected) & flags;
}
// All Wait functions poll the socket using GSocket_Select() to // All Wait functions poll the socket using GSocket_Select() to
// check for the specified combination of conditions, until one // check for the specified combination of conditions, until one
// of these conditions become true, an error occurs, or the // of these conditions become true, an error occurs, or the
@@ -749,11 +855,6 @@ wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags)
if ( wxIsMainThread() ) if ( wxIsMainThread() )
{ {
eventLoop = wxEventLoop::GetActive(); eventLoop = wxEventLoop::GetActive();
#ifdef __WXMSW__
wxASSERT_MSG( eventLoop,
"Sockets won't work without a running event loop" );
#endif // __WXMSW__
} }
else // in worker thread else // in worker thread
{ {
@@ -808,10 +909,9 @@ wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags)
if ( eventLoop ) if ( eventLoop )
{ {
// Dispatch the events when we run in the main thread and have an // This function is only called if wxSOCKET_BLOCK flag was not used
// active event loop: without this sockets don't work at all under // and so we should dispatch the events if there is an event loop
// MSW as socket flags are only updated when socket messages are // capable of doing it.
// processed.
if ( eventLoop->Pending() ) if ( eventLoop->Pending() )
eventLoop->Dispatch(); eventLoop->Dispatch();
} }

View File

@@ -776,18 +776,6 @@ int GSocket::Write(const char *buffer, int size)
return ret; return ret;
} }
/* GSocket_Select:
* Polls the socket to determine its status. This function will
* check for the events specified in the 'flags' parameter, and
* it will return a mask indicating which operations can be
* performed. This function won't block, regardless of the
* mode (blocking | nonblocking) of the socket.
*/
GSocketEventFlags GSocket::Select(GSocketEventFlags flags)
{
return flags & m_detected;
}
/* Attributes */ /* Attributes */
/* GSocket_SetNonBlocking: /* GSocket_SetNonBlocking:

View File

@@ -1285,112 +1285,6 @@ int GSocket::Write(const char *buffer, int size)
return ret; return ret;
} }
/* GSocket_Select:
* Polls the socket to determine its status. This function will
* check for the events specified in the 'flags' parameter, and
* it will return a mask indicating which operations can be
* performed. This function won't block, regardless of the
* mode (blocking | nonblocking) of the socket.
*/
GSocketEventFlags GSocket::Select(GSocketEventFlags flags)
{
assert(this);
GSocketEventFlags result = 0;
fd_set readfds;
fd_set writefds;
fd_set exceptfds;
struct timeval tv;
if (m_fd == -1)
return (GSOCK_LOST_FLAG & flags);
/* Do not use a static struct, Linux can garble it */
tv.tv_sec = 0;
tv.tv_usec = 0;
wxFD_ZERO(&readfds);
wxFD_ZERO(&writefds);
wxFD_ZERO(&exceptfds);
wxFD_SET(m_fd, &readfds);
if (flags & GSOCK_OUTPUT_FLAG || flags & GSOCK_CONNECTION_FLAG)
wxFD_SET(m_fd, &writefds);
wxFD_SET(m_fd, &exceptfds);
/* Check 'sticky' CONNECTION flag first */
result |= GSOCK_CONNECTION_FLAG & m_detected;
/* If we have already detected a LOST event, then don't try
* to do any further processing.
*/
if ((m_detected & GSOCK_LOST_FLAG) != 0)
{
m_establishing = false;
return (GSOCK_LOST_FLAG & flags);
}
/* Try select now */
if (select(m_fd + 1, &readfds, &writefds, &exceptfds, &tv) < 0)
{
/* What to do here? */
return (result & flags);
}
/* Check for exceptions and errors */
if (wxFD_ISSET(m_fd, &exceptfds))
{
m_establishing = false;
m_detected = GSOCK_LOST_FLAG;
/* LOST event: Abort any further processing */
return (GSOCK_LOST_FLAG & flags);
}
/* Check for readability */
if (wxFD_ISSET(m_fd, &readfds))
{
result |= GSOCK_INPUT_FLAG;
if (m_server && m_stream)
{
/* This is a TCP server socket that detected a connection.
While the INPUT_FLAG is also set, it doesn't matter on
this kind of sockets, as we can only Accept() from them. */
m_detected |= GSOCK_CONNECTION_FLAG;
}
}
/* Check for writability */
if (wxFD_ISSET(m_fd, &writefds))
{
if (m_establishing && !m_server)
{
int error;
SOCKOPTLEN_T len = sizeof(error);
m_establishing = false;
getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
if (error)
{
m_detected = GSOCK_LOST_FLAG;
/* LOST event: Abort any further processing */
return (GSOCK_LOST_FLAG & flags);
}
else
{
m_detected |= GSOCK_CONNECTION_FLAG;
}
}
else
{
result |= GSOCK_OUTPUT_FLAG;
}
}
return (result | m_detected) & flags;
}
/* Flags */ /* Flags */
/* GSocket_SetNonBlocking: /* GSocket_SetNonBlocking: