* Committing new wxSocket core (socket.cpp sckint.cpp). It has to be improved ...

* Adding sckint.cpp to various makefiles.
* Fixes in threadpsx.cpp (Pause/Resume)
* Fixes in threaded event dispatching
* Added Clone() to wxObject
* Implemented Clone() in wxEvent and wxSocketEvent
* wxSocket sample save the data got from the URL in test.url (this will change)
* As I only tested wxSocket on Linux Redhat 5.2 I disabled it by default on
  Windows, Mac and Unix platforms.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2289 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Guilhem Lavaux
1999-04-26 18:16:56 +00:00
parent 6a3ab8b15a
commit a737331db6
26 changed files with 1013 additions and 1190 deletions

View File

@@ -105,6 +105,22 @@ wxEvent::wxEvent(int theId)
m_isCommandEvent = FALSE;
}
wxObject *wxEvent::Clone() const
{
wxEvent *event = (wxEvent *)wxObject::Clone();
event->m_eventType = m_eventType;
event->m_eventObject = m_eventObject;
event->m_eventHandle = m_eventHandle;
event->m_timeStamp = m_timeStamp;
event->m_id = m_id;
event->m_skipped = m_skipped;
event->m_callbackUserData = m_callbackUserData;
event->m_isCommandEvent = m_isCommandEvent;
return event;
}
/*
* Command events
*
@@ -317,10 +333,10 @@ wxEvtHandler::~wxEvtHandler()
delete m_dynamicEvents;
};
#if wxUSE_THREADS
if (m_pendingEvents)
delete m_pendingEvents;
#if wxUSE_THREADS
delete m_eventsLocker;
#endif
}
@@ -337,8 +353,7 @@ bool wxEvtHandler::ProcessThreadEvent(wxEvent& event)
if (m_pendingEvents == NULL)
m_pendingEvents = new wxList();
event_main = (wxEvent *)event.GetClassInfo()->CreateObject();
*event_main = event;
event_main = (wxEvent *)event.Clone();
m_pendingEvents->Append(event_main);

View File

@@ -60,16 +60,13 @@ IMPLEMENT_PROTOCOL(wxFTP, _T("ftp"), _T("ftp"), TRUE)
wxFTP::wxFTP()
: wxProtocol()
{
wxChar tmp[256];
m_lastError = wxPROTO_NOERR;
m_streaming = FALSE;
m_user = _T("anonymous");
wxGetUserName(tmp, 256);
m_passwd.sprintf(_T("%s@"),tmp);
wxGetHostName(tmp, 256);
m_passwd += tmp;
m_passwd = wxGetUserId();
m_passwd += '@';
m_passwd += wxGetHostName();
SetNotify(0);
}
@@ -404,9 +401,12 @@ wxList *wxFTP::GetList(const wxString& wildcard)
return NULL;
}
// Ininterresting ?!
/*
sock->SetEventHandler(*GetNextHandler(), m_id);
sock->Notify(m_notifyme);
sock->SetNotify(m_neededreq);
*/
return file_list;
}

View File

@@ -116,6 +116,7 @@ void wxHTTP::SendHeaders()
bool wxHTTP::ParseHeaders()
{
wxString line;
wxStringTokenizer tokenzr;
m_headers.Clear();
m_read = TRUE;
@@ -128,17 +129,13 @@ bool wxHTTP::ParseHeaders()
if (line.Length() == 0)
break;
wxPrintf(_T("Header: %s\n"), WXSTRINGCAST line);
int pos = line.Find(':');
if (pos == -1)
printf("Header: %s\n", WXSTRINGCAST line);
tokenzr.SetString(line, " :\t\n\r");
if (!tokenzr.HasMoreToken())
return FALSE;
wxString left_str = line(0, pos);
wxString right_str = line(pos+1, line.Length());
right_str = right_str.Strip(wxString::leading);
wxString *str = new wxString(right_str);
wxString left_str = tokenzr.GetNextToken();
wxString *str = new wxString(tokenzr.GetNextToken());
m_headers.Append(left_str, (wxObject *) str);
}

View File

