X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/70190256155c4b5efcc9062bf29bb4ef6e1f4473..86fdd27b451ec92f4573f125fec73c44421ee744:/src/common/sckint.cpp diff --git a/src/common/sckint.cpp b/src/common/sckint.cpp index a8699b5859..dd17b9bdf6 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 @@ -84,9 +83,11 @@ // --------- SocketWaiter --------------------------------------- // -------------------------------------------------------------- +#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()) { } @@ -109,10 +110,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); } } @@ -139,14 +141,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)) @@ -155,28 +159,23 @@ 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. - wxThread::Sleep(10); - else - wxThread::Yield(); -#else if (ret == 0) // If nothing happened, we wait for 100 ms. wxUsleep(10); - else - wxYield(); -#endif // Check whether we should exit. - if (TestDestroy()) + if (TestDestroy()) { return NULL; - } + } + } return NULL; } @@ -186,7 +185,8 @@ void *SocketWaiter::Entry() SocketRequester::SocketRequester(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()) { } @@ -212,7 +212,7 @@ bool SocketRequester::WaitFor(wxSocketBase::wxRequestNotify req, int millisec) 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); @@ -259,6 +259,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(); @@ -293,11 +298,18 @@ 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(); - if (TestDestroy() || req == NULL) + m_internal->m_end_requester.Lock(); + 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(); if ((req->type & wxSocketBase::REQ_WAIT) != 0) { ProcessWaitEvent(req); @@ -316,6 +328,7 @@ void *SocketRequester::Entry() } return NULL; } +#endif // -------------------------------------------------------------- // --------- wxSocketInternal ----------------------------------- @@ -324,17 +337,21 @@ void *SocketRequester::Entry() 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(); +#if wxUSE_THREADS + m_thread_requester = NULL; + m_thread_waiter = NULL; + m_invalid_requester = TRUE; +#endif } wxSocketInternal::~wxSocketInternal() { -// wxASSERT(!m_finalized); there is no m_finalized anywhere, RR - m_request_locker.Unlock(); - delete m_thread_waiter; - delete m_thread_requester; +#if wxUSE_THREADS + StopRequester(); + wxASSERT(m_thread_requester == NULL); + StopWaiter(); + wxASSERT(m_thread_waiter == NULL); +#endif } // ---------------------------------------------------------------------- @@ -343,11 +360,12 @@ wxSocketInternal::~wxSocketInternal() // ---------------------------------------------------------------------- SockRequest *wxSocketInternal::WaitForReq() { +#if wxUSE_THREADS wxNode *node; node = m_requests.First(); if (node == NULL) { - m_socket_cond.Wait(m_request_locker); + m_socket_cond.Wait(m_request_locker, 10, 0); node = m_requests.First(); if (node == NULL) @@ -355,6 +373,9 @@ SockRequest *wxSocketInternal::WaitForReq() } return (SockRequest *)node->Data(); +#else + return NULL; +#endif } // ---------------------------------------------------------------------- @@ -371,88 +392,121 @@ 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 m_fd_locker.Lock(); +#endif } void wxSocketInternal::ReleaseFD() { +#if wxUSE_THREADS m_fd_locker.Unlock(); +#endif } -// ---------------------------------------------------------------------- -// InitializeSocket: called by wxSocketBase to initialize the daemons with -// a new file descriptor and to create them -// ---------------------------------------------------------------------- -void wxSocketInternal::InitializeSocket() +void wxSocketInternal::ResumeRequester() { -// wxASSERT( ((m_thread_waiter->IsAlive() && !m_thread_waiter->IsPaused()) || -// (m_thread_requester->IsAlive() && !m_thread_requester->IsPaused()))); +#if wxUSE_THREADS + wxThreadError err; - m_thread_waiter->m_fd = m_socket->m_fd; - m_thread_requester->m_fd = m_socket->m_fd; + wxASSERT(m_thread_requester == NULL || m_invalid_requester); - if (m_thread_waiter->IsPaused()) - ResumeSocket(); - else { + m_end_requester.Lock(); + if (m_invalid_requester) { + if (m_thread_requester != NULL) + delete m_thread_requester; + m_invalid_requester = FALSE; + } + m_end_requester.Unlock(); - 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_requester = new SocketRequester(m_socket, this); + + err = m_thread_requester->Create(); + wxASSERT(err == wxTHREAD_NO_ERROR); + + err = m_thread_requester->Run(); + wxASSERT(err == wxTHREAD_NO_ERROR); + +#endif +} + +void wxSocketInternal::StopRequester() +{ +#if wxUSE_THREADS + m_end_requester.Lock(); + if (m_invalid_requester) { + m_end_requester.Unlock(); + if (m_thread_requester) { + delete m_thread_requester; + m_thread_requester = NULL; } - - m_thread_waiter->Run(); - m_thread_requester->Run(); + m_invalid_requester = TRUE; + return; } -} + m_end_requester.Unlock(); + wxASSERT(m_thread_requester != NULL); -// ---------------------------------------------------------------------- -// InitializeSocket: called by wxSocketBase to destroy daemons -// ---------------------------------------------------------------------- -void wxSocketInternal::FinalizeSocket() -{ - wxASSERT( (!m_thread_waiter->IsAlive() && !m_thread_requester->IsAlive()) ); + m_request_locker.Lock(); - ResumeSocket(); + // Send a signal to the requester. + m_socket_cond.Signal(); - m_thread_waiter->Delete(); - m_socket_locker.Lock(); - if (m_requests.Number() == 0) - m_socket_cond.Signal(); - m_socket_locker.Unlock(); + m_request_locker.Unlock(); + // Finish the destruction of the requester. m_thread_requester->Delete(); -} -void wxSocketInternal::PauseSocket() -{ - if (m_thread_waiter != NULL && !m_thread_waiter->IsPaused()) - m_thread_waiter->Pause(); + delete m_thread_requester; + m_thread_requester = NULL; +#endif } -void wxSocketInternal::ResumeSocket() +void wxSocketInternal::ResumeWaiter() { - if (m_thread_waiter != NULL && m_thread_waiter->IsPaused()) - m_thread_waiter->Resume(); -} +#if wxUSE_THREADS + wxThreadError err; -void wxSocketInternal::EnableWaiter() -{ - if (m_thread_waiter != NULL && m_thread_waiter->IsPaused()) - m_thread_waiter->Resume(); + if (m_thread_waiter != NULL) + return; + + m_thread_waiter = new SocketWaiter(m_socket, this); + + err = m_thread_waiter->Create(); + wxASSERT(err == wxTHREAD_NO_ERROR); + + err = m_thread_waiter->Run(); + wxASSERT(err == wxTHREAD_NO_ERROR); +#endif } -void wxSocketInternal::DisableWaiter() +void wxSocketInternal::StopWaiter() { - if (m_thread_waiter != NULL && !m_thread_waiter->IsPaused()) - m_thread_waiter->Pause(); +#if wxUSE_THREADS + if (m_thread_waiter == NULL) + return; + + m_thread_waiter->Delete(); + + delete m_thread_waiter; + m_thread_waiter = NULL; +#endif } // ---------------------------------------------------------------------- @@ -460,14 +514,20 @@ void wxSocketInternal::DisableWaiter() // ---------------------------------------------------------------------- void wxSocketInternal::QueueRequest(SockRequest *request, bool async) { +#if wxUSE_THREADS + if (m_invalid_requester) + ResumeRequester(); + + async = FALSE; if (async) { + m_request_locker.Lock(); request->done = FALSE; m_requests.Append((wxObject *)request); + m_socket_cond.Signal(); m_request_locker.Unlock(); // Wake up - m_socket_cond.Signal(); if (request->wait) { if (wxThread::IsMain()) @@ -479,7 +539,6 @@ void wxSocketInternal::QueueRequest(SockRequest *request, bool async) wxThread::Yield(); } } - } else { m_request_locker.Lock(); @@ -502,11 +561,14 @@ void wxSocketInternal::QueueRequest(SockRequest *request, bool async) request->done = TRUE; m_request_locker.Unlock(); } +#endif } void wxSocketInternal::WaitForEnd(SockRequest *request) { +#if wxUSE_THREADS // TODOTODO +#endif } #endif