* implemented VZ's idea about creating and destroying bg threads.
(PB with the destruction of waiter: I think it's a race problem but I can't localize it if someone finds it please mail it to me) * Fixed race condition in threadpsx.cpp. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2364 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -115,12 +115,10 @@ class wxSocketInternal {
|
|||||||
|
|
||||||
int GetFD() { return m_fd; }
|
int GetFD() { return m_fd; }
|
||||||
|
|
||||||
void InitializeSocket();
|
void ResumeWaiter();
|
||||||
void FinalizeSocket();
|
void StopWaiter();
|
||||||
void PauseSocket();
|
void ResumeRequester();
|
||||||
void ResumeSocket();
|
void StopRequester();
|
||||||
void EnableWaiter();
|
|
||||||
void DisableWaiter();
|
|
||||||
|
|
||||||
void QueueRequest(SockRequest *request, bool async);
|
void QueueRequest(SockRequest *request, bool async);
|
||||||
void WaitForEnd(SockRequest *request);
|
void WaitForEnd(SockRequest *request);
|
||||||
|
@@ -165,14 +165,13 @@ void *SocketWaiter::Entry()
|
|||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
// If nothing happened, we wait for 100 ms.
|
// If nothing happened, we wait for 100 ms.
|
||||||
wxUsleep(10);
|
wxUsleep(10);
|
||||||
else
|
|
||||||
wxYield();
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Check whether we should exit.
|
// Check whether we should exit.
|
||||||
if (TestDestroy())
|
if (TestDestroy()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,16 +319,16 @@ void *SocketRequester::Entry()
|
|||||||
wxSocketInternal::wxSocketInternal(wxSocketBase *socket)
|
wxSocketInternal::wxSocketInternal(wxSocketBase *socket)
|
||||||
{
|
{
|
||||||
m_socket = socket;
|
m_socket = socket;
|
||||||
m_thread_waiter = new SocketWaiter(socket, this);
|
m_thread_requester = NULL;
|
||||||
m_thread_requester = new SocketRequester(socket, this);
|
m_thread_waiter = NULL;
|
||||||
m_request_locker.Lock();
|
m_request_locker.Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSocketInternal::~wxSocketInternal()
|
wxSocketInternal::~wxSocketInternal()
|
||||||
{
|
{
|
||||||
|
wxASSERT(m_thread_requester == NULL);
|
||||||
|
wxASSERT(m_thread_waiter == NULL);
|
||||||
m_request_locker.Unlock();
|
m_request_locker.Unlock();
|
||||||
delete m_thread_waiter;
|
|
||||||
delete m_thread_requester;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
@@ -376,82 +375,69 @@ void wxSocketInternal::ReleaseFD()
|
|||||||
m_fd_locker.Unlock();
|
m_fd_locker.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
void wxSocketInternal::ResumeRequester()
|
||||||
// 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 {
|
|
||||||
wxThreadError err;
|
wxThreadError err;
|
||||||
|
|
||||||
err = m_thread_waiter->Create();
|
wxASSERT(m_thread_requester == NULL);
|
||||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
|
||||||
|
m_thread_requester = new SocketRequester(m_socket, this);
|
||||||
|
m_thread_requester->m_fd = m_socket->m_fd;
|
||||||
|
|
||||||
err = m_thread_requester->Create();
|
err = m_thread_requester->Create();
|
||||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||||
|
|
||||||
|
err = m_thread_requester->Run();
|
||||||
|
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxSocketInternal::StopRequester()
|
||||||
|
{
|
||||||
|
wxASSERT(m_thread_requester != NULL);
|
||||||
|
|
||||||
|
m_socket_locker.Lock();
|
||||||
|
|
||||||
|
// Send a signal to the requester.
|
||||||
|
if (m_requests.Number() == 0)
|
||||||
|
m_socket_cond.Signal();
|
||||||
|
|
||||||
|
m_socket_locker.Unlock();
|
||||||
|
|
||||||
|
// Finish the destruction of the requester.
|
||||||
|
m_thread_requester->Delete();
|
||||||
|
|
||||||
|
delete m_thread_requester;
|
||||||
|
m_thread_requester = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxSocketInternal::ResumeWaiter()
|
||||||
|
{
|
||||||
|
wxThreadError err;
|
||||||
|
|
||||||
|
if (m_thread_waiter != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_thread_waiter = new SocketWaiter(m_socket, this);
|
||||||
|
m_thread_waiter->m_fd = m_socket->m_fd;
|
||||||
|
|
||||||
|
err = m_thread_waiter->Create();
|
||||||
|
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||||
|
|
||||||
err = m_thread_waiter->Run();
|
err = m_thread_waiter->Run();
|
||||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||||
err = m_thread_requester->Run();
|
|
||||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxSocketInternal::StopWaiter()
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
// InitializeSocket: called by wxSocketBase to destroy daemons
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
void wxSocketInternal::FinalizeSocket()
|
|
||||||
{
|
{
|
||||||
ResumeSocket();
|
/*
|
||||||
|
if (m_thread_waiter == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
m_thread_waiter->Delete();
|
m_thread_waiter->Delete();
|
||||||
|
|
||||||
// Send a signal to the thread "requester".
|
delete m_thread_waiter;
|
||||||
|
m_thread_waiter = NULL;
|
||||||
m_socket_locker.Lock();
|
*/
|
||||||
if (m_requests.Number() == 0)
|
|
||||||
m_socket_cond.Signal();
|
|
||||||
m_socket_locker.Unlock();
|
|
||||||
|
|
||||||
// Finish the destruction of the thread "requester".
|
|
||||||
m_thread_requester->Delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxSocketInternal::PauseSocket()
|
|
||||||
{
|
|
||||||
DisableWaiter();
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxSocketInternal::ResumeSocket()
|
|
||||||
{
|
|
||||||
EnableWaiter();
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxSocketInternal::EnableWaiter()
|
|
||||||
{
|
|
||||||
wxASSERT(m_thread_waiter != NULL);
|
|
||||||
if (!m_thread_waiter->IsAlive() || !m_thread_waiter->IsPaused())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_thread_waiter->Resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxSocketInternal::DisableWaiter()
|
|
||||||
{
|
|
||||||
wxASSERT(m_thread_waiter != NULL);
|
|
||||||
if (!m_thread_waiter->IsAlive() || m_thread_waiter->IsPaused())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_thread_waiter->Pause();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
@@ -460,6 +446,9 @@ void wxSocketInternal::DisableWaiter()
|
|||||||
void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
|
void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
|
||||||
{
|
{
|
||||||
if (async) {
|
if (async) {
|
||||||
|
if (m_thread_requester == NULL)
|
||||||
|
ResumeRequester();
|
||||||
|
|
||||||
m_request_locker.Lock();
|
m_request_locker.Lock();
|
||||||
request->done = FALSE;
|
request->done = FALSE;
|
||||||
m_requests.Append((wxObject *)request);
|
m_requests.Append((wxObject *)request);
|
||||||
@@ -478,7 +467,6 @@ void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
|
|||||||
wxThread::Yield();
|
wxThread::Yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
m_request_locker.Lock();
|
m_request_locker.Lock();
|
||||||
|
|
||||||
|
@@ -209,8 +209,6 @@ wxSocketBase::~wxSocketBase()
|
|||||||
// First, close the file descriptor.
|
// First, close the file descriptor.
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
m_internal->FinalizeSocket();
|
|
||||||
|
|
||||||
if (m_unread)
|
if (m_unread)
|
||||||
free(m_unread);
|
free(m_unread);
|
||||||
// Unregister from the handler database.
|
// Unregister from the handler database.
|
||||||
@@ -228,8 +226,8 @@ bool wxSocketBase::Close()
|
|||||||
{
|
{
|
||||||
if (m_fd != INVALID_SOCKET)
|
if (m_fd != INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
// Pause all running socket thread.
|
if (m_notify_state == TRUE)
|
||||||
m_internal->PauseSocket();
|
Notify(FALSE);
|
||||||
|
|
||||||
// Shutdown the connection.
|
// Shutdown the connection.
|
||||||
shutdown(m_fd, 2);
|
shutdown(m_fd, 2);
|
||||||
@@ -547,7 +545,7 @@ void wxSocketBase::SetNotify(wxRequestNotify flags)
|
|||||||
|
|
||||||
m_neededreq = flags;
|
m_neededreq = flags;
|
||||||
if (m_neededreq == 0)
|
if (m_neededreq == 0)
|
||||||
m_internal->DisableWaiter();
|
m_internal->StopWaiter();
|
||||||
else
|
else
|
||||||
Notify(m_notify_state);
|
Notify(m_notify_state);
|
||||||
}
|
}
|
||||||
@@ -559,9 +557,9 @@ void wxSocketBase::Notify(bool notify)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (notify)
|
if (notify)
|
||||||
m_internal->EnableWaiter();
|
m_internal->ResumeWaiter();
|
||||||
else
|
else
|
||||||
m_internal->DisableWaiter();
|
m_internal->StopWaiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxSocketBase::OnRequest(wxRequestEvent req_evt)
|
void wxSocketBase::OnRequest(wxRequestEvent req_evt)
|
||||||
@@ -577,7 +575,7 @@ void wxSocketBase::OnRequest(wxRequestEvent req_evt)
|
|||||||
// OldOnNotify(req_evt);
|
// OldOnNotify(req_evt);
|
||||||
|
|
||||||
// We disable the event reporting.
|
// We disable the event reporting.
|
||||||
SetNotify(m_neededreq & ~notify);
|
m_neededreq &= ~notify;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,7 +680,7 @@ void wxSocketBase::WantBuffer(char *buffer, size_t nbytes,
|
|||||||
SockRequest *buf = new SockRequest;
|
SockRequest *buf = new SockRequest;
|
||||||
|
|
||||||
SaveState();
|
SaveState();
|
||||||
m_internal->DisableWaiter();
|
m_internal->StopWaiter();
|
||||||
buf->buffer = buffer;
|
buf->buffer = buffer;
|
||||||
buf->size = nbytes;
|
buf->size = nbytes;
|
||||||
buf->done = FALSE;
|
buf->done = FALSE;
|
||||||
@@ -738,7 +736,7 @@ wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_internal->InitializeSocket();
|
Notify(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
@@ -769,7 +767,7 @@ bool wxSocketServer::AcceptWith(wxSocketBase& sock)
|
|||||||
sock.m_fd = fd2;
|
sock.m_fd = fd2;
|
||||||
sock.m_connected = TRUE;
|
sock.m_connected = TRUE;
|
||||||
|
|
||||||
sock.m_internal->InitializeSocket();
|
sock.m_internal->ResumeWaiter();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -851,10 +849,6 @@ bool wxSocketClient::Connect(wxSockAddress& addr_man, bool WXUNUSED(wait) )
|
|||||||
if (connect(m_fd, remote, len) != 0)
|
if (connect(m_fd, remote, len) != 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
// Initializes the background threads ...
|
|
||||||
// --------------------------------------
|
|
||||||
m_internal->InitializeSocket();
|
|
||||||
|
|
||||||
// Enables bg events.
|
// Enables bg events.
|
||||||
// ------------------
|
// ------------------
|
||||||
Notify(TRUE);
|
Notify(TRUE);
|
||||||
@@ -879,11 +873,10 @@ void wxSocketClient::OnRequest(wxRequestEvent evt)
|
|||||||
{
|
{
|
||||||
if (m_connected)
|
if (m_connected)
|
||||||
{
|
{
|
||||||
SetNotify(m_neededreq & ~REQ_CONNECT);
|
m_neededreq &= ~REQ_CONNECT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_connected = TRUE;
|
m_connected = TRUE;
|
||||||
OldOnNotify(EVT_CONNECT);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wxSocketBase::OnRequest(evt);
|
wxSocketBase::OnRequest(evt);
|
||||||
|
@@ -675,10 +675,10 @@ void wxThread::Exit(void *status)
|
|||||||
|
|
||||||
// next wake up the threads waiting for us (OTOH, this function won't return
|
// next wake up the threads waiting for us (OTOH, this function won't return
|
||||||
// until someone waited for us!)
|
// until someone waited for us!)
|
||||||
p_internal->SignalExit();
|
|
||||||
|
|
||||||
p_internal->SetState(STATE_EXITED);
|
p_internal->SetState(STATE_EXITED);
|
||||||
|
|
||||||
|
p_internal->SignalExit();
|
||||||
|
|
||||||
// delete both C++ thread object and terminate the OS thread object
|
// delete both C++ thread object and terminate the OS thread object
|
||||||
// GL: This is very ugly and buggy ...
|
// GL: This is very ugly and buggy ...
|
||||||
// delete this;
|
// delete this;
|
||||||
|
Reference in New Issue
Block a user