@@ -87,6 +87,11 @@ bool wxObject::IsKindOf(wxClassInfo *info) const
return FALSE;
}
wxObject *wxObject::Clone() const
{
return GetClassInfo()->CreateObject();
}
#if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
void wxObject::Dump(ostream& str)
{

504
src/common/sckint.cpp Normal file
View File

@@ -0,0 +1,504 @@
///////////////////////////////////////////////////////////////////////////////
// Name: socket.cpp
// Purpose: Socket handler classes
// Authors: Guilhem Lavaux (completely rewritten from a basic API of Andrew
// Davidson(1995) in wxWeb)
// Created: April 1997
// Updated: April 1999
// Copyright: (C) 1999, 1998, 1997, Guilhem Lavaux
// RCS_ID: $Id$
// License: see wxWindows license
///////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation "sckint.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_SOCKETS
#define WXSOCK_INTERNAL
#include <wx/object.h>
#include <wx/list.h>
#include <wx/socket.h>
#include <wx/thread.h>
#include <wx/sckint.h>
#ifndef __WXSTUBS__
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// -----------------------
// System specific headers
// -----------------------
#ifdef __WXMAC__
// in order to avoid problems with our c library and double definitions
#define close closesocket
#define ioctl ioctlsocket
#include <wx/mac/macsock.h>
#endif
#if defined(__WINDOWS__)
#include <winsock.h>
#endif // __WINDOWS__
#if defined(__UNIX__)
#ifdef VMS
#include <socket.h>
#else
#include <sys/socket.h>
#endif
#include <sys/ioctl.h>
#include <sys/time.h>
#include <unistd.h>
#ifdef sun
#include <sys/filio.h>
#endif
#endif // __UNIX__
#include <signal.h>
#include <errno.h>
#ifdef __VISUALC__
#include <io.h>
#endif
// Constants
#define READ_MASK wxSocketBase::REQ_READ | wxSocketBase::REQ_ACCEPT | wxSocketBase::REQ_LOST
#define WRITE_MASK wxSocketBase::REQ_WRITE | wxSocketBase::REQ_CONNECT
// --------------------------------------------------------------
// --------- SocketWaiter ---------------------------------------
// --------------------------------------------------------------
SocketWaiter::SocketWaiter(wxSocketBase *socket,
wxSocketInternal *internal)
: m_socket(socket), m_internal(internal), m_fd(internal->GetFD())
{
}
SocketWaiter::~SocketWaiter()
{
}
void SocketWaiter::ProcessReadEvent()
{
int ret;
char c;
ret = recv(m_fd, &c, 1, MSG_PEEK);
// We are a server => emit a EVT_ACCEPT event.
if (ret == -1 && m_socket->GetType() == wxSocketBase::SOCK_SERVER) {
m_socket->OnRequest(wxSocketBase::EVT_ACCEPT);
return;
}
// Else, no error => there is something to be read else
// we've lost the connection.
if (ret > 0)
m_socket->OnRequest(wxSocketBase::EVT_READ);
else {
m_socket->OnRequest(wxSocketBase::EVT_LOST);
Exit(NULL);
}
}
void SocketWaiter::ProcessWriteEvent()
{
if (m_socket->IsConnected())
m_socket->OnRequest(wxSocketBase::EVT_CONNECT);
else
m_socket->OnRequest(wxSocketBase::EVT_WRITE);
}
void *SocketWaiter::Entry()
{
struct timeval tv;
fd_set sockrd_set, sockwr_set;
wxSocketEvent event;
int ret;
while (1) {
// We won't wait.
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&sockrd_set);
FD_ZERO(&sockwr_set);
if ((m_socket->NeededReq() & READ_MASK) != 0)
FD_SET(m_fd, &sockrd_set);
if ((m_socket->NeededReq() & WRITE_MASK) != 0)
FD_SET(m_fd, &sockwr_set);
m_internal->AcquireFD();
ret = select(FD_SETSIZE, &sockrd_set, &sockwr_set, NULL, &tv);
m_internal->ReleaseFD();
if (FD_ISSET(m_fd, &sockrd_set))
ProcessReadEvent();
if (FD_ISSET(m_fd, &sockwr_set))
ProcessWriteEvent();
if (ret == 0)
// If nothing happened, we wait for 100 ms.
wxThread::Sleep(10);
else
wxThread::Yield();
// Check whether we should exit.
if (TestDestroy())
return NULL;
}
return NULL;
}
// --------------------------------------------------------------
// --------- SocketRequester ------------------------------------
// --------------------------------------------------------------
SocketRequester::SocketRequester(wxSocketBase *socket,
wxSocketInternal *internal)
: m_socket(socket), m_internal(internal), m_fd(internal->GetFD())
{
}
SocketRequester::~SocketRequester()
{
}
bool SocketRequester::WaitFor(wxSocketBase::wxRequestNotify req, int millisec)
{
int ret;
struct timeval tv;
fd_set sockrd_set, sockwr_set;
// We won't wait.
tv.tv_sec = millisec / 1000;
tv.tv_usec = (millisec % 1000) * 1000;
if ((req & READ_MASK) != 0)
FD_ZERO(&sockrd_set);
FD_ZERO(&sockwr_set);
FD_SET(m_fd, &sockrd_set);
FD_SET(m_fd, &sockwr_set);
m_internal->AcquireFD();
ret = select(FD_SETSIZE, &sockrd_set, &sockwr_set, NULL, &tv);
m_internal->ReleaseFD();
return (ret != 0);
}
void SocketRequester::ProcessReadEvent(SockRequest *req)
{
int ret;
size_t len;
// We'll wait for the first byte, in case a "timeout event" occurs it returns // immediately
if (!WaitFor(wxSocketBase::REQ_READ, req->timeout)) {
m_internal->EndRequest(req);
return;
}
m_internal->AcquireFD();
ret = recv(m_fd, req->buffer, req->size,
(req->type == wxSocketBase::REQ_PEEK) ? MSG_PEEK : 0);
m_internal->ReleaseFD();
// An error occured, we exit.
if (ret < 0) {
req->error = errno;
m_internal->EndRequest(req);
return;
}
len = ret;
// If the buffer isn't full (and we want it to be full), we don't unqueue it.
if ((len < req->size) && (m_socket->GetFlags() & wxSocketBase::WAITALL)) {
req->size -= len;
req->io_nbytes += len;
req->buffer += len;
return;
}
// The End.
req->io_nbytes += len;
m_internal->EndRequest(req);
}
void SocketRequester::ProcessWriteEvent(SockRequest *req)
{
int ret;
size_t len;
m_internal->AcquireFD();
ret = send(m_fd, req->buffer, req->size, 0);
m_internal->ReleaseFD();
if (ret < 0) {
req->error = errno;
m_internal->EndRequest(req);
return;
}
len = ret;
if ((len < req->size) && ((m_socket->GetFlags() & wxSocketBase::WAITALL) != 0)) {
req->size -= len;
req->io_nbytes += len;
req->buffer += len;
return;
}
req->io_nbytes += len;
m_internal->EndRequest(req);
}
void SocketRequester::ProcessWaitEvent(SockRequest *req)
{
if (WaitFor(req->type, req->timeout))
req->io_nbytes = 1; // We put 1 in the counter to tell the requester
// there is no timeout.
else
req->io_nbytes = 0;
m_internal->EndRequest(req);
}
void *SocketRequester::Entry()
{
SockRequest *req;
while (1) {
// Wait for a new request or a destroy message.
req = m_internal->WaitForReq();
if (TestDestroy() || req == NULL)
return NULL;
if ((req->type & wxSocketBase::REQ_WAIT) != 0) {
ProcessWaitEvent(req);
continue;
}
switch (req->type) {
case wxSocketBase::REQ_READ:
case wxSocketBase::REQ_PEEK:
ProcessReadEvent(req);
break;
case wxSocketBase::REQ_WRITE:
ProcessWriteEvent(req);
break;
}
}
return NULL;
}
// --------------------------------------------------------------
// --------- wxSocketInternal -----------------------------------
// --------------------------------------------------------------
wxSocketInternal::wxSocketInternal(wxSocketBase *socket)
{
m_socket = socket;
m_thread_waiter = new SocketWaiter(socket, this);
m_thread_requester = new SocketRequester(socket, this);
m_request_locker.Lock();
}
wxSocketInternal::~wxSocketInternal()
{
wxASSERT(!m_finalized);
m_request_locker.Unlock();
delete m_thread_waiter;
delete m_thread_requester;
}
// ----------------------------------------------------------------------
// WaitForReq: it is called by SocketRequester and should return the next
// socket request if available
// ----------------------------------------------------------------------
SockRequest *wxSocketInternal::WaitForReq()
{
wxNode *node;
node = m_requests.First();
if (node == NULL) {
m_socket_cond.Wait(m_request_locker);
node = m_requests.First();
if (node == NULL)
return NULL;
}
return (SockRequest *)node->Data();
}
// ----------------------------------------------------------------------
// EndRequest: Should be called to finalize a request
// ----------------------------------------------------------------------
void wxSocketInternal::EndRequest(SockRequest *req)
{
wxNode *node = NULL;
req->done = TRUE;
node = m_requests.Member((wxObject *)req);
if (node != NULL)
delete node;
}
void wxSocketInternal::AcquireFD()
{
m_fd_locker.Lock();
}
void wxSocketInternal::ReleaseFD()
{
m_fd_locker.Unlock();
}
// ----------------------------------------------------------------------
// InitializeSocket: called by wxSocketBase to initialize the daemons with
// a new file descriptor and to create them
// ----------------------------------------------------------------------
void wxSocketInternal::InitializeSocket()
{
wxASSERT( ((m_thread_waiter->IsAlive() && !m_thread_waiter->IsPaused()) ||
(m_thread_requester->IsAlive() && !m_thread_requester->IsPaused())));
m_thread_waiter->m_fd = m_socket->m_fd;
m_thread_requester->m_fd = m_socket->m_fd;
if (m_thread_waiter->IsPaused())
ResumeSocket();
else {
if (m_thread_waiter->Create() != wxTHREAD_NO_ERROR) {
// Something should be done here.
return;
}
if (m_thread_requester->Create() != wxTHREAD_NO_ERROR) {
// Something should be done here.
return;
}
m_thread_waiter->Run();
m_thread_requester->Run();
}
}
// ----------------------------------------------------------------------
// InitializeSocket: called by wxSocketBase to destroy daemons
// ----------------------------------------------------------------------
void wxSocketInternal::FinalizeSocket()
{
wxASSERT( (!m_thread_waiter->IsAlive() && !m_thread_requester->IsAlive()) );
ResumeSocket();
m_thread_waiter->Delete();
m_socket_locker.Lock();
if (m_requests.Number() == 0)
m_socket_cond.Signal();
m_socket_locker.Unlock();
m_thread_requester->Delete();
}
void wxSocketInternal::PauseSocket()
{
if (m_thread_waiter != NULL && !m_thread_waiter->IsPaused())
m_thread_waiter->Pause();
}
void wxSocketInternal::ResumeSocket()
{
if (m_thread_waiter != NULL && m_thread_waiter->IsPaused())
m_thread_waiter->Resume();
}
void wxSocketInternal::EnableWaiter()
{
if (m_thread_waiter != NULL && m_thread_waiter->IsPaused())
m_thread_waiter->Resume();
}
void wxSocketInternal::DisableWaiter()
{
if (m_thread_waiter != NULL && !m_thread_waiter->IsPaused())
m_thread_waiter->Pause();
}
// ----------------------------------------------------------------------
// QueueRequest:
// ----------------------------------------------------------------------
void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
{
if (async) {
m_request_locker.Lock();
request->done = FALSE;
m_requests.Append((wxObject *)request);
m_request_locker.Unlock();
// Wake up
m_socket_cond.Signal();
if (request->wait) {
if (wxThread::IsMain())
while (!request->done) {
wxYield();
}
else
while (!request->done) {
wxThread::Yield();
}
}
} else {
m_request_locker.Lock();
if ((request->type & wxSocketBase::REQ_WAIT) != 0) {
m_thread_requester->ProcessWaitEvent(request);
} else {
request->done = FALSE;
switch (request->type) {
case wxSocketBase::REQ_PEEK:
case wxSocketBase::REQ_READ:
m_thread_requester->ProcessReadEvent(request);
break;
case wxSocketBase::REQ_WRITE:
m_thread_requester->ProcessWriteEvent(request);
break;
}
}
request->done = TRUE;
m_request_locker.Unlock();
}
}
void wxSocketInternal::WaitForEnd(SockRequest *request)
{
// TODOTODO
}
#endif
// __WXSTUBS__
#endif
// wxUSE_SOCKETS

