#include <wx/thread.h>
#include <wx/sckint.h>
+// IRIX requires bstring.h be included to use select()
+#ifdef sgi
+ #include <bstring.h>
+#endif // IRIX
+
#ifndef __WXSTUBS__
#include <stdlib.h>
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) {
m_socket->OnRequest(wxSocketBase::EVT_READ);
} else {
m_socket->OnRequest(wxSocketBase::EVT_LOST);
+ m_internal->ReleaseData(); // In that case, we mustn't forget to unlock the mutex.
Exit(NULL);
}
}
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)
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;
}
SocketRequester::SocketRequester(wxSocketBase *socket,
wxSocketInternal *internal)
- : wxThread(),
+ :
+#if wxUSE_THREADS
+ wxThread(),
+#endif
m_socket(socket), m_internal(internal), m_fd(internal->GetFD())
{
}
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(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv);
req->size -= len;
req->io_nbytes += len;
req->buffer += len;
+
+ if (len == 0)
+ m_internal->EndRequest(req);
return;
}
// The End.
wxSocketInternal::wxSocketInternal(wxSocketBase *socket)
{
m_socket = socket;
-#if wxUSE_THREADS
m_thread_requester = NULL;
m_thread_waiter = NULL;
m_invalid_requester = TRUE;
-#endif
}
wxSocketInternal::~wxSocketInternal()
{
-#if wxUSE_THREADS
StopRequester();
wxASSERT(m_thread_requester == NULL);
StopWaiter();
wxASSERT(m_thread_waiter == NULL);
-#endif
}
// ----------------------------------------------------------------------
#if wxUSE_THREADS
wxNode *node;
+ // First try.
node = m_requests.First();
if (node == NULL) {
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;
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
#if wxUSE_THREADS
wxThreadError err;
- wxASSERT(m_thread_requester == NULL || m_invalid_requester);
+ wxASSERT(m_invalid_requester);
m_end_requester.Lock();
- if (m_invalid_requester) {
- if (m_thread_requester != NULL)
- delete m_thread_requester;
- m_invalid_requester = FALSE;
+
+ if (m_thread_requester != NULL) {
+ m_thread_requester->Delete(); // We must join it.
+ delete m_thread_requester;
}
+
+ m_invalid_requester = FALSE;
+
m_end_requester.Unlock();
m_thread_requester = new SocketRequester(m_socket, this);
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
}
m_end_requester.Lock();
if (m_invalid_requester) {
m_end_requester.Unlock();
- delete m_thread_requester;
- m_thread_requester = NULL;
- m_invalid_requester = FALSE;
+ 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.
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
}
m_thread_waiter = new SocketWaiter(m_socket, this);
+ m_thread_waiter->SetPriority(WXTHREAD_MIN_PRIORITY);
+
err = m_thread_waiter->Create();
wxASSERT(err == wxTHREAD_NO_ERROR);
// ----------------------------------------------------------------------
void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
{
-#if wxUSE_THREADS
-/*
if (m_invalid_requester)
ResumeRequester();
-*/
- m_thread_requester = new SocketRequester(m_socket, this);
-/*
+#if wxUSE_THREADS
if (async) {
m_request_locker.Lock();
}
}
} else {
-*/
m_request_locker.Lock();
+#endif
if ((request->type & wxSocketBase::REQ_WAIT) != 0) {
m_thread_requester->ProcessWaitEvent(request);
}
}
request->done = TRUE;
+#if wxUSE_THREADS
m_request_locker.Unlock();
-// }
- delete m_thread_requester;
- m_thread_requester = NULL;
+ }
#endif
}