* 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:
parent
0304608682
commit
2a4f27f209
@ -115,12 +115,10 @@ class wxSocketInternal {
|
||||
|
||||
int GetFD() { return m_fd; }
|
||||
|
||||
void InitializeSocket();
|
||||
void FinalizeSocket();
|
||||
void PauseSocket();
|
||||
void ResumeSocket();
|
||||
void EnableWaiter();
|
||||
void DisableWaiter();
|
||||
void ResumeWaiter();
|
||||
void StopWaiter();
|
||||
void ResumeRequester();
|
||||
void StopRequester();
|
||||
|
||||
void QueueRequest(SockRequest *request, bool async);
|
||||
void WaitForEnd(SockRequest *request);
|
||||
|
@ -165,14 +165,13 @@ void *SocketWaiter::Entry()
|
||||
if (ret == 0)
|
||||
// If nothing happened, we wait for 100 ms.
|
||||
wxUsleep(10);
|
||||
else
|
||||
wxYield();
|
||||
*/
|
||||
|
||||
// Check whether we should exit.
|
||||
if (TestDestroy())
|
||||
if (TestDestroy()) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -320,16 +319,16 @@ 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_thread_requester = NULL;
|
||||
m_thread_waiter = NULL;
|
||||
m_request_locker.Lock();
|
||||
}
|
||||
|
||||
wxSocketInternal::~wxSocketInternal()
|
||||
{
|
||||
wxASSERT(m_thread_requester == NULL);
|
||||
wxASSERT(m_thread_waiter == NULL);
|
||||
m_request_locker.Unlock();
|
||||
delete m_thread_waiter;
|
||||
delete m_thread_requester;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@ -376,82 +375,69 @@ void wxSocketInternal::ReleaseFD()
|
||||
m_fd_locker.Unlock();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// 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())));
|
||||
wxThreadError err;
|
||||
|
||||
m_thread_waiter->m_fd = m_socket->m_fd;
|
||||
wxASSERT(m_thread_requester == NULL);
|
||||
|
||||
m_thread_requester = new SocketRequester(m_socket, this);
|
||||
m_thread_requester->m_fd = m_socket->m_fd;
|
||||
|
||||
if (m_thread_waiter->IsPaused())
|
||||
ResumeSocket();
|
||||
else {
|
||||
wxThreadError err;
|
||||
err = m_thread_requester->Create();
|
||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||
|
||||
err = m_thread_waiter->Create();
|
||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||
err = m_thread_requester->Create();
|
||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||
|
||||
err = m_thread_waiter->Run();
|
||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||
err = m_thread_requester->Run();
|
||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||
}
|
||||
err = m_thread_requester->Run();
|
||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// InitializeSocket: called by wxSocketBase to destroy daemons
|
||||
// ----------------------------------------------------------------------
|
||||
void wxSocketInternal::FinalizeSocket()
|
||||
void wxSocketInternal::StopRequester()
|
||||
{
|
||||
ResumeSocket();
|
||||
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();
|
||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||
}
|
||||
|
||||
void wxSocketInternal::StopWaiter()
|
||||
{
|
||||
/*
|
||||
if (m_thread_waiter == NULL)
|
||||
return;
|
||||
|
||||
m_thread_waiter->Delete();
|
||||
|
||||
// Send a signal to the thread "requester".
|
||||
|
||||
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();
|
||||
delete m_thread_waiter;
|
||||
m_thread_waiter = NULL;
|
||||
*/
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@ -460,6 +446,9 @@ void wxSocketInternal::DisableWaiter()
|
||||
void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
|
||||
{
|
||||
if (async) {
|
||||
if (m_thread_requester == NULL)
|
||||
ResumeRequester();
|
||||
|
||||
m_request_locker.Lock();
|
||||
request->done = FALSE;
|
||||
m_requests.Append((wxObject *)request);
|
||||
@ -478,7 +467,6 @@ void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
|
||||
wxThread::Yield();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
m_request_locker.Lock();
|
||||
|
||||
|
@ -209,8 +209,6 @@ wxSocketBase::~wxSocketBase()
|
||||
// First, close the file descriptor.
|
||||
Close();
|
||||
|
||||
m_internal->FinalizeSocket();
|
||||
|
||||
if (m_unread)
|
||||
free(m_unread);
|
||||
// Unregister from the handler database.
|
||||
@ -228,8 +226,8 @@ bool wxSocketBase::Close()
|
||||
{
|
||||
if (m_fd != INVALID_SOCKET)
|
||||
{
|
||||
// Pause all running socket thread.
|
||||
m_internal->PauseSocket();
|
||||
if (m_notify_state == TRUE)
|
||||
Notify(FALSE);
|
||||
|
||||
// Shutdown the connection.
|
||||
shutdown(m_fd, 2);
|
||||
@ -547,7 +545,7 @@ void wxSocketBase::SetNotify(wxRequestNotify flags)
|
||||
|
||||
m_neededreq = flags;
|
||||
if (m_neededreq == 0)
|
||||
m_internal->DisableWaiter();
|
||||
m_internal->StopWaiter();
|
||||
else
|
||||
Notify(m_notify_state);
|
||||
}
|
||||
@ -559,9 +557,9 @@ void wxSocketBase::Notify(bool notify)
|
||||
return;
|
||||
|
||||
if (notify)
|
||||
m_internal->EnableWaiter();
|
||||
m_internal->ResumeWaiter();
|
||||
else
|
||||
m_internal->DisableWaiter();
|
||||
m_internal->StopWaiter();
|
||||
}
|
||||
|
||||
void wxSocketBase::OnRequest(wxRequestEvent req_evt)
|
||||
@ -577,7 +575,7 @@ void wxSocketBase::OnRequest(wxRequestEvent req_evt)
|
||||
// OldOnNotify(req_evt);
|
||||
|
||||
// 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;
|
||||
|
||||
SaveState();
|
||||
m_internal->DisableWaiter();
|
||||
m_internal->StopWaiter();
|
||||
buf->buffer = buffer;
|
||||
buf->size = nbytes;
|
||||
buf->done = FALSE;
|
||||
@ -738,7 +736,7 @@ wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
|
||||
return;
|
||||
}
|
||||
|
||||
m_internal->InitializeSocket();
|
||||
Notify(TRUE);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
@ -769,7 +767,7 @@ bool wxSocketServer::AcceptWith(wxSocketBase& sock)
|
||||
sock.m_fd = fd2;
|
||||
sock.m_connected = TRUE;
|
||||
|
||||
sock.m_internal->InitializeSocket();
|
||||
sock.m_internal->ResumeWaiter();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -851,10 +849,6 @@ bool wxSocketClient::Connect(wxSockAddress& addr_man, bool WXUNUSED(wait) )
|
||||
if (connect(m_fd, remote, len) != 0)
|
||||
return FALSE;
|
||||
|
||||
// Initializes the background threads ...
|
||||
// --------------------------------------
|
||||
m_internal->InitializeSocket();
|
||||
|
||||
// Enables bg events.
|
||||
// ------------------
|
||||
Notify(TRUE);
|
||||
@ -879,11 +873,10 @@ void wxSocketClient::OnRequest(wxRequestEvent evt)
|
||||
{
|
||||
if (m_connected)
|
||||
{
|
||||
SetNotify(m_neededreq & ~REQ_CONNECT);
|
||||
m_neededreq &= ~REQ_CONNECT;
|
||||
return;
|
||||
}
|
||||
m_connected = TRUE;
|
||||
OldOnNotify(EVT_CONNECT);
|
||||
return;
|
||||
}
|
||||
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
|
||||
// until someone waited for us!)
|
||||
p_internal->SignalExit();
|
||||
|
||||
p_internal->SetState(STATE_EXITED);
|
||||
|
||||
p_internal->SignalExit();
|
||||
|
||||
// delete both C++ thread object and terminate the OS thread object
|
||||
// GL: This is very ugly and buggy ...
|
||||
// delete this;
|
||||
|
Loading…
Reference in New Issue
Block a user