File diff suppressed because it is too large Load Diff

View File

@@ -63,6 +63,7 @@ LIB_CPP_SRC=\
common/valtext.cpp \
common/variant.cpp \
common/socket.cpp \
common/sckint.cpp \
common/sckaddr.cpp \
common/sckipc.cpp \
common/protocol.cpp \

View File

@@ -1402,4 +1402,4 @@ wxApp::macAdjustCursor()
}
}
}
*/
*/

View File

@@ -1402,4 +1402,4 @@ wxApp::macAdjustCursor()
}
}
}
*/
*/

View File

@@ -62,6 +62,7 @@ LIB_CPP_SRC=\
../common/variant.cpp \
../common/wxexpr.cpp \
../common/socket.cpp \
../common/sckint.cpp \
../common/sckaddr.cpp \
../common/sckipc.cpp \
../common/protocol.cpp \

View File

@@ -62,6 +62,7 @@ LIB_CPP_SRC=\
../common/variant.cpp \
../common/wxexpr.cpp \
../common/socket.cpp \
../common/sckint.cpp \
../common/sckaddr.cpp \
../common/sckipc.cpp \
../common/protocol.cpp \

View File

@@ -151,6 +151,7 @@ COMMONOBJS = \
$(MSWDIR)\dynlib.obj \
$(MSWDIR)\tokenzr.obj \
$(MSWDIR)\socket.obj \
$(MSWDIR)\sckint.obj \
$(MSWDIR)\sckaddr.obj \
$(MSWDIR)\protocol.obj \
$(MSWDIR)\url.obj \

