]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/sckint.cpp
Compile fix for GTK 1.0
[wxWidgets.git] / src / common / sckint.cpp
index a8699b5859995f1a99b29a99b5181e0ec6c487d0..dd17b9bdf6d55cd239b424236c84cdf5c34a39fd 100644 (file)
@@ -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
 // --------- 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