* wxThread fixes
* wxStream fix (Read(wxStreamBase)) * wxEvent: GTK idle loop waking up was actually good, reenabled. * wxSocket: all features working on Linux/RH6 (including high-level protocols) Needs testing on other platforms now. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2563 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -82,7 +82,11 @@ class SocketWaiter: public wxThread {
|
|||||||
int m_fd;
|
int m_fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SocketRequester: public wxThread {
|
class SocketRequester
|
||||||
|
#if wxUSE_THREADS
|
||||||
|
: public wxThread
|
||||||
|
#endif
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
SocketRequester(wxSocketBase *socket, wxSocketInternal *internal);
|
SocketRequester(wxSocketBase *socket, wxSocketInternal *internal);
|
||||||
~SocketRequester();
|
~SocketRequester();
|
||||||
@@ -136,8 +140,8 @@ class wxSocketInternal {
|
|||||||
wxMutex m_socket_locker, m_fd_locker, m_request_locker, m_end_requester;
|
wxMutex m_socket_locker, m_fd_locker, m_request_locker, m_end_requester;
|
||||||
wxCondition m_socket_cond;
|
wxCondition m_socket_cond;
|
||||||
SocketWaiter *m_thread_waiter;
|
SocketWaiter *m_thread_waiter;
|
||||||
SocketRequester *m_thread_requester;
|
|
||||||
#endif
|
#endif
|
||||||
|
SocketRequester *m_thread_requester;
|
||||||
wxList m_requests;
|
wxList m_requests;
|
||||||
int m_fd;
|
int m_fd;
|
||||||
bool m_invalid_requester;
|
bool m_invalid_requester;
|
||||||
|
@@ -95,6 +95,8 @@ public:
|
|||||||
wxSocketBase& Read(char* buffer, size_t nbytes);
|
wxSocketBase& Read(char* buffer, size_t nbytes);
|
||||||
wxSocketBase& Write(const char *buffer, size_t nbytes);
|
wxSocketBase& Write(const char *buffer, size_t nbytes);
|
||||||
wxSocketBase& Unread(const char *buffer, size_t nbytes);
|
wxSocketBase& Unread(const char *buffer, size_t nbytes);
|
||||||
|
wxSocketBase& ReadMsg(char *buffer, size_t nbytes);
|
||||||
|
wxSocketBase& WriteMsg(const char *buffer, size_t nbytes);
|
||||||
void Discard();
|
void Discard();
|
||||||
|
|
||||||
// Try not to use this two methods (they sould be protected)
|
// Try not to use this two methods (they sould be protected)
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
* Purpose: wxSocket: client demo
|
* Purpose: wxSocket: client demo
|
||||||
* Author: LAVAUX Guilhem
|
* Author: LAVAUX Guilhem
|
||||||
* Created: June 1997
|
* Created: June 1997
|
||||||
* Updated:
|
* CVS ID: $Id$
|
||||||
* Copyright: (c) 1997, LAVAUX Guilhem
|
* Copyright: (c) 1997, LAVAUX Guilhem
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -163,11 +163,8 @@ void MyFrame::OnExecOpenConnection(wxCommandEvent& WXUNUSED(evt))
|
|||||||
if (sock->IsConnected())
|
if (sock->IsConnected())
|
||||||
sock->Close();
|
sock->Close();
|
||||||
|
|
||||||
/*
|
|
||||||
wxString hname = wxGetTextFromUser("Enter the address of the wxSocket Sample Server",
|
wxString hname = wxGetTextFromUser("Enter the address of the wxSocket Sample Server",
|
||||||
"Connect ...", "localhost");
|
"Connect ...", "localhost");
|
||||||
*/
|
|
||||||
wxString hname = "localhost";
|
|
||||||
addr.Hostname(hname);
|
addr.Hostname(hname);
|
||||||
addr.Service(3000);
|
addr.Service(3000);
|
||||||
sock->SetNotify(0);
|
sock->SetNotify(0);
|
||||||
@@ -282,13 +279,15 @@ void MyFrame::OnExecUrlTest(wxCommandEvent& WXUNUSED(evt))
|
|||||||
wxURL url(urlname);
|
wxURL url(urlname);
|
||||||
wxInputStream *datas = url.GetInputStream();
|
wxInputStream *datas = url.GetInputStream();
|
||||||
|
|
||||||
if (!datas)
|
if (!datas) {
|
||||||
wxMessageBox("Error in getting data from the URL.", "Alert !");
|
wxString error;
|
||||||
else {
|
error.Printf(_T("Error in getting data from the URL. (error = %d)"), url.GetError());
|
||||||
|
wxMessageBox(error, "Alert !");
|
||||||
|
} else {
|
||||||
wxFileOutputStream *str_out = new wxFileOutputStream("test.url");
|
wxFileOutputStream *str_out = new wxFileOutputStream("test.url");
|
||||||
str_out->Write(*datas);
|
str_out->Write(*datas);
|
||||||
|
|
||||||
wxMessageBox("Success !! Click on OK to see the text.", "OK");
|
wxMessageBox(_T("Success !! Click on OK to see the text."), "OK");
|
||||||
delete datas;
|
delete datas;
|
||||||
delete str_out;
|
delete str_out;
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
* Purpose: wxSocket: server demo
|
* Purpose: wxSocket: server demo
|
||||||
* Author: LAVAUX Guilhem
|
* Author: LAVAUX Guilhem
|
||||||
* Created: June 1997
|
* Created: June 1997
|
||||||
* Updated:
|
* CVS Id: $Id$
|
||||||
* Copyright: (C) 1997, LAVAUX Guilhem
|
* Copyright: (C) 1997, LAVAUX Guilhem
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -102,6 +102,9 @@ void MyFrame::OnSockRequest(wxSocketEvent& evt)
|
|||||||
waiting socket thread, i.e. here we are
|
waiting socket thread, i.e. here we are
|
||||||
not in the main GUI thread and thus we
|
not in the main GUI thread and thus we
|
||||||
must not call any GUI function here. */
|
must not call any GUI function here. */
|
||||||
|
/* Wrong ! This routine is called by the main GUI thread
|
||||||
|
because the main GUI thread received a signal from the other
|
||||||
|
thread using wxEvent::ProcessThreadEvent */
|
||||||
|
|
||||||
wxSocketBase *sock = evt.Socket();
|
wxSocketBase *sock = evt.Socket();
|
||||||
|
|
||||||
@@ -119,6 +122,7 @@ void MyFrame::OnSockRequest(wxSocketEvent& evt)
|
|||||||
case wxSocketBase::EVT_LOST:
|
case wxSocketBase::EVT_LOST:
|
||||||
printf("Destroying socket\n");
|
printf("Destroying socket\n");
|
||||||
wxPendingDelete.Append(sock);
|
wxPendingDelete.Append(sock);
|
||||||
|
UpdateStatus(-1);
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -132,17 +136,21 @@ void MyFrame::OnSockRequestServer(wxSocketEvent& evt)
|
|||||||
waiting socket thread, i.e. here we are
|
waiting socket thread, i.e. here we are
|
||||||
not in the main GUI thread and thus we
|
not in the main GUI thread and thus we
|
||||||
must not call any GUI function here. */
|
must not call any GUI function here. */
|
||||||
|
/* Wrong ! This routine is called by the main GUI thread
|
||||||
|
because the main GUI thread received a signal from the other
|
||||||
|
thread using wxEvent::ProcessThreadEvent */
|
||||||
|
|
||||||
wxSocketBase *sock2;
|
wxSocketBase *sock2;
|
||||||
wxSocketServer *server = (wxSocketServer *) evt.Socket();
|
wxSocketServer *server = (wxSocketServer *) evt.Socket();
|
||||||
|
|
||||||
printf("OnSockRequestServer OK\n");
|
printf("OnSockRequestServer OK\n");
|
||||||
printf("OnSockRequest (event = %d)\n",evt.SocketEvent());
|
printf("OnSockRequest (Main = %d) (event = %d)\n",wxThread::IsMain(), evt.SocketEvent());
|
||||||
|
|
||||||
sock2 = server->Accept();
|
sock2 = server->Accept();
|
||||||
if (sock2 == NULL)
|
if (sock2 == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
UpdateStatus(1);
|
||||||
sock2->SetFlags(wxSocketBase::SPEED);
|
sock2->SetFlags(wxSocketBase::SPEED);
|
||||||
sock2->Notify(TRUE);
|
sock2->Notify(TRUE);
|
||||||
sock2->SetEventHandler(*this, SKDEMO_SOCKET);
|
sock2->SetEventHandler(*this, SKDEMO_SOCKET);
|
||||||
|
@@ -563,8 +563,8 @@ bool wxEvtHandler::ProcessThreadEvent(wxEvent& event)
|
|||||||
wxPendingEventsLocker->Leave();
|
wxPendingEventsLocker->Leave();
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
// if (g_isIdle)
|
if (g_isIdle)
|
||||||
// wxapp_install_idle_handler();
|
wxapp_install_idle_handler();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@@ -355,6 +355,7 @@ wxInputStream *wxFTP::GetInputStream(const wxString& path)
|
|||||||
|
|
||||||
in_stream->m_ftpsize = wxAtoi(WXSTRINGCAST str_size);
|
in_stream->m_ftpsize = wxAtoi(WXSTRINGCAST str_size);
|
||||||
}
|
}
|
||||||
|
sock->SetFlags(WAITALL);
|
||||||
|
|
||||||
return in_stream;
|
return in_stream;
|
||||||
}
|
}
|
||||||
@@ -401,13 +402,6 @@ wxList *wxFTP::GetList(const wxString& wildcard)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ininterresting ?!
|
|
||||||
/*
|
|
||||||
sock->SetEventHandler(*GetNextHandler(), m_id);
|
|
||||||
sock->Notify(m_notifyme);
|
|
||||||
sock->SetNotify(m_neededreq);
|
|
||||||
*/
|
|
||||||
|
|
||||||
return file_list;
|
return file_list;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -195,8 +195,8 @@ bool wxHTTP::BuildRequest(const wxString& path, wxHTTP_Req req)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SaveState();
|
SaveState();
|
||||||
|
SetFlags(NONE);
|
||||||
Notify(FALSE);
|
Notify(FALSE);
|
||||||
SetFlags(WAITALL);
|
|
||||||
|
|
||||||
sprintf(buf, "%s %s HTTP/1.0\n\r", tmp_buf, (const char*)pathbuf);
|
sprintf(buf, "%s %s HTTP/1.0\n\r", tmp_buf, (const char*)pathbuf);
|
||||||
Write(buf, strlen(buf));
|
Write(buf, strlen(buf));
|
||||||
@@ -275,6 +275,7 @@ wxInputStream *wxHTTP::GetInputStream(const wxString& path)
|
|||||||
if (!GetHeader(_T("Content-Length")).IsEmpty())
|
if (!GetHeader(_T("Content-Length")).IsEmpty())
|
||||||
inp_stream->m_httpsize = wxAtoi(WXSTRINGCAST GetHeader(_T("Content-Length")));
|
inp_stream->m_httpsize = wxAtoi(WXSTRINGCAST GetHeader(_T("Content-Length")));
|
||||||
|
|
||||||
|
SetFlags(WAITALL);
|
||||||
return inp_stream;
|
return inp_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -100,7 +100,9 @@ void SocketWaiter::ProcessReadEvent()
|
|||||||
int ret;
|
int ret;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
|
m_internal->AcquireFD();
|
||||||
ret = recv(m_fd, &c, 1, MSG_PEEK);
|
ret = recv(m_fd, &c, 1, MSG_PEEK);
|
||||||
|
m_internal->ReleaseFD();
|
||||||
|
|
||||||
// We are a server => emit a EVT_ACCEPT event.
|
// We are a server => emit a EVT_ACCEPT event.
|
||||||
if (ret == -1 && m_socket->GetType() == wxSocketBase::SOCK_SERVER) {
|
if (ret == -1 && m_socket->GetType() == wxSocketBase::SOCK_SERVER) {
|
||||||
@@ -167,14 +169,12 @@ void *SocketWaiter::Entry()
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ret == 0)
|
// We wait for 100 ms to prevent the CPU from burning.
|
||||||
// If nothing happened, we wait for 100 ms.
|
wxUsleep(100);
|
||||||
wxUsleep(10);
|
|
||||||
|
|
||||||
// Check whether we should exit.
|
// Check whether we should exit.
|
||||||
if (TestDestroy()) {
|
if (TestDestroy())
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -185,7 +185,10 @@ void *SocketWaiter::Entry()
|
|||||||
|
|
||||||
SocketRequester::SocketRequester(wxSocketBase *socket,
|
SocketRequester::SocketRequester(wxSocketBase *socket,
|
||||||
wxSocketInternal *internal)
|
wxSocketInternal *internal)
|
||||||
: wxThread(),
|
:
|
||||||
|
#if wxUSE_THREADS
|
||||||
|
wxThread(),
|
||||||
|
#endif
|
||||||
m_socket(socket), m_internal(internal), m_fd(internal->GetFD())
|
m_socket(socket), m_internal(internal), m_fd(internal->GetFD())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -204,12 +207,12 @@ bool SocketRequester::WaitFor(wxSocketBase::wxRequestNotify req, int millisec)
|
|||||||
tv.tv_sec = millisec / 1000;
|
tv.tv_sec = millisec / 1000;
|
||||||
tv.tv_usec = (millisec % 1000) * 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_ZERO(&sockwr_set);
|
||||||
|
if ((req & READ_MASK) != 0)
|
||||||
FD_SET(m_fd, &sockrd_set);
|
FD_SET(m_fd, &sockrd_set);
|
||||||
FD_SET(m_fd, &sockwr_set);
|
if ((req & WRITE_MASK) != 0)
|
||||||
|
FD_SET(m_fd, &sockwr_set);
|
||||||
|
|
||||||
m_internal->AcquireFD();
|
m_internal->AcquireFD();
|
||||||
ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv);
|
ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv);
|
||||||
@@ -247,6 +250,9 @@ void SocketRequester::ProcessReadEvent(SockRequest *req)
|
|||||||
req->size -= len;
|
req->size -= len;
|
||||||
req->io_nbytes += len;
|
req->io_nbytes += len;
|
||||||
req->buffer += len;
|
req->buffer += len;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
m_internal->EndRequest(req);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// The End.
|
// The End.
|
||||||
@@ -337,21 +343,17 @@ void *SocketRequester::Entry()
|
|||||||
wxSocketInternal::wxSocketInternal(wxSocketBase *socket)
|
wxSocketInternal::wxSocketInternal(wxSocketBase *socket)
|
||||||
{
|
{
|
||||||
m_socket = socket;
|
m_socket = socket;
|
||||||
#if wxUSE_THREADS
|
|
||||||
m_thread_requester = NULL;
|
m_thread_requester = NULL;
|
||||||
m_thread_waiter = NULL;
|
m_thread_waiter = NULL;
|
||||||
m_invalid_requester = TRUE;
|
m_invalid_requester = TRUE;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSocketInternal::~wxSocketInternal()
|
wxSocketInternal::~wxSocketInternal()
|
||||||
{
|
{
|
||||||
#if wxUSE_THREADS
|
|
||||||
StopRequester();
|
StopRequester();
|
||||||
wxASSERT(m_thread_requester == NULL);
|
wxASSERT(m_thread_requester == NULL);
|
||||||
StopWaiter();
|
StopWaiter();
|
||||||
wxASSERT(m_thread_waiter == NULL);
|
wxASSERT(m_thread_waiter == NULL);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
@@ -363,10 +365,12 @@ SockRequest *wxSocketInternal::WaitForReq()
|
|||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
wxNode *node;
|
wxNode *node;
|
||||||
|
|
||||||
|
// First try.
|
||||||
node = m_requests.First();
|
node = m_requests.First();
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
m_socket_cond.Wait(m_request_locker, 10, 0);
|
m_socket_cond.Wait(m_request_locker, 10, 0);
|
||||||
|
|
||||||
|
// Second try, if it is unsuccessul we give up.
|
||||||
node = m_requests.First();
|
node = m_requests.First();
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -425,14 +429,17 @@ void wxSocketInternal::ResumeRequester()
|
|||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
wxThreadError err;
|
wxThreadError err;
|
||||||
|
|
||||||
wxASSERT(m_thread_requester == NULL || m_invalid_requester);
|
wxASSERT(m_invalid_requester);
|
||||||
|
|
||||||
m_end_requester.Lock();
|
m_end_requester.Lock();
|
||||||
if (m_invalid_requester) {
|
|
||||||
if (m_thread_requester != NULL)
|
if (m_thread_requester != NULL) {
|
||||||
delete m_thread_requester;
|
m_thread_requester->Delete(); // We must join it.
|
||||||
m_invalid_requester = FALSE;
|
delete m_thread_requester;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_invalid_requester = FALSE;
|
||||||
|
|
||||||
m_end_requester.Unlock();
|
m_end_requester.Unlock();
|
||||||
|
|
||||||
m_thread_requester = new SocketRequester(m_socket, this);
|
m_thread_requester = new SocketRequester(m_socket, this);
|
||||||
@@ -442,7 +449,11 @@ void wxSocketInternal::ResumeRequester()
|
|||||||
|
|
||||||
err = m_thread_requester->Run();
|
err = m_thread_requester->Run();
|
||||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||||
|
#else
|
||||||
|
if (!m_invalid_requester)
|
||||||
|
return;
|
||||||
|
m_thread_requester = new SocketRequester(m_socket, this);
|
||||||
|
m_invalid_requester = FALSE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,6 +464,7 @@ void wxSocketInternal::StopRequester()
|
|||||||
if (m_invalid_requester) {
|
if (m_invalid_requester) {
|
||||||
m_end_requester.Unlock();
|
m_end_requester.Unlock();
|
||||||
if (m_thread_requester) {
|
if (m_thread_requester) {
|
||||||
|
m_thread_requester->Delete();
|
||||||
delete m_thread_requester;
|
delete m_thread_requester;
|
||||||
m_thread_requester = NULL;
|
m_thread_requester = NULL;
|
||||||
}
|
}
|
||||||
@@ -475,6 +487,11 @@ void wxSocketInternal::StopRequester()
|
|||||||
|
|
||||||
delete m_thread_requester;
|
delete m_thread_requester;
|
||||||
m_thread_requester = NULL;
|
m_thread_requester = NULL;
|
||||||
|
m_invalid_requester = TRUE;
|
||||||
|
#else
|
||||||
|
delete m_thread_requester;
|
||||||
|
m_thread_requester = NULL;
|
||||||
|
m_invalid_requester = TRUE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,6 +505,8 @@ void wxSocketInternal::ResumeWaiter()
|
|||||||
|
|
||||||
m_thread_waiter = new SocketWaiter(m_socket, this);
|
m_thread_waiter = new SocketWaiter(m_socket, this);
|
||||||
|
|
||||||
|
m_thread_waiter->SetPriority(WXTHREAD_MIN_PRIORITY);
|
||||||
|
|
||||||
err = m_thread_waiter->Create();
|
err = m_thread_waiter->Create();
|
||||||
wxASSERT(err == wxTHREAD_NO_ERROR);
|
wxASSERT(err == wxTHREAD_NO_ERROR);
|
||||||
|
|
||||||
@@ -514,11 +533,10 @@ void wxSocketInternal::StopWaiter()
|
|||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
|
void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
|
||||||
{
|
{
|
||||||
#if wxUSE_THREADS
|
|
||||||
if (m_invalid_requester)
|
if (m_invalid_requester)
|
||||||
ResumeRequester();
|
ResumeRequester();
|
||||||
|
|
||||||
async = FALSE;
|
#if wxUSE_THREADS
|
||||||
if (async) {
|
if (async) {
|
||||||
|
|
||||||
m_request_locker.Lock();
|
m_request_locker.Lock();
|
||||||
@@ -541,6 +559,7 @@ void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_request_locker.Lock();
|
m_request_locker.Lock();
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((request->type & wxSocketBase::REQ_WAIT) != 0) {
|
if ((request->type & wxSocketBase::REQ_WAIT) != 0) {
|
||||||
m_thread_requester->ProcessWaitEvent(request);
|
m_thread_requester->ProcessWaitEvent(request);
|
||||||
@@ -559,6 +578,7 @@ void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
request->done = TRUE;
|
request->done = TRUE;
|
||||||
|
#if wxUSE_THREADS
|
||||||
m_request_locker.Unlock();
|
m_request_locker.Unlock();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -260,6 +260,65 @@ wxSocketBase& wxSocketBase::Read(char* buffer, size_t nbytes)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxSocketBase& wxSocketBase::ReadMsg(char* buffer, size_t nbytes)
|
||||||
|
{
|
||||||
|
unsigned long len, len2, sig;
|
||||||
|
struct {
|
||||||
|
char sig[4];
|
||||||
|
char len[4];
|
||||||
|
} msg;
|
||||||
|
|
||||||
|
// sig should be an explicit 32-bit unsigned integer; I've seen
|
||||||
|
// compilers in which size_t was actually a 16-bit unsigned integer
|
||||||
|
|
||||||
|
Read((char *)&msg, sizeof(msg));
|
||||||
|
if (m_lcount != sizeof(msg))
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
sig = msg.sig[0] & 0xff;
|
||||||
|
sig |= (size_t)(msg.sig[1] & 0xff) << 8;
|
||||||
|
sig |= (size_t)(msg.sig[2] & 0xff) << 16;
|
||||||
|
sig |= (size_t)(msg.sig[3] & 0xff) << 24;
|
||||||
|
|
||||||
|
if (sig != 0xfeeddead)
|
||||||
|
return *this;
|
||||||
|
len = msg.len[0] & 0xff;
|
||||||
|
len |= (size_t)(msg.len[1] & 0xff) << 8;
|
||||||
|
len |= (size_t)(msg.len[2] & 0xff) << 16;
|
||||||
|
len |= (size_t)(msg.len[3] & 0xff) << 24;
|
||||||
|
|
||||||
|
// len2 is incorrectly computed in the original; this sequence is
|
||||||
|
// the fix
|
||||||
|
if (len > nbytes) {
|
||||||
|
len2 = len - nbytes;
|
||||||
|
len = nbytes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
len2 = 0;
|
||||||
|
|
||||||
|
// the "len &&" in the following statement is necessary so that
|
||||||
|
// we don't attempt to read (and possibly hang the system)
|
||||||
|
// if the message was zero bytes long
|
||||||
|
if (len && Read(buffer, len).LastCount() != len)
|
||||||
|
return *this;
|
||||||
|
if (len2 && (Read(NULL, len2).LastCount() != len2))
|
||||||
|
return *this;
|
||||||
|
if (Read((char *)&msg, sizeof(msg)).LastCount() != sizeof(msg))
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
sig = msg.sig[0] & 0xff;
|
||||||
|
sig |= (size_t)(msg.sig[1] & 0xff) << 8;
|
||||||
|
sig |= (size_t)(msg.sig[2] & 0xff) << 16;
|
||||||
|
sig |= (size_t)(msg.sig[3] & 0xff) << 24;
|
||||||
|
// ERROR
|
||||||
|
// we return *this either way, so a smart optimizer will
|
||||||
|
// optimize the following sequence out; I'm leaving it in anyway
|
||||||
|
if (sig != 0xdeadfeed)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
wxSocketBase& wxSocketBase::Peek(char* buffer, size_t nbytes)
|
wxSocketBase& wxSocketBase::Peek(char* buffer, size_t nbytes)
|
||||||
{
|
{
|
||||||
m_lcount = GetPushback(buffer, nbytes, TRUE);
|
m_lcount = GetPushback(buffer, nbytes, TRUE);
|
||||||
@@ -282,9 +341,54 @@ wxSocketBase& wxSocketBase::Write(const char *buffer, size_t nbytes)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxSocketBase& wxSocketBase::WriteMsg(const char *buffer, size_t nbytes)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
char sig[4];
|
||||||
|
char len[4];
|
||||||
|
} msg;
|
||||||
|
|
||||||
|
// warning about 'cast truncates constant value'
|
||||||
|
#ifdef __VISUALC__
|
||||||
|
#pragma warning(disable: 4310)
|
||||||
|
#endif // __VISUALC__
|
||||||
|
|
||||||
|
msg.sig[0] = (char) 0xad;
|
||||||
|
msg.sig[1] = (char) 0xde;
|
||||||
|
msg.sig[2] = (char) 0xed;
|
||||||
|
msg.sig[3] = (char) 0xfe;
|
||||||
|
|
||||||
|
msg.len[0] = (char) nbytes & 0xff;
|
||||||
|
msg.len[1] = (char) (nbytes >> 8) & 0xff;
|
||||||
|
msg.len[2] = (char) (nbytes >> 16) & 0xff;
|
||||||
|
msg.len[3] = (char) (nbytes >> 24) & 0xff;
|
||||||
|
|
||||||
|
if (Write((char *)&msg, sizeof(msg)).LastCount() < sizeof(msg))
|
||||||
|
return *this;
|
||||||
|
if (Write(buffer, nbytes).LastCount() < nbytes)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
msg.sig[0] = (char) 0xed;
|
||||||
|
msg.sig[1] = (char) 0xfe;
|
||||||
|
msg.sig[2] = (char) 0xad;
|
||||||
|
msg.sig[3] = (char) 0xde;
|
||||||
|
msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
|
||||||
|
Write((char *)&msg, sizeof(msg));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
#ifdef __VISUALC__
|
||||||
|
#pragma warning(default: 4310)
|
||||||
|
#endif // __VISUALC__
|
||||||
|
}
|
||||||
|
|
||||||
wxSocketBase& wxSocketBase::Unread(const char *buffer, size_t nbytes)
|
wxSocketBase& wxSocketBase::Unread(const char *buffer, size_t nbytes)
|
||||||
{
|
{
|
||||||
CreatePushbackAfter(buffer, nbytes);
|
m_lcount = 0;
|
||||||
|
if (nbytes != 0) {
|
||||||
|
CreatePushbackAfter(buffer, nbytes);
|
||||||
|
m_lcount = nbytes;
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +408,7 @@ bool wxSocketBase::IsData() const
|
|||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
FD_ZERO(&sock_set);
|
FD_ZERO(&sock_set);
|
||||||
FD_SET(m_fd, &sock_set);
|
FD_SET(m_fd, &sock_set);
|
||||||
select(FD_SETSIZE, &sock_set, NULL, NULL, &tv);
|
select(m_fd+1, &sock_set, NULL, NULL, &tv);
|
||||||
|
|
||||||
m_internal->ReleaseFD();
|
m_internal->ReleaseFD();
|
||||||
|
|
||||||
@@ -424,7 +528,9 @@ void wxSocketBase::RestoreState()
|
|||||||
state = (SocketState *)node->Data();
|
state = (SocketState *)node->Data();
|
||||||
|
|
||||||
SetFlags(state->socket_flags);
|
SetFlags(state->socket_flags);
|
||||||
|
m_internal->AcquireData();
|
||||||
m_neededreq = state->evt_notify_state;
|
m_neededreq = state->evt_notify_state;
|
||||||
|
m_internal->ReleaseData();
|
||||||
m_cbk = state->c_callback;
|
m_cbk = state->c_callback;
|
||||||
m_cdata = state->c_callback_data;
|
m_cdata = state->c_callback_data;
|
||||||
Notify(state->notify_state);
|
Notify(state->notify_state);
|
||||||
@@ -682,7 +788,6 @@ void wxSocketBase::WantBuffer(char *buffer, size_t nbytes,
|
|||||||
SockRequest *buf = new SockRequest;
|
SockRequest *buf = new SockRequest;
|
||||||
|
|
||||||
SaveState();
|
SaveState();
|
||||||
m_internal->StopWaiter();
|
|
||||||
buf->buffer = buffer;
|
buf->buffer = buffer;
|
||||||
buf->size = nbytes;
|
buf->size = nbytes;
|
||||||
buf->done = FALSE;
|
buf->done = FALSE;
|
||||||
|
@@ -340,7 +340,7 @@ size_t wxStreamBuffer::Read(wxStreamBuffer *s_buf)
|
|||||||
if (m_mode == write)
|
if (m_mode == write)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while (bytes_read == BUF_TEMP_SIZE) {
|
while (bytes_read != 0) {
|
||||||
bytes_read = Read(buf, bytes_read);
|
bytes_read = Read(buf, bytes_read);
|
||||||
bytes_read = s_buf->Write(buf, bytes_read);
|
bytes_read = s_buf->Write(buf, bytes_read);
|
||||||
s += bytes_read;
|
s += bytes_read;
|
||||||
|
@@ -271,6 +271,8 @@ private:
|
|||||||
// state
|
// state
|
||||||
// 2. The Delete() function blocks until the condition is signaled when the
|
// 2. The Delete() function blocks until the condition is signaled when the
|
||||||
// thread exits.
|
// thread exits.
|
||||||
|
// GL: On Linux, this may fail because we can have a deadlock in either
|
||||||
|
// SignalExit() or Wait(): so we add m_end_mutex for the finalization.
|
||||||
wxMutex m_mutex, m_end_mutex;
|
wxMutex m_mutex, m_end_mutex;
|
||||||
wxCondition m_cond;
|
wxCondition m_cond;
|
||||||
|
|
||||||
@@ -299,7 +301,7 @@ void *wxThreadInternal::PthreadStart(void *ptr)
|
|||||||
}
|
}
|
||||||
#if HAVE_THREAD_CLEANUP_FUNCTIONS
|
#if HAVE_THREAD_CLEANUP_FUNCTIONS
|
||||||
// Install the cleanup handler.
|
// Install the cleanup handler.
|
||||||
// pthread_cleanup_push(wxThreadInternal::PthreadCleanup, ptr);
|
pthread_cleanup_push(wxThreadInternal::PthreadCleanup, ptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// wait for the condition to be signaled from Run()
|
// wait for the condition to be signaled from Run()
|
||||||
@@ -311,7 +313,7 @@ void *wxThreadInternal::PthreadStart(void *ptr)
|
|||||||
status = thread->Entry();
|
status = thread->Entry();
|
||||||
|
|
||||||
#if HAVE_THREAD_CLEANUP_FUNCTIONS
|
#if HAVE_THREAD_CLEANUP_FUNCTIONS
|
||||||
// pthread_cleanup_pop(FALSE);
|
pthread_cleanup_pop(FALSE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// terminate the thread
|
// terminate the thread
|
||||||
@@ -371,8 +373,16 @@ wxThreadInternal::~wxThreadInternal()
|
|||||||
// note that m_mutex will be unlocked by the thread which waits for our
|
// note that m_mutex will be unlocked by the thread which waits for our
|
||||||
// termination
|
// termination
|
||||||
|
|
||||||
// m_end_mutex can be unlocked here.
|
// In the case, we didn't start the thread, all these mutex are locked:
|
||||||
m_end_mutex.Unlock();
|
// we must unlock them.
|
||||||
|
if (m_mutex.IsLocked())
|
||||||
|
m_mutex.Unlock();
|
||||||
|
|
||||||
|
if (m_end_mutex.IsLocked())
|
||||||
|
m_end_mutex.Unlock();
|
||||||
|
|
||||||
|
if (m_mutexSuspend.IsLocked())
|
||||||
|
m_mutexSuspend.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxThreadError wxThreadInternal::Run()
|
wxThreadError wxThreadInternal::Run()
|
||||||
@@ -748,6 +758,14 @@ bool wxThread::TestDestroy()
|
|||||||
|
|
||||||
wxThread::~wxThread()
|
wxThread::~wxThread()
|
||||||
{
|
{
|
||||||
|
m_critsect.Enter();
|
||||||
|
if (p_internal->GetState() != STATE_EXITED &&
|
||||||
|
p_internal->GetState() != STATE_NEW)
|
||||||
|
wxLogDebug(_T("The thread is being destroyed althought it is still running ! The application may crash."));
|
||||||
|
|
||||||
|
m_critsect.Leave();
|
||||||
|
|
||||||
|
delete p_internal;
|
||||||
// remove this thread from the global array
|
// remove this thread from the global array
|
||||||
gs_allThreads.Remove(this);
|
gs_allThreads.Remove(this);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user