X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ba9838b9916db818f00480b1e77caf82031fb99d..f79fd1e54b4533507c6de798eecfdde765a3fc4e:/src/common/sckint.cpp?ds=sidebyside diff --git a/src/common/sckint.cpp b/src/common/sckint.cpp index de4284bd35..6483df8ee8 100644 --- a/src/common/sckint.cpp +++ b/src/common/sckint.cpp @@ -1,10 +1,9 @@ /////////////////////////////////////////////////////////////////////////////// -// 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 +// Name: sckint.cpp +// Purpose: Socket internal classes +// Authors: Guilhem Lavaux +// Created: April 1999 +// Updated: // Copyright: (C) 1999, 1998, 1997, Guilhem Lavaux // RCS_ID: $Id$ // License: see wxWindows license @@ -23,11 +22,18 @@ #if wxUSE_SOCKETS #define WXSOCK_INTERNAL -#include -#include -#include -#include -#include +#include "wx/object.h" +#include "wx/list.h" +#include "wx/socket.h" +#include "wx/thread.h" +#include "wx/sckint.h" +#include "wx/sckint.h" +#include "wx/utils.h" + +// IRIX requires bstring.h be included to use select() +#ifdef sgi + #include +#endif // IRIX #ifndef __WXSTUBS__ @@ -87,7 +93,8 @@ #if wxUSE_THREADS SocketWaiter::SocketWaiter(wxSocketBase *socket, wxSocketInternal *internal) - : m_socket(socket), m_internal(internal), m_fd(internal->GetFD()) + : wxThread(), + m_socket(socket), m_internal(internal), m_fd(internal->GetFD()) { } @@ -100,7 +107,9 @@ void SocketWaiter::ProcessReadEvent() int ret; char c; + m_internal->AcquireFD(); ret = recv(m_fd, &c, 1, MSG_PEEK); + m_internal->ReleaseFD(); // We are a server => emit a EVT_ACCEPT event. if (ret == -1 && m_socket->GetType() == wxSocketBase::SOCK_SERVER) { @@ -110,10 +119,11 @@ void SocketWaiter::ProcessReadEvent() // Else, no error => there is something to be read else // we've lost the connection. - if (ret > 0) + if (ret > 0) { m_socket->OnRequest(wxSocketBase::EVT_READ); - else { + } else { m_socket->OnRequest(wxSocketBase::EVT_LOST); + m_internal->ReleaseData(); // In that case, we mustn't forget to unlock the mutex. Exit(NULL); } } @@ -140,14 +150,16 @@ void *SocketWaiter::Entry() FD_ZERO(&sockrd_set); FD_ZERO(&sockwr_set); - + + m_internal->AcquireData(); + 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); + ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv); m_internal->ReleaseFD(); if (FD_ISSET(m_fd, &sockrd_set)) @@ -156,20 +168,20 @@ void *SocketWaiter::Entry() if (FD_ISSET(m_fd, &sockwr_set)) ProcessWriteEvent(); + m_internal->ReleaseData(); + #if wxUSE_THREADS #ifdef Yield #undef Yield #endif #endif - if (ret == 0) - // If nothing happened, we wait for 100 ms. - wxUsleep(10); + // We wait for 100 ms to prevent the CPU from burning. + wxUsleep(100); // Check whether we should exit. - if (TestDestroy()) { + if (TestDestroy()) return NULL; - } } return NULL; } @@ -180,7 +192,11 @@ void *SocketWaiter::Entry() SocketRequester::SocketRequester(wxSocketBase *socket, wxSocketInternal *internal) - : m_socket(socket), m_internal(internal), m_fd(internal->GetFD()) + : +#if wxUSE_THREADS + wxThread(), +#endif + m_socket(socket), m_internal(internal), m_fd(internal->GetFD()) { } @@ -198,15 +214,15 @@ bool SocketRequester::WaitFor(wxSocketBase::wxRequestNotify req, int millisec) tv.tv_sec = millisec / 1000; tv.tv_usec = (millisec % 1000) * 1000; - if ((req & READ_MASK) != 0) - FD_ZERO(&sockrd_set); + FD_ZERO(&sockrd_set); FD_ZERO(&sockwr_set); - - FD_SET(m_fd, &sockrd_set); - FD_SET(m_fd, &sockwr_set); + if ((req & READ_MASK) != 0) + FD_SET(m_fd, &sockrd_set); + if ((req & WRITE_MASK) != 0) + FD_SET(m_fd, &sockwr_set); m_internal->AcquireFD(); - ret = select(FD_SETSIZE, &sockrd_set, &sockwr_set, NULL, &tv); + ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv); m_internal->ReleaseFD(); return (ret != 0); @@ -241,6 +257,9 @@ void SocketRequester::ProcessReadEvent(SockRequest *req) req->size -= len; req->io_nbytes += len; req->buffer += len; + + if (len == 0) + m_internal->EndRequest(req); return; } // The End. @@ -253,6 +272,11 @@ void SocketRequester::ProcessWriteEvent(SockRequest *req) int ret; size_t len; + if (!WaitFor(wxSocketBase::REQ_WRITE, req->timeout)) { + m_internal->EndRequest(req); + return; + } + m_internal->AcquireFD(); ret = send(m_fd, req->buffer, req->size, 0); m_internal->ReleaseFD(); @@ -287,13 +311,15 @@ void *SocketRequester::Entry() { SockRequest *req; + m_internal->m_request_locker.Lock(); while (1) { // Wait for a new request or a destroy message. req = m_internal->WaitForReq(); m_internal->m_end_requester.Lock(); - if (TestDestroy() || req == NULL) { + if (req == NULL) { m_internal->m_invalid_requester = TRUE; m_internal->m_end_requester.Unlock(); + m_internal->m_request_locker.Unlock(); return NULL; } m_internal->m_end_requester.Unlock(); @@ -324,23 +350,17 @@ void *SocketRequester::Entry() wxSocketInternal::wxSocketInternal(wxSocketBase *socket) { m_socket = socket; -#if wxUSE_THREADS m_thread_requester = NULL; m_thread_waiter = NULL; m_invalid_requester = TRUE; - m_request_locker.Lock(); -#endif } wxSocketInternal::~wxSocketInternal() { -#if wxUSE_THREADS StopRequester(); wxASSERT(m_thread_requester == NULL); StopWaiter(); wxASSERT(m_thread_waiter == NULL); - m_request_locker.Unlock(); -#endif } // ---------------------------------------------------------------------- @@ -352,10 +372,12 @@ SockRequest *wxSocketInternal::WaitForReq() #if wxUSE_THREADS wxNode *node; + // First try. node = m_requests.First(); if (node == NULL) { - m_socket_cond.Wait(m_request_locker, 1, 0); + m_socket_cond.Wait(m_request_locker, 10, 0); + // Second try, if it is unsuccessul we give up. node = m_requests.First(); if (node == NULL) return NULL; @@ -381,6 +403,20 @@ void wxSocketInternal::EndRequest(SockRequest *req) delete node; } +void wxSocketInternal::AcquireData() +{ +#if wxUSE_THREADS + m_socket_locker.Lock(); +#endif +} + +void wxSocketInternal::ReleaseData() +{ +#if wxUSE_THREADS + m_socket_locker.Unlock(); +#endif +} + void wxSocketInternal::AcquireFD() { #if wxUSE_THREADS @@ -400,52 +436,69 @@ void wxSocketInternal::ResumeRequester() #if wxUSE_THREADS wxThreadError err; - wxASSERT(m_thread_requester == NULL); + wxASSERT(m_invalid_requester); m_end_requester.Lock(); - if (m_invalid_requester) { + + if (m_thread_requester != NULL) { + m_thread_requester->Delete(); // We must join it. delete m_thread_requester; + } - m_thread_requester = new SocketRequester(m_socket, this); - m_thread_requester->m_fd = m_socket->m_fd; + m_invalid_requester = FALSE; - err = m_thread_requester->Create(); - wxASSERT(err == wxTHREAD_NO_ERROR); + m_end_requester.Unlock(); - err = m_thread_requester->Run(); - wxASSERT(err == wxTHREAD_NO_ERROR); + m_thread_requester = new SocketRequester(m_socket, this); - m_invalid_requester = FALSE; - } - m_end_requester.Unlock(); + err = m_thread_requester->Create(); + wxASSERT(err == wxTHREAD_NO_ERROR); + + err = m_thread_requester->Run(); + wxASSERT(err == wxTHREAD_NO_ERROR); +#else + if (!m_invalid_requester) + return; + m_thread_requester = new SocketRequester(m_socket, this); + m_invalid_requester = FALSE; #endif } void wxSocketInternal::StopRequester() { #if wxUSE_THREADS + m_end_requester.Lock(); if (m_invalid_requester) { - delete m_thread_requester; - m_thread_requester = NULL; - m_invalid_requester = FALSE; + m_end_requester.Unlock(); + if (m_thread_requester) { + m_thread_requester->Delete(); + delete m_thread_requester; + m_thread_requester = NULL; + } + m_invalid_requester = TRUE; return; } + m_end_requester.Unlock(); wxASSERT(m_thread_requester != NULL); - m_socket_locker.Lock(); + m_request_locker.Lock(); // Send a signal to the requester. - if (m_requests.Number() == 0) - m_socket_cond.Signal(); + m_socket_cond.Signal(); - m_socket_locker.Unlock(); + m_request_locker.Unlock(); // Finish the destruction of the requester. m_thread_requester->Delete(); delete m_thread_requester; m_thread_requester = NULL; + m_invalid_requester = TRUE; +#else + delete m_thread_requester; + m_thread_requester = NULL; + m_invalid_requester = TRUE; #endif } @@ -458,7 +511,8 @@ void wxSocketInternal::ResumeWaiter() return; m_thread_waiter = new SocketWaiter(m_socket, this); - m_thread_waiter->m_fd = m_socket->m_fd; + + m_thread_waiter->SetPriority(WXTHREAD_MIN_PRIORITY); err = m_thread_waiter->Create(); wxASSERT(err == wxTHREAD_NO_ERROR); @@ -486,10 +540,11 @@ void wxSocketInternal::StopWaiter() // ---------------------------------------------------------------------- void wxSocketInternal::QueueRequest(SockRequest *request, bool async) { + if (m_invalid_requester) + ResumeRequester(); + #if wxUSE_THREADS if (async) { - if (m_thread_requester == NULL) - ResumeRequester(); m_request_locker.Lock(); request->done = FALSE; @@ -511,6 +566,7 @@ void wxSocketInternal::QueueRequest(SockRequest *request, bool async) } } else { m_request_locker.Lock(); +#endif if ((request->type & wxSocketBase::REQ_WAIT) != 0) { m_thread_requester->ProcessWaitEvent(request); @@ -529,6 +585,7 @@ void wxSocketInternal::QueueRequest(SockRequest *request, bool async) } } request->done = TRUE; +#if wxUSE_THREADS m_request_locker.Unlock(); } #endif