diff --git a/mozilla/netwerk/protocol/http/src/nsHttpConnection.cpp b/mozilla/netwerk/protocol/http/src/nsHttpConnection.cpp index 575b4a13fac..af6a46d41af 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpConnection.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpConnection.cpp @@ -38,29 +38,6 @@ static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID); -//----------------------------------------------------------------------------- -// helpers... -//----------------------------------------------------------------------------- - -static void *PR_CALLBACK -TransactionReleaseEventHandler(PLEvent *ev) -{ - nsHttpTransaction *trans = - NS_STATIC_CAST(nsHttpTransaction *, PL_GetEventOwner(ev)); - - LOG(("TransactionReleaseEventHandler [trans=%x refcnt=%u] calling release...\n", - trans, trans->RefCnt())); - - NS_RELEASE(trans); - return 0; -} - -static void PR_CALLBACK -TransactionReleaseDestroyHandler(PLEvent *ev) -{ - delete ev; -} - //----------------------------------------------------------------------------- // nsHttpConnection //----------------------------------------------------------------------------- @@ -86,10 +63,7 @@ nsHttpConnection::~nsHttpConnection() NS_IF_RELEASE(mConnectionInfo); mConnectionInfo = 0; - if (mTransaction) { - ProxyReleaseTransaction(mTransaction); - mTransaction = 0; - } + NS_IF_RELEASE(mTransaction); // warning: this call could result in OnStopRequest being called. this // is why we are careful to null out mTransaction and mConnectionInfo ;-) @@ -111,7 +85,7 @@ nsHttpConnection::Init(nsHttpConnectionInfo *info) return NS_OK; } -// never called from the socket thread +// called from any thread nsresult nsHttpConnection::SetTransaction(nsHttpTransaction *transaction) { @@ -125,22 +99,15 @@ nsHttpConnection::SetTransaction(nsHttpTransaction *transaction) mTransaction = transaction; NS_ADDREF(mTransaction); - // grab a reference to the calling thread's event queue. - mConsumerEventQ = 0; - nsCOMPtr eqs; - nsHttpHandler::get()->GetEventQueueService(getter_AddRefs(eqs)); - if (eqs) - eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(mConsumerEventQ)); - // build a proxy for the progress event sink mProgressSink = 0; - if (mTransaction->Callbacks()) { + if (mTransaction->Callbacks() && mTransaction->ConsumerEventQ()) { nsCOMPtr temp = do_GetInterface(mTransaction->Callbacks()); if (temp) { nsCOMPtr mgr; nsHttpHandler::get()->GetProxyObjectManager(getter_AddRefs(mgr)); if (mgr) - mgr->GetProxyForObject(mConsumerEventQ, + mgr->GetProxyForObject(mTransaction->ConsumerEventQ(), NS_GET_IID(nsIProgressEventSink), temp, PROXY_ASYNC | PROXY_ALWAYS, @@ -429,26 +396,6 @@ nsHttpConnection::CreateTransport() return rv; } -nsresult -nsHttpConnection::ProxyReleaseTransaction(nsHttpTransaction *trans) -{ - LOG(("nsHttpConnection::ProxyReleaseTransaction [this=%x trans=%x refcnt=%u]\n", - this, trans, trans->RefCnt())); - - NS_ENSURE_TRUE(mConsumerEventQ, NS_ERROR_NOT_INITIALIZED); - NS_ENSURE_ARG_POINTER(trans); - - PLEvent *event = new PLEvent; - if (!event) - return NS_ERROR_OUT_OF_MEMORY; - - PL_InitEvent(event, trans, - TransactionReleaseEventHandler, - TransactionReleaseDestroyHandler); - - return mConsumerEventQ->PostEvent(event); -} - nsresult nsHttpConnection::SetupSSLProxyConnect() { @@ -549,17 +496,15 @@ nsHttpConnection::OnStopRequest(nsIRequest *request, nsISupports *ctxt, mProgressSink = 0; // make sure mTransaction is clear before calling OnStopTransaction - nsHttpTransaction *trans = mTransaction; - mTransaction = nsnull; + if (mTransaction) { + nsHttpTransaction *trans = mTransaction; + mTransaction = nsnull; - trans->OnStopTransaction(status); + trans->OnStopTransaction(status); + NS_RELEASE(trans); + } - // because this could be the last reference to the transaction and - // because we are on the socket transport thread, it is essential that - // this final release be proxied to the thread which called - // SetTransaction. - if (NS_FAILED(ProxyReleaseTransaction(trans))) - NS_NOTREACHED("proxy release of transaction failed"); + nsHttpHandler::get()->ReclaimConnection(this); } // no point in returning anything else but NS_OK return NS_OK; diff --git a/mozilla/netwerk/protocol/http/src/nsHttpHandler.cpp b/mozilla/netwerk/protocol/http/src/nsHttpHandler.cpp index b9d7a55d827..25847824344 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpHandler.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpHandler.cpp @@ -45,6 +45,7 @@ #include "nsPrintfCString.h" #include "nsCOMPtr.h" #include "nsNetCID.h" +#include "nsAutoLock.h" #include "prprf.h" #if defined(XP_UNIX) || defined(XP_BEOS) @@ -143,6 +144,11 @@ nsHttpHandler::~nsHttpHandler() mAuthCache = nsnull; } + if (mConnectionLock) { + PR_DestroyLock(mConnectionLock); + mConnectionLock = nsnull; + } + mGlobalInstance = nsnull; } @@ -186,6 +192,10 @@ nsHttpHandler::Init() return rv; } + mConnectionLock = PR_NewLock(); + if (!mConnectionLock) + return NS_ERROR_OUT_OF_MEMORY; + mPrefs = do_GetService(kPrefServiceCID, &rv); if (NS_FAILED(rv)) { NS_WARNING("unable to continue without prefs service"); @@ -326,75 +336,23 @@ nsHttpHandler::GetCacheSession(nsCacheStoragePolicy storagePolicy, return NS_OK; } +// may be called from any thread nsresult nsHttpHandler::InitiateTransaction(nsHttpTransaction *trans, nsHttpConnectionInfo *ci, PRBool failIfBusy) { - nsresult rv; - LOG(("nsHttpHandler::InitiateTransaction\n")); NS_ENSURE_ARG_POINTER(trans); NS_ENSURE_ARG_POINTER(ci); - if ((mActiveConnections.Count() == mMaxConnections) || - (CountActiveConnections(ci) == PRUint32(mMaxConnectionsPerServer))) { - LOG(("unable to perform the transaction at this time [trans=%x]\n", trans)); - if (failIfBusy) return NS_ERROR_FAILURE; - return EnqueueTransaction(trans, ci); - } + nsAutoLock lock(mConnectionLock); - nsHttpConnection *conn = nsnull; - - // search the idle connection list - PRInt32 i; - for (i=0; iConnectionInfo()->Host(), conn->ConnectionInfo()->Port())); - - // we check if the connection can be reused before even checking if it - // is a "matching" connection. this is how we keep the idle connection - // list fresh. we could alternatively use some sort of timer for this. - if (!conn->CanReuse()) { - LOG(("dropping stale connection: [conn=%x]\n", conn)); - mIdleConnections.RemoveElementAt(i); - i--; - NS_RELEASE(conn); - } - else if (conn->ConnectionInfo()->Equals(ci)) { - LOG(("reusing connection [conn=%x]\n", conn)); - mIdleConnections.RemoveElementAt(i); - i--; - break; - } - conn = nsnull; - } - - if (!conn) { - LOG(("creating new connection...\n")); - NS_NEWXPCOM(conn, nsHttpConnection); - if (!conn) - return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(conn); - - rv = conn->Init(ci); - if (NS_FAILED(rv)) goto failed; - } - - rv = conn->SetTransaction(trans); - if (NS_FAILED(rv)) goto failed; - - mActiveConnections.AppendElement(conn); - return NS_OK; - -failed: - NS_RELEASE(conn); - return rv; + return InitiateTransaction_Locked(trans, ci, failIfBusy); } +// may be called from any thread nsresult nsHttpHandler::ReclaimConnection(nsHttpConnection *conn) { @@ -403,6 +361,8 @@ nsHttpHandler::ReclaimConnection(nsHttpConnection *conn) LOG(("nsHttpHandler::ReclaimConnection [conn=%x keep-alive=%d]\n", conn, conn->CanReuse())); + nsAutoLock lock(mConnectionLock); + // remove connection from the active connection list mActiveConnections.RemoveElement(conn); @@ -446,8 +406,9 @@ nsHttpHandler::CancelPendingTransaction(nsHttpTransaction *trans, NS_ENSURE_ARG_POINTER(trans); - nsPendingTransaction *pt = nsnull; + nsAutoLock lock(mConnectionLock); + nsPendingTransaction *pt = nsnull; PRInt32 i; for (i=0; iTransaction(), - pt->ConnectionInfo(), - PR_TRUE); + nsresult rv = InitiateTransaction_Locked(pt->Transaction(), + pt->ConnectionInfo(), + PR_TRUE); if (NS_SUCCEEDED(rv)) { mTransactionQ.RemoveElementAt(i); delete pt; @@ -651,6 +613,7 @@ nsHttpHandler::ProcessTransactionQ() } } +// called while holding the connection lock nsresult nsHttpHandler::EnqueueTransaction(nsHttpTransaction *trans, nsHttpConnectionInfo *ci) @@ -667,14 +630,90 @@ nsHttpHandler::EnqueueTransaction(nsHttpTransaction *trans, return NS_OK; } +nsresult +nsHttpHandler::InitiateTransaction_Locked(nsHttpTransaction *trans, + nsHttpConnectionInfo *ci, + PRBool failIfBusy) +{ + nsresult rv; + + LOG(("nsHttpHandler::InitiateTransaction_Locked [failIfBusy=%d]\n", failIfBusy)); + + if ((mActiveConnections.Count() == mMaxConnections) || + (CountActiveConnections(ci) == PRUint32(mMaxConnectionsPerServer))) { + LOG(("unable to perform the transaction at this time [trans=%x]\n", trans)); + if (failIfBusy) return NS_ERROR_FAILURE; + return EnqueueTransaction(trans, ci); + } + + nsHttpConnection *conn = nsnull; + + // search the idle connection list + PRInt32 i; + for (i=0; iConnectionInfo()->Host(), conn->ConnectionInfo()->Port())); + + // we check if the connection can be reused before even checking if it + // is a "matching" connection. this is how we keep the idle connection + // list fresh. we could alternatively use some sort of timer for this. + if (!conn->CanReuse()) { + LOG(("dropping stale connection: [conn=%x]\n", conn)); + mIdleConnections.RemoveElementAt(i); + i--; + NS_RELEASE(conn); + } + else if (conn->ConnectionInfo()->Equals(ci)) { + LOG(("reusing connection [conn=%x]\n", conn)); + mIdleConnections.RemoveElementAt(i); + i--; + break; + } + conn = nsnull; + } + + if (!conn) { + LOG(("creating new connection...\n")); + NS_NEWXPCOM(conn, nsHttpConnection); + if (!conn) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(conn); + + rv = conn->Init(ci); + if (NS_FAILED(rv)) goto failed; + } + + rv = conn->SetTransaction(trans); + if (NS_FAILED(rv)) goto failed; + + mActiveConnections.AppendElement(conn); + return NS_OK; + +failed: + NS_RELEASE(conn); + return rv; +} + PRUint32 nsHttpHandler::CountActiveConnections(nsHttpConnectionInfo *ci) { - PRUint32 count = mActiveConnections.Count(); + PRUint32 count = 0; + nsHttpConnection *conn = 0; - LOG(("nsHttpHandler::CountActiveConnections [host=%s:%d] found %u\n", - ci->Host(), ci->Port(), count)); + LOG(("nsHttpHandler::CountActiveConnections [host=%s:%d]\n", + ci->Host(), ci->Port())); + PRInt32 i; + for (i=0; iConnectionInfo()->Equals(ci)) + count++; + } + + LOG(("found count=%u\n", count)); return count; } @@ -692,7 +731,7 @@ nsHttpHandler::CountIdleConnections(nsHttpConnectionInfo *ci) PRInt32 i; for (i=0; iConnectionInfo()->Equals(ci)) { diff --git a/mozilla/netwerk/protocol/http/src/nsHttpHandler.h b/mozilla/netwerk/protocol/http/src/nsHttpHandler.h index 3f990426e62..c1eb7def801 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpHandler.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpHandler.h @@ -106,16 +106,17 @@ public: // Called to kick-off a new transaction, by default the transaction // will be put on the pending transaction queue if it cannot be - // initiated at this time. + // initiated at this time. Callable from any thread. nsresult InitiateTransaction(nsHttpTransaction *, nsHttpConnectionInfo *, PRBool failIfBusy = PR_FALSE); - // Called when a connection is done processing a transaction + // Called when a connection is done processing a transaction. Callable + // from any thread. nsresult ReclaimConnection(nsHttpConnection *); // Called when a transaction, which is not assigned to a connection, - // is canceled. + // is canceled. Callable from any thread. nsresult CancelPendingTransaction(nsHttpTransaction *, nsresult status); // @@ -161,6 +162,11 @@ private: void ProcessTransactionQ(); nsresult EnqueueTransaction(nsHttpTransaction *, nsHttpConnectionInfo *); + // Called with mConnectionLock held + nsresult InitiateTransaction_Locked(nsHttpTransaction *, + nsHttpConnectionInfo *, + PRBool failIfBusy = PR_FALSE); + PRUint32 CountActiveConnections(nsHttpConnectionInfo *); PRUint32 CountIdleConnections(nsHttpConnectionInfo *); @@ -195,7 +201,7 @@ private: nsCOMPtr mMimeService; // the authentication credentials cache - nsHttpAuthCache *mAuthCache; + nsHttpAuthCache *mAuthCache; // // prefs @@ -231,6 +237,7 @@ private: nsVoidArray mActiveConnections; // list of nsHttpConnection objects nsVoidArray mIdleConnections; // list of nsHttpConnection objects nsVoidArray mTransactionQ; // list of nsPendingTransaction objects + PRLock *mConnectionLock; // protect connection lists // useragent components nsXPIDLCString mAppName; diff --git a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp index 841dee7cdb8..60356d9c670 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp @@ -32,45 +32,6 @@ #include "pratom.h" #include "plevent.h" -//----------------------------------------------------------------------------- -// helpers... -//----------------------------------------------------------------------------- - -static void *PR_CALLBACK -TransactionRestartEventHandler(PLEvent *ev) -{ - nsHttpTransaction *trans = - NS_STATIC_CAST(nsHttpTransaction *, PL_GetEventOwner(ev)); - - LOG(("TransactionRestartEventHandler [trans=%x]\n", trans)); - - NS_PRECONDITION(trans->Connection() && - trans->Connection()->ConnectionInfo(), "oops"); - - if (trans->Connection()) { - nsHttpConnectionInfo *ci = trans->Connection()->ConnectionInfo(); - if (ci) { - NS_ADDREF(ci); - - // clean up the old connection - nsHttpHandler::get()->ReclaimConnection(trans->Connection()); - trans->SetConnection(nsnull); - - // initiate the transaction again - nsHttpHandler::get()->InitiateTransaction(trans, ci); - NS_RELEASE(ci); - } - } - NS_RELEASE(trans); - return 0; -} - -static void PR_CALLBACK -TransactionRestartDestroyHandler(PLEvent *ev) -{ - delete ev; -} - //----------------------------------------------------------------------------- // nsHttpTransaction //----------------------------------------------------------------------------- @@ -103,10 +64,7 @@ nsHttpTransaction::~nsHttpTransaction() { LOG(("Destroying nsHttpTransaction @%x\n", this)); - if (mConnection) { - nsHttpHandler::get()->ReclaimConnection(mConnection); - NS_RELEASE(mConnection); - } + NS_IF_RELEASE(mConnection); if (mChunkedDecoder) delete mChunkedDecoder; @@ -122,6 +80,12 @@ nsHttpTransaction::SetupRequest(nsHttpRequestHead *requestHead, NS_ENSURE_ARG_POINTER(requestHead); + // grab a reference to the calling thread's event queue. + nsCOMPtr eqs; + nsHttpHandler::get()->GetEventQueueService(getter_AddRefs(eqs)); + if (eqs) + eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(mConsumerEventQ)); + if (requestHead->Method() == nsHttp::Head) mNoContent = PR_TRUE; @@ -150,6 +114,9 @@ nsHttpTransaction::SetupRequest(nsHttpRequestHead *requestHead, nsresult nsHttpTransaction::SetConnection(nsHttpConnection *conn) { + LOG(("nsHttpTransaction::SetConnection [this=%x mConnection=%x conn=%x]\n", + this, mConnection, conn)); + mConnection = conn; NS_IF_ADDREF(mConnection); return NS_OK; @@ -229,11 +196,17 @@ nsHttpTransaction::OnDataReadable(nsIInputStream *is) // we don't want the connection to send anymore notifications to us. mConnection->DropTransaction(); - // the transaction needs to be restarted from the thread on which - // it was created. - rv = ProxyRestartTransaction(mConnection->ConsumerEventQ()); - NS_ASSERTION(NS_SUCCEEDED(rv), "ProxyRestartTransaction failed"); + nsHttpConnectionInfo *ci = mConnection->ConnectionInfo(); + NS_ADDREF(ci); + // we must release the connection before calling initiate transaction + // since we will be getting a new connection. + NS_RELEASE(mConnection); + + rv = nsHttpHandler::get()->InitiateTransaction(this, ci); + NS_ASSERTION(NS_SUCCEEDED(rv), "InitiateTransaction failed"); + + NS_RELEASE(ci); NS_RELEASE_THIS(); return NS_BINDING_ABORTED; } @@ -502,7 +475,13 @@ nsHttpTransaction::HandleContent(char *buf, if (priorVal == 0 && mConnection) { // let the connection know that we are done with it; this should // result in OnStopTransaction being fired. - return mConnection->OnTransactionComplete(NS_OK); + rv = mConnection->OnTransactionComplete(NS_OK); + + // at this point, we no longer need the connection + //nsHttpHandler::get()->ReclaimConnection(mConnection); + NS_RELEASE(mConnection); + + return rv; } return NS_OK; } @@ -512,34 +491,83 @@ nsHttpTransaction::HandleContent(char *buf, return (!mNoContent && !*countRead) ? NS_BASE_STREAM_WOULD_BLOCK : NS_OK; } -nsresult -nsHttpTransaction::ProxyRestartTransaction(nsIEventQueue *eventQ) +void +nsHttpTransaction::DeleteSelfOnConsumerThread() { - LOG(("nsHttpTransaction::ProxyRestartTransaction [this=%x]\n", this)); + nsCOMPtr eqs; + nsCOMPtr currentEventQ; - NS_ENSURE_ARG_POINTER(eventQ); - NS_PRECONDITION(!mResponseHead, "already received a (partial) response!"); + LOG(("nsHttpTransaction::DeleteSelfOnConsumerThread [this=%x]\n", this)); - PLEvent *event = new PLEvent; - if (!event) - return NS_ERROR_OUT_OF_MEMORY; + nsHttpHandler::get()->GetEventQueueService(getter_AddRefs(eqs)); + if (eqs) + eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(currentEventQ)); - NS_ADDREF_THIS(); + if (currentEventQ == mConsumerEventQ) + delete this; + else { + LOG(("proxying delete to consumer thread...\n")); - PL_InitEvent(event, this, - TransactionRestartEventHandler, - TransactionRestartDestroyHandler); + PLEvent *event = new PLEvent; + if (!event) { + NS_WARNING("out of memory"); + // probably better to leak |this| than to delete it on this thread. + return; + } - return eventQ->PostEvent(event); + PL_InitEvent(event, this, + nsHttpTransaction::DeleteThis_EventHandlerFunc, + nsHttpTransaction::DeleteThis_EventCleanupFunc); + + PRStatus status = mConsumerEventQ->PostEvent(event); + NS_ASSERTION(status == PR_SUCCESS, "PostEvent failed"); + } +} + +void *PR_CALLBACK +nsHttpTransaction::DeleteThis_EventHandlerFunc(PLEvent *ev) +{ + nsHttpTransaction *trans = + NS_STATIC_CAST(nsHttpTransaction *, PL_GetEventOwner(ev)); + + LOG(("nsHttpTransaction::DeleteThis_EventHandlerFunc [trans=%x]\n", trans)); + + delete trans; + return nsnull; +} + +void PR_CALLBACK +nsHttpTransaction::DeleteThis_EventCleanupFunc(PLEvent *ev) +{ + delete ev; } //----------------------------------------------------------------------------- // nsHttpTransaction::nsISupports //----------------------------------------------------------------------------- -NS_IMPL_THREADSAFE_ISUPPORTS2(nsHttpTransaction, - nsIRequest, - nsIInputStream) +NS_IMPL_THREADSAFE_ADDREF(nsHttpTransaction) + +NS_IMETHODIMP_(nsrefcnt) +nsHttpTransaction::Release() +{ + nsrefcnt count; + NS_PRECONDITION(0 != mRefCnt, "dup release"); + count = PR_AtomicDecrement((PRInt32 *) &mRefCnt); + NS_LOG_RELEASE(this, count, "nsHttpTransaction"); + if (0 == count) { + mRefCnt = 1; /* stablize */ + // it is essential that the transaction be destroyed on the consumer + // thread (we could be holding the last reference to our consumer). + DeleteSelfOnConsumerThread(); + return 0; + } + return count; +} + +NS_IMPL_THREADSAFE_QUERY_INTERFACE2(nsHttpTransaction, + nsIRequest, + nsIInputStream) //----------------------------------------------------------------------------- // nsHttpTransaction::nsIRequest @@ -592,8 +620,10 @@ nsHttpTransaction::Cancel(nsresult status) // completion, in which case we should ignore this cancelation request. PRInt32 priorVal = PR_AtomicSet(&mTransactionDone, 1); - if (priorVal == 0) + if (priorVal == 0) { mConnection->OnTransactionComplete(status); + NS_RELEASE(mConnection); + } return NS_OK; } diff --git a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h index 3fa8e636ebb..39e2ba7119b 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h @@ -29,6 +29,7 @@ #include "nsIStreamListener.h" #include "nsIInputStream.h" #include "nsIInterfaceRequestor.h" +#include "nsIEventQueue.h" #include "nsXPIDLString.h" #include "nsCOMPtr.h" @@ -36,7 +37,6 @@ class nsHttpRequestHead; class nsHttpResponseHead; class nsHttpConnection; class nsHttpChunkedDecoder; -class nsIEventQueue; //----------------------------------------------------------------------------- // nsHttpTransaction represents a single HTTP transaction. It is thread-safe, @@ -63,11 +63,12 @@ public: // Called to initialize the transaction nsresult SetupRequest(nsHttpRequestHead *, nsIInputStream *); - nsIStreamListener *Listener() { return mListener; } - nsHttpConnection *Connection() { return mConnection; } - nsHttpRequestHead *RequestHead() { return mRequestHead; } - nsHttpResponseHead *ResponseHead() { return mResponseHead; } - nsIInterfaceRequestor *Callbacks() { return mCallbacks; } + nsIStreamListener *Listener() { return mListener; } + nsHttpConnection *Connection() { return mConnection; } + nsHttpRequestHead *RequestHead() { return mRequestHead; } + nsHttpResponseHead *ResponseHead() { return mResponseHead; } + nsIInterfaceRequestor *Callbacks() { return mCallbacks; } + nsIEventQueue *ConsumerEventQ() { return mConsumerEventQ; } // Called to take ownership of the response headers; the transaction // will drop any reference to the response headers after this call. @@ -90,11 +91,15 @@ private: void ParseLineSegment(char *seg, PRUint32 len); nsresult ParseHead(char *, PRUint32 count, PRUint32 *countRead); nsresult HandleContent(char *, PRUint32 count, PRUint32 *countRead); - nsresult ProxyRestartTransaction(nsIEventQueue *); + void DeleteSelfOnConsumerThread(); + + static void *PR_CALLBACK DeleteThis_EventHandlerFunc(PLEvent *); + static void PR_CALLBACK DeleteThis_EventCleanupFunc(PLEvent *); private: nsCOMPtr mListener; nsCOMPtr mCallbacks; + nsCOMPtr mConsumerEventQ; nsHttpConnection *mConnection; // hard ref