View File

@@ -77,6 +77,7 @@ COMMONOBJS = cmndata.obj \
paper.obj \
string.obj \
socket.obj \
sckint.obj \
sckaddr.obj \
sckfile.obj \
sckipc.obj \
@@ -628,6 +629,9 @@ string.obj: $(COMMDIR)\string.cpp
socket.obj: $(COMMDIR)\socket.cpp
$(CCC) $(CPPFLAGS) $(IFLAGS) $(COMMDIR)\socket.cpp /BINARY socket.obj
sckint.obj: $(COMMDIR)\sckint.cpp
$(CCC) $(CPPFLAGS) $(IFLAGS) $(COMMDIR)\sckint.cpp /BINARY sckint.obj
sckaddr.obj: $(COMMDIR)\sckaddr.cpp
$(CCC) $(CPPFLAGS) $(IFLAGS) $(COMMDIR)\sckaddr.cpp /BINARY sckaddr.obj

View File

@@ -141,6 +141,7 @@ COMMONOBJS = \
..\common\$D\paper.obj \
..\common\$D\string.obj \
..\common\$D\socket.obj \
..\common\$D\socket.obj \
..\common\$D\sckaddr.obj \
..\common\$D\sckfile.obj \
..\common\$D\sckipc.obj \

View File

@@ -664,6 +664,13 @@ bool wxThread::IsAlive() const
(p_internal->GetState() == STATE_PAUSED);
}
bool wxThread::IsPaused() const
{
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
return (p_internal->GetState() == STATE_PAUSED);
}
bool wxThread::TestDestroy()
{
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);

