* 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:
Guilhem Lavaux 1999-05-08 12:18:53 +00:00
parent 0304608682
commit 2a4f27f209
4 changed files with 78 additions and 99 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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;