View File

@@ -325,7 +325,8 @@ wxThreadInternal::wxThreadInternal()
wxThreadInternal::~wxThreadInternal()
{
m_mutexSuspend.Unlock();
// GL: moved to SignalExit
// m_mutexSuspend.Unlock();
// note that m_mutex will be unlocked by the thread which waits for our
// termination
@@ -375,6 +376,9 @@ void wxThreadInternal::Wait()
void wxThreadInternal::SignalExit()
{
// GL: Unlock mutexSuspend here.
m_mutexSuspend.Unlock();
// as mutex is currently locked, this will block until some other thread
// (normally the same which created this one) unlocks it by entering Wait()
m_mutex.Lock();
@@ -453,9 +457,7 @@ wxThread::wxThread()
wxThreadError wxThread::Create()
{
// Maybe we could think about recreate the thread once it has exited.
if (p_internal->GetState() != STATE_NEW &&
p_internal->GetState() != STATE_EXITED)
if (p_internal->GetState() != STATE_NEW)
return wxTHREAD_RUNNING;
// set up the thread attribute: right now, we only set thread priority
@@ -590,7 +592,9 @@ wxThreadError wxThread::Resume()
if ( p_internal->GetState() == STATE_PAUSED )
{
m_critsect.Leave();
p_internal->Resume();
m_critsect.Enter();
return wxTHREAD_NO_ERROR;
}
@@ -727,6 +731,13 @@ bool wxThread::IsAlive() const
}
}
bool wxThread::IsPaused() const
{
wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
return (p_internal->GetState() == STATE_PAUSED);
}
//--------------------------------------------------------------------
// wxThreadModule
//--------------------------------------------------------------------