diff --git a/mozilla/chrome/src/nsChromeProtocolHandler.cpp b/mozilla/chrome/src/nsChromeProtocolHandler.cpp index 6e647f86c27..8c7cdd5e5ca 100644 --- a/mozilla/chrome/src/nsChromeProtocolHandler.cpp +++ b/mozilla/chrome/src/nsChromeProtocolHandler.cpp @@ -47,12 +47,10 @@ #include "nsCOMPtr.h" #include "nsContentCID.h" #include "nsCRT.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsIChannel.h" #include "nsIChromeRegistry.h" #include "nsIComponentManager.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" #include "nsIFastLoadService.h" #include "nsIFile.h" #include "nsIFileURL.h" @@ -117,16 +115,12 @@ protected: nsCOMPtr mOwner; nsresult mStatus; - static NS_HIDDEN_(nsresult) - PostLoadEvent(nsCachedChromeChannel* aChannel, PLHandleEventProc aHandler); - - static void* PR_CALLBACK HandleLoadEvent(PLEvent* aEvent); - static void PR_CALLBACK DestroyLoadEvent(PLEvent* aEvent); - #ifdef PR_LOGGING static PRLogModuleInfo* gLog; #endif + void HandleLoadEvent(); + public: nsCachedChromeChannel(nsIURI* aURI); @@ -144,18 +138,15 @@ public: NS_IMETHOD GetLoadFlags(nsLoadFlags *); NS_IMETHOD SetLoadFlags(nsLoadFlags); -// nsIChannel + // nsIChannel NS_DECL_NSICHANNEL - }; #ifdef PR_LOGGING PRLogModuleInfo* nsCachedChromeChannel::gLog; #endif -NS_IMPL_ISUPPORTS2(nsCachedChromeChannel, - nsIChannel, - nsIRequest) +NS_IMPL_ISUPPORTS2(nsCachedChromeChannel, nsIChannel, nsIRequest) nsCachedChromeChannel::nsCachedChromeChannel(nsIURI* aURI) : mURI(aURI) @@ -220,10 +211,13 @@ nsCachedChromeChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) LOG(("nsCachedChromeChannel[%p]: posting load event for %p", this, listener)); + nsCOMPtr event = + NS_NewRunnableMethod(this, &nsCachedChromeChannel::HandleLoadEvent); + // Queue an event to ourselves to let the stack unwind before // calling OnStartRequest(). This allows embedding to occur // before we fire OnStopRequest(). - rv = PostLoadEvent(this, HandleLoadEvent); + rv = NS_DispatchToCurrentThread(event); if (NS_FAILED(rv)) return rv; @@ -347,78 +341,42 @@ nsCachedChromeChannel::SetContentLength(PRInt32 aContentLength) return NS_ERROR_NOT_IMPLEMENTED; } -nsresult -nsCachedChromeChannel::PostLoadEvent(nsCachedChromeChannel* aChannel, - PLHandleEventProc aHandler) -{ - nsCOMPtr queue; - nsresult rv = NS_GetCurrentEventQ(getter_AddRefs(queue)); - if (NS_FAILED(rv)) - return rv; - - PLEvent* event = new PLEvent; - if (! event) - return NS_ERROR_OUT_OF_MEMORY; - - PL_InitEvent(event, - aChannel, - aHandler, - DestroyLoadEvent); - NS_ADDREF(aChannel); - - rv = queue->PostEvent(event); - if (NS_FAILED(rv)) - PL_DestroyEvent(event); - return rv; -} - -void* PR_CALLBACK -nsCachedChromeChannel::HandleLoadEvent(PLEvent* aEvent) +void +nsCachedChromeChannel::HandleLoadEvent() { // Fire the OnStartRequest() for the cached chrome channel, then - // queue another event to trigger the OnStopRequest()... - nsCachedChromeChannel* channel = (nsCachedChromeChannel*) aEvent->owner; + // trigger the OnStopRequest()... // If the load has been cancelled, then just bail now. We won't // send On[Start|Stop]Request(). - if (NS_FAILED(channel->mStatus)) - return nsnull; + if (NS_FAILED(mStatus)) + return; LOG(("nsCachedChromeChannel[%p]: firing OnStartRequest for %p", - channel, channel->mListener.get())); + this, mListener.get())); - (void) channel->mListener->OnStartRequest(channel, channel->mContext); + mListener->OnStartRequest(this, mContext); LOG(("nsCachedChromeChannel[%p]: firing OnStopRequest for %p", - channel, channel->mListener.get())); + this, mListener.get())); - (void) channel->mListener->OnStopRequest(channel, channel->mContext, - channel->mStatus); + mListener->OnStopRequest(this, mContext, mStatus); - if (channel->mLoadGroup) { + if (mLoadGroup) { LOG(("nsCachedChromeChannel[%p]: removing self from load group %p", - channel, channel->mLoadGroup.get())); - - (void) channel->mLoadGroup->RemoveRequest(channel, nsnull, channel->mStatus); + this, mLoadGroup.get())); + mLoadGroup->RemoveRequest(this, nsnull, mStatus); } - channel->mListener = nsnull; - channel->mContext = nsnull; - - return nsnull; -} - -void PR_CALLBACK -nsCachedChromeChannel::DestroyLoadEvent(PLEvent* aEvent) -{ - nsCachedChromeChannel* channel = (nsCachedChromeChannel*) aEvent->owner; - NS_RELEASE(channel); - delete aEvent; + mListener = nsnull; + mContext = nsnull; } //////////////////////////////////////////////////////////////////////////////// -NS_IMPL_THREADSAFE_ISUPPORTS2(nsChromeProtocolHandler, nsIProtocolHandler, nsISupportsWeakReference) +NS_IMPL_THREADSAFE_ISUPPORTS2(nsChromeProtocolHandler, + nsIProtocolHandler, + nsISupportsWeakReference) //////////////////////////////////////////////////////////////////////////////// // nsIProtocolHandler methods: diff --git a/mozilla/configure.in b/mozilla/configure.in index c2c38d8462f..357ea19e314 100644 --- a/mozilla/configure.in +++ b/mozilla/configure.in @@ -7135,6 +7135,14 @@ if test "$MOZ_PROFILESHARING"; then AC_DEFINE(MOZ_PROFILESHARING) fi +dnl ======================================================== +dnl enable ipc/ipcd +dnl ======================================================== +MOZ_ARG_ENABLE_BOOL(ipcd, +[ --enable-ipcd Enable IPC daemon], + MOZ_IPCD=1, + MOZ_IPCD= ) + dnl ======================================================== dnl disable profile locking dnl do no use this in applications that can have more than diff --git a/mozilla/content/base/public/nsContentUtils.h b/mozilla/content/base/public/nsContentUtils.h index 1fe35a0e6b6..78be224c1c2 100644 --- a/mozilla/content/base/public/nsContentUtils.h +++ b/mozilla/content/base/public/nsContentUtils.h @@ -79,7 +79,6 @@ class nsIStringBundle; class nsIContentPolicy; class nsILineBreaker; class nsIWordBreaker; -class nsIEventQueueService; class nsIJSRuntimeService; class nsIEventListenerManager; class nsIScriptContext; @@ -664,14 +663,6 @@ public: */ static nsIContentPolicy *GetContentPolicy(); - /** - * Return the event queue service - */ - static nsIEventQueueService* EventQueueService() - { - return sEventQueueService; - } - /** * Make sure that whatever value *aPtr contains at any given moment is * protected from JS GC until we remove the GC root. A call to this that @@ -863,8 +854,6 @@ private: static nsILineBreaker* sLineBreaker; static nsIWordBreaker* sWordBreaker; - static nsIEventQueueService* sEventQueueService; - // Holds pointers to nsISupports* that should be released at shutdown static nsVoidArray* sPtrsToPtrsToRelease; diff --git a/mozilla/content/base/src/nsContentUtils.cpp b/mozilla/content/base/src/nsContentUtils.cpp index 2f3c5812cd8..2458bd307c5 100644 --- a/mozilla/content/base/src/nsContentUtils.cpp +++ b/mozilla/content/base/src/nsContentUtils.cpp @@ -117,7 +117,6 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); #include "nsLWBrkCIID.h" #include "nsILineBreaker.h" #include "nsIWordBreaker.h" -#include "nsIEventQueueService.h" #include "jsdbgapi.h" #include "nsIJSRuntimeService.h" #include "nsIDOMDocumentXBL.h" @@ -159,7 +158,6 @@ nsIContentPolicy *nsContentUtils::sContentPolicyService; PRBool nsContentUtils::sTriedToGetContentPolicy = PR_FALSE; nsILineBreaker *nsContentUtils::sLineBreaker; nsIWordBreaker *nsContentUtils::sWordBreaker; -nsIEventQueueService *nsContentUtils::sEventQueueService; nsVoidArray *nsContentUtils::sPtrsToPtrsToRelease; nsIJSRuntimeService *nsContentUtils::sJSRuntimeService; JSRuntime *nsContentUtils::sScriptRuntime; @@ -300,9 +298,6 @@ nsContentUtils::Init() rv = CallGetService(NS_WBRK_CONTRACTID, &sWordBreaker); NS_ENSURE_SUCCESS(rv, rv); - rv = CallGetService(NS_EVENTQUEUESERVICE_CONTRACTID, &sEventQueueService); - NS_ENSURE_SUCCESS(rv, rv); - // Ignore failure and just don't load images rv = CallGetService("@mozilla.org/image/loader;1", &sImgLoader); if (NS_FAILED(rv)) { @@ -593,7 +588,6 @@ nsContentUtils::Shutdown() NS_IF_RELEASE(sIOService); NS_IF_RELEASE(sLineBreaker); NS_IF_RELEASE(sWordBreaker); - NS_IF_RELEASE(sEventQueueService); #ifdef MOZ_XTF NS_IF_RELEASE(sXTFService); #endif diff --git a/mozilla/content/base/src/nsDOMParser.cpp b/mozilla/content/base/src/nsDOMParser.cpp index d7da7c7b5fb..83dd6407ec7 100644 --- a/mozilla/content/base/src/nsDOMParser.cpp +++ b/mozilla/content/base/src/nsDOMParser.cpp @@ -62,11 +62,10 @@ #include "nsIDOMEventReceiver.h" #include "nsLoadListenerProxy.h" #include "nsStreamUtils.h" +#include "nsThreadUtils.h" #include "nsNetCID.h" #include "nsContentUtils.h" -static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - static const char* kLoadAsData = "loadAsData"; static NS_DEFINE_CID(kIDOMDOMImplementationCID, NS_DOM_IMPLEMENTATION_CID); @@ -118,7 +117,6 @@ nsDOMParser::Error(nsIDOMEvent* aEvent) nsDOMParser::nsDOMParser() : mLoopingForSyncLoad(PR_FALSE) { - mEventQService = do_GetService(kEventQueueServiceCID); } nsDOMParser::~nsDOMParser() @@ -320,19 +318,8 @@ nsDOMParser::ParseFromStream(nsIInputStream *stream, nsCOMPtr document(do_QueryInterface(domDocument)); if (!document) return NS_ERROR_FAILURE; - nsCOMPtr modalEventQueue; - - if(!mEventQService) { - return NS_ERROR_FAILURE; - } - mLoopingForSyncLoad = PR_TRUE; - rv = mEventQService->PushThreadEventQueue(getter_AddRefs(modalEventQueue)); - if (NS_FAILED(rv)) { - return rv; - } - // Have to pass PR_FALSE for reset here, else the reset will remove // our event listener. Should that listener addition move to later // than this call? @@ -347,9 +334,6 @@ nsDOMParser::ParseFromStream(nsIInputStream *stream, } if (NS_FAILED(rv) || !listener) { - if (modalEventQueue) { - mEventQService->PopThreadEventQueue(modalEventQueue); - } return NS_ERROR_FAILURE; } @@ -374,17 +358,17 @@ nsDOMParser::ParseFromStream(nsIInputStream *stream, // the channel, so we do not need to call Cancel(rv) as we do above. if (NS_FAILED(rv)) { - if (modalEventQueue) { - mEventQService->PopThreadEventQueue(modalEventQueue); - } return NS_ERROR_FAILURE; } - while (mLoopingForSyncLoad) { - modalEventQueue->ProcessPendingEvents(); - } + // Process events until we receive a load, abort, or error event for the + // document object. That event may have already fired. - mEventQService->PopThreadEventQueue(modalEventQueue); + nsIThread *thread = NS_GetCurrentThread(); + while (mLoopingForSyncLoad) { + if (!NS_ProcessNextEvent(thread)) + break; + } domDocument.swap(*aResult); diff --git a/mozilla/content/base/src/nsDOMParser.h b/mozilla/content/base/src/nsDOMParser.h index 4fc7059bd8a..6a88a8f853a 100644 --- a/mozilla/content/base/src/nsDOMParser.h +++ b/mozilla/content/base/src/nsDOMParser.h @@ -41,7 +41,6 @@ #include "nsIDOMParser.h" #include "nsCOMPtr.h" #include "nsIURI.h" -#include "nsIEventQueueService.h" #include "nsIDOMLoadListener.h" #include "nsWeakReference.h" @@ -70,7 +69,6 @@ public: private: nsCOMPtr mBaseURI; - nsCOMPtr mEventQService; PRBool mLoopingForSyncLoad; }; diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index 8ec87d5a202..2bed22e8e74 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -88,6 +88,7 @@ #include "nsIPresShell.h" #include "nsPresContext.h" #include "nsContentUtils.h" +#include "nsThreadUtils.h" #include "nsNodeInfoManager.h" #include "nsIXBLService.h" #include "nsIXPointer.h" @@ -132,9 +133,6 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID); #include "nsIDOMHTMLFormElement.h" #include "nsIRequest.h" #include "nsILink.h" -#include "plevent.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" #include "nsICharsetAlias.h" #include "nsIParser.h" @@ -5079,55 +5077,30 @@ nsDocument::UnblockOnload(PRBool aFireSync) } } +class nsUnblockOnloadEvent : public nsRunnable { +public: + nsUnblockOnloadEvent(nsDocument *doc) : mDoc(doc) {} + NS_IMETHOD Run() { + mDoc->DoUnblockOnload(); + return NS_OK; + } +private: + nsRefPtr mDoc; +}; + void nsDocument::PostUnblockOnloadEvent() { - nsCOMPtr eventQ; - nsContentUtils::EventQueueService()-> - GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs(eventQ)); - if (!eventQ) { - return; - } - - PLEvent* evt = new PLEvent(); - if (!evt) { - return; - } - - PL_InitEvent(evt, this, nsDocument::HandleOnloadBlockerEvent, - nsDocument::DestroyOnloadBlockerEvent); - - // After this point, event destruction will release |this| - NS_ADDREF_THIS(); - - nsresult rv = eventQ->PostEvent(evt); - if (NS_FAILED(rv)) { - PL_DestroyEvent(evt); - } else { + nsCOMPtr evt = new nsUnblockOnloadEvent(this); + nsresult rv = NS_DispatchToCurrentThread(evt); + if (NS_SUCCEEDED(rv)) { // Stabilize block count so we don't post more events while this one is up ++mOnloadBlockCount; + } else { + NS_WARNING("failed to dispatch nsUnblockOnloadEvent"); } } -// static -void* PR_CALLBACK -nsDocument::HandleOnloadBlockerEvent(PLEvent* aEvent) -{ - nsDocument* doc = NS_STATIC_CAST(nsDocument*, aEvent->owner); - doc->DoUnblockOnload(); - return nsnull; -} - -// static -void PR_CALLBACK -nsDocument::DestroyOnloadBlockerEvent(PLEvent* aEvent) -{ - nsDocument* doc = NS_STATIC_CAST(nsDocument*, aEvent->owner); - NS_RELEASE(doc); - delete aEvent; -} - void nsDocument::DoUnblockOnload() { diff --git a/mozilla/content/base/src/nsDocument.h b/mozilla/content/base/src/nsDocument.h index 6eb20280817..b036cc137be 100644 --- a/mozilla/content/base/src/nsDocument.h +++ b/mozilla/content/base/src/nsDocument.h @@ -114,6 +114,7 @@ class nsIRadioVisitor; class nsIFormControl; struct nsRadioGroupStruct; class nsOnloadBlocker; +class nsUnblockOnloadEvent; struct PLEvent; PR_BEGIN_EXTERN_C @@ -802,9 +803,9 @@ protected: nsString mBaseTarget; private: + friend class nsUnblockOnloadEvent; + void PostUnblockOnloadEvent(); - static EventHandlerFunc HandleOnloadBlockerEvent; - static EventDestructorFunc DestroyOnloadBlockerEvent; void DoUnblockOnload(); // These are not implemented and not supported. diff --git a/mozilla/content/base/src/nsImageLoadingContent.cpp b/mozilla/content/base/src/nsImageLoadingContent.cpp index 6b68a15cd93..4951a099320 100644 --- a/mozilla/content/base/src/nsImageLoadingContent.cpp +++ b/mozilla/content/base/src/nsImageLoadingContent.cpp @@ -56,9 +56,7 @@ #include "imgIContainer.h" #include "gfxIImageFrame.h" #include "imgILoader.h" -#include "plevent.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" +#include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsPresContext.h" @@ -715,10 +713,10 @@ nsImageLoadingContent::StringToURI(const nsAString& aSpec, /** - * Struct used to dispatch events + * Class used to dispatch events */ -class ImageEvent : public PLEvent +class ImageEvent : public nsRunnable { public: ImageEvent(nsPresContext* aPresContext, nsIContent* aContent, @@ -728,12 +726,13 @@ public: mMessage(aMessage), mDocument(aDocument) { - MOZ_COUNT_CTOR(ImageEvent); } ~ImageEvent() { - MOZ_COUNT_DTOR(ImageEvent); + mDocument->UnblockOnload(PR_TRUE); } + + NS_IMETHOD Run(); nsCOMPtr mPresContext; nsCOMPtr mContent; @@ -744,13 +743,12 @@ public: nsCOMPtr mDocument; }; -PR_STATIC_CALLBACK(void*) -HandleImagePLEvent(PLEvent* aEvent) +NS_IMETHODIMP +ImageEvent::Run() { - ImageEvent* evt = NS_STATIC_CAST(ImageEvent*, aEvent); PRUint32 eventMsg; - if (evt->mMessage.EqualsLiteral("load")) { + if (mMessage.EqualsLiteral("load")) { eventMsg = NS_IMAGE_LOAD; } else { eventMsg = NS_IMAGE_ERROR; @@ -758,18 +756,9 @@ HandleImagePLEvent(PLEvent* aEvent) nsEvent event(PR_TRUE, eventMsg); event.flags |= NS_EVENT_FLAG_CANT_BUBBLE; - nsEventDispatcher::Dispatch(evt->mContent, evt->mPresContext, &event); + nsEventDispatcher::Dispatch(mContent, mPresContext, &event); - return nsnull; -} - -PR_STATIC_CALLBACK(void) -DestroyImagePLEvent(PLEvent* aEvent) -{ - ImageEvent* evt = NS_STATIC_CAST(ImageEvent*, aEvent); - evt->mDocument->UnblockOnload(PR_TRUE); - - delete evt; + return NS_OK; } nsresult @@ -784,13 +773,9 @@ nsImageLoadingContent::FireEvent(const nsAString& aEventType) // no use to fire events if there is no document.... return NS_OK; } - nsCOMPtr eventQ; - // Use the UI thread event queue (though we should not be getting called from - // off the UI thread in any case....) - nsresult rv = nsContentUtils::EventQueueService()-> - GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs(eventQ)); - NS_ENSURE_TRUE(eventQ, rv); + + // We should not be getting called from off the UI thread... + NS_ASSERTION(NS_IsMainThread(), "should be on the main thread"); nsIPresShell *shell = document->GetShellAt(0); NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE); @@ -800,21 +785,13 @@ nsImageLoadingContent::FireEvent(const nsAString& aEventType) nsCOMPtr ourContent = do_QueryInterface(this); - ImageEvent* evt = new ImageEvent(presContext, ourContent, aEventType, document); - + nsCOMPtr evt = + new ImageEvent(presContext, ourContent, aEventType, document); NS_ENSURE_TRUE(evt, NS_ERROR_OUT_OF_MEMORY); - PL_InitEvent(evt, this, ::HandleImagePLEvent, ::DestroyImagePLEvent); - // Block onload for our event. Since we unblock in the event destructor, we // want to block now, even if posting will fail. document->BlockOnload(); - rv = eventQ->PostEvent(evt); - - if (NS_FAILED(rv)) { - PL_DestroyEvent(evt); - } - - return rv; + return NS_DispatchToCurrentThread(evt); } diff --git a/mozilla/content/base/src/nsObjectLoadingContent.cpp b/mozilla/content/base/src/nsObjectLoadingContent.cpp index 944bcc48afc..3f92b07c330 100644 --- a/mozilla/content/base/src/nsObjectLoadingContent.cpp +++ b/mozilla/content/base/src/nsObjectLoadingContent.cpp @@ -61,7 +61,6 @@ #include "nsIWebNavigationInfo.h" // Util headers -#include "plevent.h" #include "prlog.h" #include "nsAutoPtr.h" @@ -69,9 +68,9 @@ #include "nsContentPolicyUtils.h" #include "nsContentUtils.h" #include "nsDocShellCID.h" -#include "nsEventQueueUtils.h" #include "nsHTMLAtoms.h" #include "nsLayoutAtoms.h" +#include "nsThreadUtils.h" #include "nsNetUtil.h" // Concrete classes @@ -88,20 +87,11 @@ static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc"); #define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args) #define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG) -PR_BEGIN_EXTERN_C -/* Note that these typedefs declare functions, not pointer to - functions. That's the only way in which they differ from - PLHandleEventProc and PLDestroyEventProc. */ -typedef void* -(PR_CALLBACK EventHandlerFunc)(PLEvent* self); -typedef void -(PR_CALLBACK EventDestructorFunc)(PLEvent* self); -PR_END_EXTERN_C - -struct nsAsyncInstantiateEvent : public PLEvent { +class nsAsyncInstantiateEvent : public nsRunnable { +public: // This stores both the content and the frame so that Instantiate calls can be // avoided if the frame changed in the meantime. - // (the content is stored implicitly as the owner) + nsObjectLoadingContent *mContent; nsIObjectFrame* mFrame; nsCString mContentType; nsCOMPtr mURI; @@ -110,107 +100,81 @@ struct nsAsyncInstantiateEvent : public PLEvent { nsIObjectFrame* aFrame, const nsCString& aType, nsIURI* aURI) - : mFrame(aFrame), mContentType(aType), mURI(aURI) + : mContent(aContent), mFrame(aFrame), mContentType(aType), mURI(aURI) { - NS_ADDREF(NS_STATIC_CAST(nsIObjectLoadingContent*, aContent)); - PL_InitEvent(this, aContent, nsAsyncInstantiateEvent::HandleEvent, - nsAsyncInstantiateEvent::CleanupEvent); + NS_STATIC_CAST(nsIObjectLoadingContent *, mContent)->AddRef(); } ~nsAsyncInstantiateEvent() { - nsIObjectLoadingContent* con = NS_STATIC_CAST(nsIObjectLoadingContent*, - PL_GetEventOwner(this)); - NS_RELEASE(con); + NS_STATIC_CAST(nsIObjectLoadingContent *, mContent)->Release(); } - static EventHandlerFunc HandleEvent; - static EventDestructorFunc CleanupEvent; + NS_IMETHOD Run(); }; -/* static */ void* PR_CALLBACK -nsAsyncInstantiateEvent::HandleEvent(PLEvent* event) +NS_IMETHODIMP +nsAsyncInstantiateEvent::Run() { - nsAsyncInstantiateEvent* ev = NS_STATIC_CAST(nsAsyncInstantiateEvent*, - event); - nsObjectLoadingContent* con = NS_STATIC_CAST(nsObjectLoadingContent*, - PL_GetEventOwner(event)); + // Check if we've been "revoked" + if (mContent->mPendingInstantiateEvent != this) + return NS_OK; + mContent->mPendingInstantiateEvent = nsnull; + // Make sure that we still have the right frame (NOTE: we don't need to check // the type here - GetFrame() only returns object frames, and that means we're // a plugin) // Also make sure that we still refer to the same data. - if (con->GetFrame() == ev->mFrame && - con->mURI == ev->mURI && - con->mContentType.Equals(ev->mContentType)) { + if (mContent->GetFrame() == mFrame && + mContent->mURI == mURI && + mContent->mContentType.Equals(mContentType)) { if (LOG_ENABLED()) { nsCAutoString spec; - if (ev->mURI) { - ev->mURI->GetSpec(spec); + if (mURI) { + mURI->GetSpec(spec); } LOG(("OBJLC [%p]: Handling Instantiate event: Type=<%s> URI=%p<%s>\n", - con, ev->mContentType.get(), ev->mURI.get(), spec.get())); + mContent, mContentType.get(), mURI.get(), spec.get())); } - nsresult rv = con->Instantiate(ev->mContentType, ev->mURI); + nsresult rv = mContent->Instantiate(mContentType, mURI); if (NS_FAILED(rv)) { - con->Fallback(PR_TRUE); + mContent->Fallback(PR_TRUE); } } else { - LOG(("OBJLC [%p]: Discarding event, data changed\n", con)); + LOG(("OBJLC [%p]: Discarding event, data changed\n", mContent)); } - return nsnull; -} -/* static */ void PR_CALLBACK -nsAsyncInstantiateEvent::CleanupEvent(PLEvent* event) -{ - nsAsyncInstantiateEvent* ev = NS_STATIC_CAST(nsAsyncInstantiateEvent*, - event); - delete ev; + return NS_OK; } /** - * A PLEvent for firing PluginNotFound DOM Events. + * A task for firing PluginNotFound DOM Events. */ -struct nsPluginNotFoundEvent : public PLEvent { +class nsPluginNotFoundEvent : public nsRunnable { +public: + nsCOMPtr mContent; + nsPluginNotFoundEvent(nsIContent* aContent) - { - NS_ADDREF(aContent); - PL_InitEvent(this, aContent, nsPluginNotFoundEvent::HandleEvent, - nsPluginNotFoundEvent::CleanupEvent); - } + : mContent(aContent) + {} - ~nsPluginNotFoundEvent() - { - nsIContent* con = NS_STATIC_CAST(nsIContent*, PL_GetEventOwner(this)); - NS_RELEASE(con); - } + ~nsPluginNotFoundEvent() {} - static EventHandlerFunc HandleEvent; - static EventDestructorFunc CleanupEvent; + NS_IMETHOD Run(); }; -/* static */ void* PR_CALLBACK -nsPluginNotFoundEvent::HandleEvent(PLEvent* event) +NS_IMETHODIMP +nsPluginNotFoundEvent::Run() { - nsIContent* con = NS_STATIC_CAST(nsIContent*, PL_GetEventOwner(event)); - - LOG(("OBJLC []: Firing plugin not found event for content %p\n", con)); - nsContentUtils::DispatchTrustedEvent(con->GetDocument(), con, + LOG(("OBJLC []: Firing plugin not found event for content %p\n", + mContent.get())); + nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent, NS_LITERAL_STRING("PluginNotFound"), PR_TRUE, PR_TRUE); - return nsnull; + return NS_OK; } -/* static */ void PR_CALLBACK -nsPluginNotFoundEvent::CleanupEvent(PLEvent* event) -{ - nsPluginNotFoundEvent* ev = NS_STATIC_CAST(nsPluginNotFoundEvent*, - event); - delete ev; -} - - class AutoNotifier { public: AutoNotifier(nsObjectLoadingContent* aContent, PRBool aNotify) : @@ -548,11 +512,9 @@ nsObjectLoadingContent::EnsureInstantiation(nsIPluginInstance** aInstance) if (frame) { // If we have a frame, we may have pending instantiate events; revoke // them. - nsCOMPtr eventQ; - NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - if (eventQ) { - LOG(("OBJLC [%p]: Revoking events\n", this)); - eventQ->RevokeEvents(this); + if (mPendingInstantiateEvent) { + LOG(("OBJLC [%p]: Revoking pending instantiate event\n", this)); + mPendingInstantiateEvent = nsnull; } } else { // mInstantiating is true if we're in LoadObject; we shouldn't @@ -612,6 +574,9 @@ nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame) // This must be done asynchronously to ensure that the frame is correctly // initialized (has a view etc) + // "revoke" any existing instantiate event. + mPendingInstantiateEvent = nsnull; + // When in a plugin document, the document will take care of calling // instantiate nsCOMPtr pDoc (do_QueryInterface(GetOurDocument())); @@ -619,23 +584,20 @@ nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame) return NS_OK; } - nsCOMPtr eventQ; - NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - if (!eventQ) { - return NS_ERROR_UNEXPECTED; - } - - nsAsyncInstantiateEvent* ev = new nsAsyncInstantiateEvent(this, aFrame, - mContentType, - mURI); - if (!ev) { + nsCOMPtr event = + new nsAsyncInstantiateEvent(this, aFrame, mContentType, mURI); + if (!event) { return NS_ERROR_OUT_OF_MEMORY; } - LOG((" posting event\n")); - nsresult rv = eventQ->PostEvent(ev); + LOG((" dispatching event\n")); + nsresult rv = NS_DispatchToCurrentThread(event); if (NS_FAILED(rv)) { - PL_DestroyEvent(ev); + NS_ERROR("failed to dispatch nsAsyncInstantiateEvent"); + } else { + // Remember this event. This is a weak reference that will be cleared + // when the event runs. + mPendingInstantiateEvent = event; } } return NS_OK; @@ -765,13 +727,9 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI, } // Need to revoke any potentially pending instantiate events - if (mType == eType_Plugin) { - nsCOMPtr eventQ; - NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - if (eventQ) { - LOG(("OBJLC [%p]: Revoking events\n", this)); - eventQ->RevokeEvents(this); - } + if (mType == eType_Plugin && mPendingInstantiateEvent) { + LOG(("OBJLC [%p]: Revoking pending instantiate event\n", this)); + mPendingInstantiateEvent = nsnull; } AutoNotifier notifier(this, aNotify); @@ -1208,22 +1166,13 @@ nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType, /* static */ void nsObjectLoadingContent::FirePluginNotFound(nsIContent* thisContent) { - nsCOMPtr eventQ; - NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - if (!eventQ) { - return; - } - - nsPluginNotFoundEvent* ev = new nsPluginNotFoundEvent(thisContent); - if (!ev) { - return; - } - - LOG(("OBJLC []: Posting PluginNotFound event for content %p\n", + LOG(("OBJLC []: Dispatching PluginNotFound event for content %p\n", thisContent)); - nsresult rv = eventQ->PostEvent(ev); + + nsCOMPtr ev = new nsPluginNotFoundEvent(thisContent); + nsresult rv = NS_DispatchToCurrentThread(ev); if (NS_FAILED(rv)) { - PL_DestroyEvent(ev); + NS_WARNING("failed to dispatch nsPluginNotFoundEvent"); } } @@ -1236,8 +1185,8 @@ nsObjectLoadingContent::GetTypeOfContent(const nsCString& aMIMEType) return eType_Image; } - PRBool isSVG = aMIMEType.LowerCaseEqualsLiteral("image/svg+xml"); #ifdef MOZ_SVG + PRBool isSVG = aMIMEType.LowerCaseEqualsLiteral("image/svg+xml"); PRBool supportedSVG = isSVG && (caps & eSupportSVG); #else PRBool supportedSVG = PR_FALSE; diff --git a/mozilla/content/base/src/nsObjectLoadingContent.h b/mozilla/content/base/src/nsObjectLoadingContent.h index 5645e9faf33..a66838df920 100644 --- a/mozilla/content/base/src/nsObjectLoadingContent.h +++ b/mozilla/content/base/src/nsObjectLoadingContent.h @@ -50,6 +50,7 @@ #include "nsIInterfaceRequestor.h" #include "nsIChannelEventSink.h" #include "nsIObjectLoadingContent.h" +#include "nsIRunnable.h" #include "nsWeakReference.h" @@ -306,6 +307,11 @@ class nsObjectLoadingContent : public nsImageLoadingContent */ nsCOMPtr mFrameLoader; + /** + * A pending nsAsyncInstantiateEvent (may be null). This is a weak ref. + */ + nsIRunnable *mPendingInstantiateEvent; + /** * The content type of the resource we were last asked to load. */ diff --git a/mozilla/content/base/src/nsSyncLoadService.cpp b/mozilla/content/base/src/nsSyncLoadService.cpp index d0dc3242e61..32a31ee37f8 100644 --- a/mozilla/content/base/src/nsSyncLoadService.cpp +++ b/mozilla/content/base/src/nsSyncLoadService.cpp @@ -55,13 +55,13 @@ #include "nsIDOMElement.h" #include "nsIDOMDOMImplementation.h" #include "nsIDOMEventReceiver.h" -#include "nsIEventQueueService.h" #include "nsIJSContextStack.h" #include "nsIPrivateDOMImplementation.h" #include "nsIScriptGlobalObject.h" #include "nsIScriptSecurityManager.h" #include "nsContentCID.h" #include "nsContentUtils.h" +#include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsIHttpChannel.h" #include "nsIScriptLoader.h" @@ -311,42 +311,26 @@ nsSyncLoader::LoadDocument(nsIChannel* aChannel, nsresult nsSyncLoader::PushAsyncStream(nsIStreamListener* aListener) { - nsresult rv = NS_OK; - - // Set up a new eventqueue - nsCOMPtr service = - do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr currentThreadQ; - rv = service->PushThreadEventQueue(getter_AddRefs(currentThreadQ)); - NS_ENSURE_SUCCESS(rv, rv); - // Hook us up to listen to redirects and the like mChannel->SetNotificationCallbacks(this); // Start reading from the channel - rv = mChannel->AsyncOpen(aListener, nsnull); + nsresult rv = mChannel->AsyncOpen(aListener, nsnull); if (NS_SUCCEEDED(rv)) { - mLoading = PR_TRUE; - // process events until we're finished. - PLEvent *event; + mLoading = PR_TRUE; + nsIThread *thread = NS_GetCurrentThread(); while (mLoading && NS_SUCCEEDED(rv)) { - rv = currentThreadQ->WaitForEvent(&event); - NS_ASSERTION(NS_SUCCEEDED(rv), ": currentThreadQ->WaitForEvent failed...\n"); - if (NS_SUCCEEDED(rv)) { - rv = currentThreadQ->HandleEvent(event); - NS_ASSERTION(NS_SUCCEEDED(rv), ": currentThreadQ->HandleEvent failed...\n"); - } + PRBool processedEvent; + rv = thread->ProcessNextEvent(PR_TRUE, &processedEvent); + if (NS_SUCCEEDED(rv) && !processedEvent) + rv = NS_ERROR_UNEXPECTED; } } // Note that if AsyncOpen failed that's ok -- the only caller of // this method nulls out mChannel immediately after we return. - - service->PopThreadEventQueue(currentThreadQ); return rv; } diff --git a/mozilla/content/base/src/nsXMLHttpRequest.cpp b/mozilla/content/base/src/nsXMLHttpRequest.cpp index 916a77e371c..1dd20aa198a 100644 --- a/mozilla/content/base/src/nsXMLHttpRequest.cpp +++ b/mozilla/content/base/src/nsXMLHttpRequest.cpp @@ -50,6 +50,7 @@ #include "nsIURI.h" #include "nsILoadGroup.h" #include "nsNetUtil.h" +#include "nsThreadUtils.h" #include "nsIUploadChannel.h" #include "nsIDOMSerializer.h" #include "nsXPCOM.h" @@ -90,7 +91,6 @@ static const char* kLoadAsData = "loadAsData"; // CIDs static NS_DEFINE_CID(kIDOMDOMImplementationCID, NS_DOM_IMPLEMENTATION_CID); static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); // State #define XML_HTTP_REQUEST_UNINITIALIZED (1 << 0) // 0 @@ -1602,20 +1602,8 @@ nsXMLHttpRequest::Send(nsIVariant *aBody) // Reset responseXML mDocument = nsnull; - nsCOMPtr modalEventQueue; - if (!(mState & XML_HTTP_REQUEST_ASYNC)) { - if(!mEventQService) { - mEventQService = do_GetService(kEventQueueServiceCID, &rv); - NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); - } - mState |= XML_HTTP_REQUEST_SYNCLOOPING; - - rv = mEventQService->PushThreadEventQueue(getter_AddRefs(modalEventQueue)); - if (NS_FAILED(rv)) { - return rv; - } } if (!mScriptContext) { @@ -1665,10 +1653,6 @@ nsXMLHttpRequest::Send(nsIVariant *aBody) rv = mChannel->AsyncOpen(listener, nsnull); if (NS_FAILED(rv)) { - if (modalEventQueue) { - mEventQService->PopThreadEventQueue(modalEventQueue); - } - // Drop our ref to the channel to avoid cycles mChannel = nsnull; return rv; @@ -1676,22 +1660,20 @@ nsXMLHttpRequest::Send(nsIVariant *aBody) // If we're synchronous, spin an event loop here and wait if (!(mState & XML_HTTP_REQUEST_ASYNC)) { + nsIThread *thread = NS_GetCurrentThread(); while (mState & XML_HTTP_REQUEST_SYNCLOOPING) { - modalEventQueue->ProcessPendingEvents(); - - // Be sure not to busy wait! (see bug 273578) - if (mState & XML_HTTP_REQUEST_SYNCLOOPING) - PR_Sleep(PR_MillisecondsToInterval(10)); + if (!NS_ProcessNextEvent(thread)) { + rv = NS_ERROR_UNEXPECTED; + break; + } } - - mEventQService->PopThreadEventQueue(modalEventQueue); } if (!mChannel) { return NS_ERROR_FAILURE; } - return NS_OK; + return rv; } /* void setRequestHeader (in AUTF8String header, in AUTF8String value); */ diff --git a/mozilla/content/base/src/nsXMLHttpRequest.h b/mozilla/content/base/src/nsXMLHttpRequest.h index d993e14fcc2..5be5060dc65 100644 --- a/mozilla/content/base/src/nsXMLHttpRequest.h +++ b/mozilla/content/base/src/nsXMLHttpRequest.h @@ -49,7 +49,6 @@ #include "nsIHttpChannel.h" #include "nsIDocument.h" #include "nsIStreamListener.h" -#include "nsIEventQueueService.h" #include "nsWeakReference.h" #include "jsapi.h" #include "nsIScriptContext.h" @@ -171,7 +170,6 @@ protected: nsCOMPtr mOnReadystatechangeListener; nsCOMPtr mXMLParserStreamListener; - nsCOMPtr mEventQService; // used to implement getAllResponseHeaders() class nsHeaderVisitor : public nsIHttpHeaderVisitor { diff --git a/mozilla/content/events/public/nsPLDOMEvent.h b/mozilla/content/events/public/nsPLDOMEvent.h index ce4c58a348a..459886049c9 100644 --- a/mozilla/content/events/public/nsPLDOMEvent.h +++ b/mozilla/content/events/public/nsPLDOMEvent.h @@ -39,29 +39,32 @@ #define nsPLDOMEvent_h___ #include "nsCOMPtr.h" -#include "plevent.h" +#include "nsThreadUtils.h" #include "nsIDOMNode.h" #include "nsString.h" + /** * Use nsPLDOMEvent to fire a DOM event that requires safe a stable DOM. * For example, you may need to fire an event from within layout, but * want to ensure that the event handler doesn't mutate the DOM at * the wrong time, in order to avoid resulting instability. + * + * TODO: This should be renamed nsAsyncDOMEvent or something that does + * not include the substring "PL" that refers to the old PLEvent + * structure used with the old eventing system. See bug 334573. */ -struct nsPLDOMEvent : public PLEvent { +class nsPLDOMEvent : public nsRunnable { +public: nsPLDOMEvent (nsIDOMNode *aEventNode, const nsAString& aEventType) : mEventNode(aEventNode), mEventType(aEventType) { } - void HandleEvent(); + NS_IMETHOD Run(); nsresult PostDOMEvent(); nsCOMPtr mEventNode; nsString mEventType; }; -static void* PR_CALLBACK HandlePLDOMEvent(PLEvent* aEvent); -static void PR_CALLBACK DestroyPLDOMEvent(PLEvent* aEvent); - #endif diff --git a/mozilla/content/events/src/nsPLDOMEvent.cpp b/mozilla/content/events/src/nsPLDOMEvent.cpp index 2615c435aa3..1ecf0acf018 100644 --- a/mozilla/content/events/src/nsPLDOMEvent.cpp +++ b/mozilla/content/events/src/nsPLDOMEvent.cpp @@ -36,17 +36,16 @@ * ***** END LICENSE BLOCK ***** */ #include "nsPLDOMEvent.h" -#include "nsEventQueueUtils.h" #include "nsIDOMEvent.h" #include "nsIPrivateDOMEvent.h" #include "nsIDOMDocument.h" #include "nsIDOMDocumentEvent.h" #include "nsIDOMEventTarget.h" -void nsPLDOMEvent::HandleEvent() +NS_IMETHODIMP nsPLDOMEvent::Run() { if (!mEventNode) { - return; + return NS_OK; } nsCOMPtr domDoc; @@ -66,29 +65,11 @@ void nsPLDOMEvent::HandleEvent() target->DispatchEvent(domEvent, &defaultActionEnabled); } } + + return NS_OK; } nsresult nsPLDOMEvent::PostDOMEvent() { - nsCOMPtr eventQueue; - nsresult rv = NS_GetCurrentEventQ(getter_AddRefs(eventQueue)); - if (NS_SUCCEEDED(rv)) { - PL_InitEvent(this, nsnull, ::HandlePLDOMEvent, ::DestroyPLDOMEvent); - rv = eventQueue->PostEvent(this); - } - - return rv; -} - -static void* PR_CALLBACK HandlePLDOMEvent(PLEvent* aEvent) -{ - nsPLDOMEvent* event = NS_STATIC_CAST(nsPLDOMEvent*, aEvent); - event->HandleEvent(); - return nsnull; -} - -static void PR_CALLBACK DestroyPLDOMEvent(PLEvent* aEvent) -{ - nsPLDOMEvent* event = NS_STATIC_CAST(nsPLDOMEvent*, aEvent); - delete event; + return NS_DispatchToCurrentThread(this); } diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index 5050157bd21..c581277ab2f 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -58,6 +58,8 @@ #include "nsIMarkupDocumentViewer.h" #include "nsINodeInfo.h" #include "nsHTMLTokens.h" +#include "nsIAppShell.h" +#include "nsWidgetsCID.h" #include "nsCRT.h" #include "prtime.h" #include "prlog.h" @@ -118,7 +120,6 @@ #include "nsIPrompt.h" #include "nsLayoutCID.h" #include "nsIDocShellTreeItem.h" -#include "plevent.h" #include "nsEscape.h" #include "nsIElementObserver.h" @@ -127,6 +128,17 @@ //---------------------------------------------------------------------- +static void +FavorPerformanceHint(PRBool perfOverStarvation, PRUint32 starvationDelay) +{ + static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); + nsCOMPtr appShell = do_GetService(kAppShellCID); + if (appShell) + appShell->FavorPerformanceHint(perfOverStarvation, starvationDelay); +} + +//---------------------------------------------------------------------- + #ifdef NS_DEBUG static PRLogModuleInfo* gSinkLogModuleInfo; @@ -2312,7 +2324,7 @@ HTMLContentSink::DidBuildModel(void) if (mFlags & NS_SINK_FLAG_DYNAMIC_LOWER_VALUE) { // Reset the performance hint which was set to FALSE // when NS_SINK_FLAG_DYNAMIC_LOWER_VALUE was set. - PL_FavorPerformanceHint(PR_TRUE , 0); + FavorPerformanceHint(PR_TRUE , 0); } if (mFlags & NS_SINK_FLAG_CAN_INTERRUPT_PARSER) { @@ -3430,7 +3442,7 @@ HTMLContentSink::DidProcessAToken(void) // Set the performance hint to prevent event starvation when // dispatching PLEvents. This improves application responsiveness // during page loads. - PL_FavorPerformanceHint(PR_FALSE, 0); + FavorPerformanceHint(PR_FALSE, 0); } } else { @@ -3440,7 +3452,7 @@ HTMLContentSink::DidProcessAToken(void) // to favor overall page load speed over responsiveness. mFlags &= ~NS_SINK_FLAG_DYNAMIC_LOWER_VALUE; // Reset the hint that to favoring performance for PLEvent dispatch. - PL_FavorPerformanceHint(PR_TRUE, 0); + FavorPerformanceHint(PR_TRUE, 0); } } diff --git a/mozilla/content/xml/document/src/nsXMLDocument.cpp b/mozilla/content/xml/document/src/nsXMLDocument.cpp index 487ef528ca0..149c710be21 100644 --- a/mozilla/content/xml/document/src/nsXMLDocument.cpp +++ b/mozilla/content/xml/document/src/nsXMLDocument.cpp @@ -81,6 +81,7 @@ #include "nsMimeTypes.h" #include "nsIEventListenerManager.h" #include "nsContentUtils.h" +#include "nsThreadUtils.h" #include "nsJSUtils.h" #include "nsCRT.h" #include "nsIWindowWatcher.h" @@ -96,8 +97,6 @@ static const char kLoadAsData[] = "loadAsData"; -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - // ================================================================== // = @@ -217,8 +216,6 @@ nsXMLDocument::Init() nsresult rv = nsDocument::Init(); NS_ENSURE_SUCCESS(rv, rv); - mEventQService = do_GetService(kEventQueueServiceCID, &rv); - return rv; } @@ -499,17 +496,6 @@ nsXMLDocument::Load(const nsAString& aUrl, PRBool *aReturn) SetPrincipal(principal); - nsCOMPtr modalEventQueue; - - if(!mAsync) { - NS_ENSURE_TRUE(mEventQService, NS_ERROR_FAILURE); - - rv = mEventQService->PushThreadEventQueue(getter_AddRefs(modalEventQueue)); - if (NS_FAILED(rv)) { - return rv; - } - } - // Prepare for loading the XML document "into oneself" nsCOMPtr listener; if (NS_FAILED(rv = StartDocumentLoad(kLoadAsData, channel, @@ -517,9 +503,6 @@ nsXMLDocument::Load(const nsAString& aUrl, PRBool *aReturn) getter_AddRefs(listener), PR_FALSE))) { NS_ERROR("nsXMLDocument::Load: Failed to start the document load."); - if (modalEventQueue) { - mEventQService->PopThreadEventQueue(modalEventQueue); - } return rv; } @@ -530,21 +513,18 @@ nsXMLDocument::Load(const nsAString& aUrl, PRBool *aReturn) rv = channel->AsyncOpen(listener, nsnull); if (NS_FAILED(rv)) { mChannelIsPending = PR_FALSE; - if (modalEventQueue) { - mEventQService->PopThreadEventQueue(modalEventQueue); - } return rv; } if (!mAsync) { + nsCOMPtr thread = do_GetCurrentThread(); + mLoopingForSyncLoad = PR_TRUE; - while (mLoopingForSyncLoad) { - modalEventQueue->ProcessPendingEvents(); + if (!NS_ProcessNextEvent(thread)) + break; } - mEventQService->PopThreadEventQueue(modalEventQueue); - // We set return to true unless there was a parsing error nsCOMPtr node = do_QueryInterface(mRootContent); if (node) { diff --git a/mozilla/content/xml/document/src/nsXMLDocument.h b/mozilla/content/xml/document/src/nsXMLDocument.h index 183b792cd8d..5afd9ab3b05 100644 --- a/mozilla/content/xml/document/src/nsXMLDocument.h +++ b/mozilla/content/xml/document/src/nsXMLDocument.h @@ -46,7 +46,6 @@ #include "nsIScriptContext.h" #include "nsHTMLStyleSheet.h" #include "nsIHTMLCSSStyleSheet.h" -#include "nsIEventQueueService.h" class nsIParser; class nsIDOMNode; @@ -98,8 +97,6 @@ public: protected: virtual nsresult GetLoadGroup(nsILoadGroup **aLoadGroup); - nsCOMPtr mEventQService; - nsCOMPtr mScriptContext; // mChannelIsPending indicates whether we're currently asynchronously loading diff --git a/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp b/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp index 9fda936e627..34db1e314e0 100644 --- a/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp +++ b/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp @@ -63,8 +63,8 @@ #include "txUnknownHandler.h" #include "txXSLTProcessor.h" #include "nsIPrincipal.h" +#include "nsThreadUtils.h" #include "jsapi.h" -#include "nsIEventQueueService.h" static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID); @@ -364,30 +364,27 @@ txMozillaXSLTProcessor::SetSourceContentModel(nsIDOMNode* aSourceDOM) return NS_OK; } -PR_BEGIN_EXTERN_C -void* PR_CALLBACK -HandleTransformBlockerEvent(PLEvent *aEvent) -{ - txMozillaXSLTProcessor *processor = - NS_STATIC_CAST(txMozillaXSLTProcessor*, aEvent->owner); - processor->TransformToDoc(nsnull, nsnull); +class nsTransformBlockerEvent : public nsRunnable { +public: + nsRefPtr mProcessor; - return nsnull; -} + nsTransformBlockerEvent(txMozillaXSLTProcessor *processor) + : mProcessor(processor) + {} -void PR_CALLBACK -DestroyTransformBlockerEvent(PLEvent *aEvent) -{ - txMozillaXSLTProcessor *processor = - NS_STATIC_CAST(txMozillaXSLTProcessor*, aEvent->owner); + ~nsTransformBlockerEvent() + { nsCOMPtr document = - do_QueryInterface(processor->GetSourceContentModel()); + do_QueryInterface(mProcessor->GetSourceContentModel()); document->UnblockOnload(PR_TRUE); + } - NS_RELEASE(processor); - delete aEvent; -} -PR_END_EXTERN_C + NS_IMETHOD Run() + { + mProcessor->TransformToDoc(nsnull, nsnull); + return NS_OK; + } +}; nsresult txMozillaXSLTProcessor::DoTransform() @@ -395,39 +392,24 @@ txMozillaXSLTProcessor::DoTransform() NS_ENSURE_TRUE(mSource, NS_ERROR_UNEXPECTED); NS_ENSURE_TRUE(mStylesheet, NS_ERROR_UNEXPECTED); NS_ASSERTION(mObserver, "no observer"); + NS_ASSERTION(NS_IsMainThread(), "should only be on main thread"); nsresult rv; nsCOMPtr document = do_QueryInterface(mSource, &rv); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr service = - do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr eventQ; - rv = service->GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs(eventQ)); - NS_ENSURE_SUCCESS(rv, rv); - - PLEvent* event = new PLEvent(); + nsCOMPtr event = new nsTransformBlockerEvent(this); if (!event) { return NS_ERROR_OUT_OF_MEMORY; } - PL_InitEvent(event, this, HandleTransformBlockerEvent, - DestroyTransformBlockerEvent); - document->BlockOnload(); - // After this point, event destruction will release |this| (in - // DestroyTransformBlockerEvent) - NS_ADDREF_THIS(); - - rv = eventQ->PostEvent(event); + rv = NS_DispatchToCurrentThread(event); if (NS_FAILED(rv)) { // XXX Maybe we should just display the source document in this case? // Also, set up context information, see bug 204655. reportError(rv, nsnull, nsnull); - PL_DestroyEvent(event); } return rv; diff --git a/mozilla/directory/xpcom/base/src/nsLDAPConnection.cpp b/mozilla/directory/xpcom/base/src/nsLDAPConnection.cpp index 9f7ebbbd1a6..d99579b9678 100644 --- a/mozilla/directory/xpcom/base/src/nsLDAPConnection.cpp +++ b/mozilla/directory/xpcom/base/src/nsLDAPConnection.cpp @@ -49,13 +49,12 @@ #include "nsIComponentManager.h" #include "nsLDAPConnection.h" #include "nsLDAPMessage.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsIConsoleService.h" #include "nsIDNSService.h" #include "nsIDNSRecord.h" #include "nsIRequestObserver.h" #include "nsIProxyObjectManager.h" -#include "nsEventQueueUtils.h" #include "nsNetError.h" #include "nsLDAPOperation.h" #include "nsILDAPErrors.h" @@ -194,11 +193,10 @@ nsLDAPConnection::Init(const char *aHost, PRInt32 aPort, PRBool aSSL, return NS_ERROR_FAILURE; } - nsCOMPtr curEventQ; - rv = NS_GetCurrentEventQ(getter_AddRefs(curEventQ)); - if (NS_FAILED(rv)) { + nsCOMPtr curThread = do_GetCurrentThread(); + if (!curThread) { NS_ERROR("nsLDAPConnection::Init(): couldn't " - "get current event queue"); + "get current thread"); return NS_ERROR_FAILURE; } // Do the pre-resolve of the hostname, using the DNS service. This @@ -230,7 +228,7 @@ nsLDAPConnection::Init(const char *aHost, PRInt32 aPort, PRBool aSSL, if (spacePos != kNotFound) mDNSHost.Truncate(spacePos); - rv = pDNSService->AsyncResolve(mDNSHost, 0, this, curEventQ, + rv = pDNSService->AsyncResolve(mDNSHost, 0, this, curThread, getter_AddRefs(mDNSRequest)); if (NS_FAILED(rv)) { @@ -1023,13 +1021,13 @@ nsLDAPConnection::OnLookupComplete(nsICancelable *aRequest, mRunnable->mWeakConn = do_GetWeakReference(conn); // kick off a thread for result listening and marshalling - // XXXdmose - should this be JOINABLE? // - rv = NS_NewThread(getter_AddRefs(mThread), mRunnable, 0, - PR_UNJOINABLE_THREAD); + rv = NS_NewThread(getter_AddRefs(mThread), mRunnable); if (NS_FAILED(rv)) { rv = NS_ERROR_NOT_AVAILABLE; } + // XXX(darin): We need to shutdown this thread at some point. + // Otherwise, it will stick around until shutdown. } } diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 40989aa25bf..e4602e5f606 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -93,6 +93,8 @@ #include "nsIPrefBranch.h" #include "nsIPrefBranch2.h" #include "nsIWritablePropertyBag2.h" +#include "nsIAppShell.h" +#include "nsWidgetsCID.h" // we want to explore making the document own the load group // so we can associate the document URI with the load group. @@ -175,15 +177,13 @@ static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID); static NS_DEFINE_CID(kDocumentCharsetInfoCID, NS_DOCUMENTCHARSETINFO_CID); static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID); +static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); #if defined(DEBUG_bryner) || defined(DEBUG_chb) //#define DEBUG_DOCSHELL_FOCUS #define DEBUG_PAGE_CACHE #endif -#include "plevent.h" -#include "nsGUIEvent.h" -#include "nsEventQueueUtils.h" #include "nsContentErrors.h" // Number of documents currently loading @@ -200,7 +200,7 @@ nsIURIFixup *nsDocShell::sURIFixup = 0; // the pref on the creation of the first docshell. static PRBool gValidateOrigin = (PRBool)0xffffffff; -// Hint for native dispatch of plevents on how long to delay after +// Hint for native dispatch of events on how long to delay after // all documents have loaded in milliseconds before favoring normal // native event dispatch priorites over performance #define NS_EVENT_STARVATION_DELAY_HINT 2000 @@ -218,6 +218,14 @@ static PRLogModuleInfo* gDocShellLog; static PRLogModuleInfo* gDocShellLeakLog; #endif +static void +FavorPerformanceHint(PRBool perfOverStarvation, PRUint32 starvationDelay) +{ + nsCOMPtr appShell = do_GetService(kAppShellCID); + if (appShell) + appShell->FavorPerformanceHint(perfOverStarvation, starvationDelay); +} + //***************************************************************************** //*** nsDocShellFocusController //***************************************************************************** @@ -3197,11 +3205,8 @@ NS_IMETHODIMP nsDocShell::Stop(PRUint32 aStopFlags) { if (nsIWebNavigation::STOP_CONTENT & aStopFlags) { - // Revoke any pending plevents related to content viewer restoration - nsCOMPtr uiThreadQueue; - NS_GetMainEventQ(getter_AddRefs(uiThreadQueue)); - if (uiThreadQueue) - uiThreadQueue->RevokeEvents(this); + // Revoke any pending event related to content viewer restoration + mRestorePresentationEvent.Revoke(); // Stop the document loading if (mContentViewer) @@ -4778,7 +4783,7 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress, // over performance if (--gNumberOfDocumentsLoading == 0) { // Hint to use normal native event dispatch priorities - PL_FavorPerformanceHint(PR_FALSE, NS_EVENT_STARVATION_DELAY_HINT); + FavorPerformanceHint(PR_FALSE, NS_EVENT_STARVATION_DELAY_HINT); } } /* Check if the httpChannel has any cache-control related response headers, @@ -5066,39 +5071,12 @@ nsDocShell::CaptureState() return NS_OK; } -class RestorePresentationEvent : public PLEvent +NS_IMETHODIMP +nsDocShell::RestorePresentationEvent::Run() { -public: - RestorePresentationEvent(nsDocShell *aShell); - - nsRefPtr mDocShell; -}; - -PR_STATIC_CALLBACK(void*) -HandleRestorePresentationEvent(PLEvent *aEvent) -{ - RestorePresentationEvent *event = - NS_STATIC_CAST(RestorePresentationEvent*, aEvent); - -#ifdef NS_DEBUG - nsresult rv = -#endif - event->mDocShell->RestoreFromHistory(); - NS_ASSERTION(NS_SUCCEEDED(rv), "RestoreFromHistory failed"); - return nsnull; -} - -PR_STATIC_CALLBACK(void) -DestroyRestorePresentationEvent(PLEvent *aEvent) -{ - delete NS_STATIC_CAST(RestorePresentationEvent*, aEvent); -} - -RestorePresentationEvent::RestorePresentationEvent(nsDocShell *aShell) - : mDocShell(aShell) -{ - PL_InitEvent(this, mDocShell, ::HandleRestorePresentationEvent, - ::DestroyRestorePresentationEvent); + if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())) + NS_WARNING("RestoreFromHistory failed"); + return NS_OK; } NS_IMETHODIMP @@ -5258,32 +5236,32 @@ nsDocShell::RestorePresentation(nsISHEntry *aSHEntry, PRBool *aRestoring) BeginRestore(viewer, PR_TRUE); - // Post a PLEvent that will remove the request after we've returned + // Post an event that will remove the request after we've returned // to the event loop. This mimics the way it is called by nsIChannel // implementations. - nsCOMPtr uiThreadQueue; - NS_GetMainEventQ(getter_AddRefs(uiThreadQueue)); - NS_ENSURE_TRUE(uiThreadQueue, NS_ERROR_UNEXPECTED); + // Revoke any pending restore (just in case) + NS_ASSERTION(!mRestorePresentationEvent.IsPending(), + "should only have one RestorePresentationEvent"); + mRestorePresentationEvent.Revoke(); - PLEvent *evt = new RestorePresentationEvent(this); - NS_ENSURE_TRUE(evt, NS_ERROR_OUT_OF_MEMORY); - - nsresult rv = uiThreadQueue->PostEvent(evt); + nsRefPtr evt = new RestorePresentationEvent(this); + nsresult rv = NS_DispatchToCurrentThread(evt); if (NS_SUCCEEDED(rv)) { - // The rest of the restore processing will happen on our PLEvent + mRestorePresentationEvent = evt.get(); + // The rest of the restore processing will happen on our event // callback. *aRestoring = PR_TRUE; - } else { - PL_DestroyEvent(evt); } - return NS_OK; + return rv; } nsresult nsDocShell::RestoreFromHistory() { + mRestorePresentationEvent.Forget(); + // This section of code follows the same ordering as CreateContentViewer. if (!mLSHE) return NS_ERROR_FAILURE; @@ -5487,7 +5465,7 @@ nsDocShell::RestoreFromHistory() // Tell the event loop to favor plevents over user events, see comments // in CreateContentViewer. if (++gNumberOfDocumentsLoading == 1) - PL_FavorPerformanceHint(PR_TRUE, NS_EVENT_STARVATION_DELAY_HINT); + FavorPerformanceHint(PR_TRUE, NS_EVENT_STARVATION_DELAY_HINT); if (oldMUDV && newMUDV) @@ -5730,7 +5708,7 @@ nsDocShell::CreateContentViewer(const char *aContentType, // Hint to favor performance for the plevent notification mechanism. // We want the pages to load as fast as possible even if its means // native messages might be starved. - PL_FavorPerformanceHint(PR_TRUE, NS_EVENT_STARVATION_DELAY_HINT); + FavorPerformanceHint(PR_TRUE, NS_EVENT_STARVATION_DELAY_HINT); } if (onLocationChangeNeeded) { diff --git a/mozilla/docshell/base/nsDocShell.h b/mozilla/docshell/base/nsDocShell.h index 0fe918d010a..d6bc1e6a5a8 100644 --- a/mozilla/docshell/base/nsDocShell.h +++ b/mozilla/docshell/base/nsDocShell.h @@ -72,6 +72,7 @@ #include "nsPoint.h" // mCurrent/mDefaultScrollbarPreferences #include "nsString.h" #include "nsAutoPtr.h" +#include "nsThreadUtils.h" // Threshold value in ms for META refresh based redirects #define REFRESH_REDIRECT_TIMER 15000 @@ -469,6 +470,16 @@ protected: // Override the parent setter from nsDocLoader virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader); + // Event type dispatched by RestorePresentation + class RestorePresentationEvent : public nsRunnable { + public: + NS_DECL_NSIRUNNABLE + RestorePresentationEvent(nsDocShell *ds) : mDocShell(ds) {} + void Revoke() { mDocShell = nsnull; } + private: + nsDocShell *mDocShell; + }; + PRPackedBool mAllowSubframes; PRPackedBool mAllowPlugins; PRPackedBool mAllowJavascript; @@ -546,6 +557,11 @@ protected: // Somebody give me better name nsCOMPtr mLSHE; + // Holds a weak pointer to a RestorePresentationEvent object if any that + // holds a weak pointer back to us. We use this pointer to possibly revoke + // the event whenever necessary. + nsRevocableEventPtr mRestorePresentationEvent; + // Index into the SHTransaction list, indicating the previous and current // transaction at the time that this DocShell begins to load PRInt32 mPreviousTransIndex; diff --git a/mozilla/docshell/base/nsWebShell.cpp b/mozilla/docshell/base/nsWebShell.cpp index c2e9519ffad..1c4c477d2e5 100644 --- a/mozilla/docshell/base/nsWebShell.cpp +++ b/mozilla/docshell/base/nsWebShell.cpp @@ -56,12 +56,10 @@ #include "nsIDOMEvent.h" #include "nsPresContext.h" #include "nsIComponentManager.h" -#include "nsIEventQueueService.h" #include "nsCRT.h" #include "nsVoidArray.h" #include "nsString.h" #include "nsReadableUtils.h" -#include "plevent.h" #include "prprf.h" #include "nsIPluginHost.h" #include "nsplugin.h" @@ -105,6 +103,7 @@ #include "nsIUploadChannel.h" #include "nsISeekableStream.h" #include "nsStreamUtils.h" +#include "nsThreadUtils.h" #include "nsILocaleService.h" #include "nsIStringBundle.h" @@ -404,10 +403,9 @@ nsWebShell::nsWebShell() : nsDocShell() ++gNumberOfWebShells; #endif #ifdef DEBUG - printf("++WEBSHELL %p == %ld\n", this, gNumberOfWebShells); + printf("++WEBSHELL %p == %ld\n", (void*) this, gNumberOfWebShells); #endif - mThread = nsnull; InitFrameData(); mItemType = typeContent; mCharsetReloadState = eCharsetReloadInit; @@ -430,7 +428,7 @@ nsWebShell::~nsWebShell() --gNumberOfWebShells; #endif #ifdef DEBUG - printf("--WEBSHELL %p == %ld\n", this, gNumberOfWebShells); + printf("--WEBSHELL %p == %ld\n", (void*) this, gNumberOfWebShells); #endif } @@ -565,14 +563,15 @@ nsWebShell::SetRendering(PRBool aRender) // WebShell link handling -struct OnLinkClickEvent : public PLEvent { +class OnLinkClickEvent : public nsRunnable { +public: OnLinkClickEvent(nsWebShell* aHandler, nsIContent* aContent, nsLinkVerb aVerb, nsIURI* aURI, - const PRUnichar* aTargetSpec, nsIInputStream* aPostDataStream = 0, + const PRUnichar* aTargetSpec, + nsIInputStream* aPostDataStream = 0, nsIInputStream* aHeadersDataStream = 0); - ~OnLinkClickEvent(); - void HandleEvent() { + NS_IMETHOD Run() { nsCOMPtr window(do_QueryInterface(mHandler->mScriptGlobal)); nsAutoPopupStatePusher popupStatePusher(window, mPopupState); @@ -580,9 +579,11 @@ struct OnLinkClickEvent : public PLEvent { mTargetSpec.get(), mPostDataStream, mHeadersDataStream, nsnull, nsnull); + return NS_OK; } - nsWebShell* mHandler; +private: + nsRefPtr mHandler; nsCOMPtr mURI; nsString mTargetSpec; nsCOMPtr mPostDataStream; @@ -592,19 +593,6 @@ struct OnLinkClickEvent : public PLEvent { PopupControlState mPopupState; }; -static void* PR_CALLBACK HandlePLEvent(PLEvent* aEvent) -{ - OnLinkClickEvent* event = NS_STATIC_CAST(OnLinkClickEvent*, aEvent); - event->HandleEvent(); - return nsnull; -} - -static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent) -{ - OnLinkClickEvent* event = NS_STATIC_CAST(OnLinkClickEvent*, aEvent); - delete event; -} - OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler, nsIContent *aContent, nsLinkVerb aVerb, @@ -612,32 +600,17 @@ OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler, const PRUnichar* aTargetSpec, nsIInputStream* aPostDataStream, nsIInputStream* aHeadersDataStream) + : mHandler(aHandler) + , mURI(aURI) + , mTargetSpec(aTargetSpec) + , mPostDataStream(aPostDataStream) + , mHeadersDataStream(aHeadersDataStream) + , mContent(aContent) + , mVerb(aVerb) { - mHandler = aHandler; - NS_ADDREF(aHandler); - mURI = aURI; - mTargetSpec.Assign(aTargetSpec); - mPostDataStream = aPostDataStream; - mHeadersDataStream = aHeadersDataStream; - mContent = aContent; - mVerb = aVerb; - nsCOMPtr window(do_QueryInterface(mHandler->mScriptGlobal)); mPopupState = window->GetPopupControlState(); - - PL_InitEvent(this, nsnull, ::HandlePLEvent, ::DestroyPLEvent); - - nsCOMPtr eventQueue; - aHandler->GetEventQueue(getter_AddRefs(eventQueue)); - NS_ASSERTION(eventQueue, "no event queue"); - if (eventQueue) - eventQueue->PostEvent(this); -} - -OnLinkClickEvent::~OnLinkClickEvent() -{ - NS_IF_RELEASE(mHandler); } //---------------------------------------- @@ -650,26 +623,11 @@ nsWebShell::OnLinkClick(nsIContent* aContent, nsIInputStream* aPostDataStream, nsIInputStream* aHeadersDataStream) { - OnLinkClickEvent* ev; - - ev = new OnLinkClickEvent(this, aContent, aVerb, aURI, - aTargetSpec, aPostDataStream, aHeadersDataStream); - if (!ev) { - return NS_ERROR_OUT_OF_MEMORY; - } - return NS_OK; -} - -nsresult -nsWebShell::GetEventQueue(nsIEventQueue **aQueue) -{ - NS_ENSURE_ARG_POINTER(aQueue); - *aQueue = 0; - - nsCOMPtr eventService(do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID)); - if (eventService) - eventService->GetThreadEventQueue(mThread, aQueue); - return *aQueue ? NS_OK : NS_ERROR_FAILURE; + NS_ASSERTION(NS_IsMainThread(), "wrong thread"); + nsCOMPtr ev = + new OnLinkClickEvent(this, aContent, aVerb, aURI, aTargetSpec, + aPostDataStream, aHeadersDataStream); + return NS_DispatchToCurrentThread(ev); } NS_IMETHODIMP @@ -1386,14 +1344,6 @@ NS_IMETHODIMP nsWebShell::Create() return NS_OK; } - // Remember the current thread (in current and forseeable implementations, - // it'll just be the unique UI thread) - // - // Since this call must be made on the UI thread, we know the Event Queue - // will be associated with the current thread... - // - mThread = PR_GetCurrentThread(); - WEB_TRACE(WEB_TRACE_CALLS, ("nsWebShell::Init: this=%p", this)); diff --git a/mozilla/docshell/base/nsWebShell.h b/mozilla/docshell/base/nsWebShell.h index ab07eced579..97a98397880 100644 --- a/mozilla/docshell/base/nsWebShell.h +++ b/mozilla/docshell/base/nsWebShell.h @@ -47,7 +47,6 @@ #include "nsIIOService.h" #include "nsCRT.h" -class nsIEventQueue; class nsIController; struct PRThread; struct OnLinkClickEvent; @@ -103,9 +102,6 @@ public: NS_IMETHOD Create(); - // nsWebShell - nsresult GetEventQueue(nsIEventQueue **aQueue); - static nsEventStatus PR_CALLBACK HandleEvent(nsGUIEvent *aEvent); // NS_IMETHOD SetURL(const PRUnichar* aURL); @@ -129,8 +125,6 @@ protected: nsIChannel* channel, nsresult aStatus); - PRThread *mThread; - eCharsetReloadState mCharsetReloadState; nsresult CreateViewer(nsIRequest* request, diff --git a/mozilla/docshell/shistory/src/nsSHEntry.cpp b/mozilla/docshell/shistory/src/nsSHEntry.cpp index 5704ff1762a..96149286d0b 100644 --- a/mozilla/docshell/shistory/src/nsSHEntry.cpp +++ b/mozilla/docshell/shistory/src/nsSHEntry.cpp @@ -49,10 +49,8 @@ #include "nsIDocShellTreeItem.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" -#include "plevent.h" #include "nsAutoPtr.h" -#include "nsIEventQueue.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" static PRUint32 gEntryID = 0; @@ -685,63 +683,39 @@ nsSHEntry::ContentRemoved(nsIDocument* aDocument, DocumentMutated(); } -class DestroyViewerEvent : public PLEvent +class DestroyViewerEvent : public nsRunnable { public: - DestroyViewerEvent(nsIContentViewer* aViewer, nsIDocument* aDocument); + DestroyViewerEvent(nsIContentViewer* aViewer, nsIDocument* aDocument) + : mViewer(aViewer), + mDocument(aDocument) + {} + + NS_IMETHOD Run() + { + if (mViewer) + mViewer->Destroy(); + return NS_OK; + } nsCOMPtr mViewer; nsCOMPtr mDocument; }; -PR_STATIC_CALLBACK(void*) -HandleDestroyViewerEvent(PLEvent *aEvent) -{ - nsIContentViewer* viewer = NS_STATIC_CAST(DestroyViewerEvent*, aEvent)->mViewer; - if (viewer) { - viewer->Destroy(); - } - - return nsnull; -} - -PR_STATIC_CALLBACK(void) -DestroyDestroyViewerEvent(PLEvent *aEvent) -{ - delete NS_STATIC_CAST(DestroyViewerEvent*, aEvent); -} - -DestroyViewerEvent::DestroyViewerEvent(nsIContentViewer* aViewer, - nsIDocument* aDocument) - : mViewer(aViewer), - mDocument(aDocument) -{ - PL_InitEvent(this, mViewer, ::HandleDestroyViewerEvent, - ::DestroyDestroyViewerEvent); -} - void nsSHEntry::DocumentMutated() { NS_ASSERTION(mContentViewer && mDocument, "we shouldn't still be observing the doc"); - // Release the reference to the contentviewer asynconously so that the + // Release the reference to the contentviewer asynchronously so that the // document doesn't get nuked mid-mutation. - nsCOMPtr uiThreadQueue; - NS_GetMainEventQ(getter_AddRefs(uiThreadQueue)); - if (!uiThreadQueue) { - return; - } - PLEvent *evt = new DestroyViewerEvent(mContentViewer, mDocument); - if (!evt) { - return; - } - - nsresult rv = uiThreadQueue->PostEvent(evt); + nsCOMPtr evt = + new DestroyViewerEvent(mContentViewer, mDocument); + nsresult rv = NS_DispatchToCurrentThread(evt); if (NS_FAILED(rv)) { - PL_DestroyEvent(evt); + NS_WARNING("failed to dispatch DestroyViewerEvent"); } else { // Drop presentation. Also ensures that we don't post more then one diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index c9c2e98c332..ee9d4723c1e 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -96,7 +96,7 @@ #include "nsIDOMPkcs11.h" #include "nsDOMString.h" #include "nsIEmbeddingSiteWindow2.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsIEventStateManager.h" #include "nsIHttpProtocolHandler.h" #include "nsIJSContextStack.h" @@ -282,7 +282,6 @@ PRInt32 gTimeoutCnt = 0; PR_END_MACRO // CIDs -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); #ifdef OJI static NS_DEFINE_CID(kJVMServiceCID, NS_JVMMANAGER_CID); #endif @@ -4227,51 +4226,22 @@ nsGlobalWindow::GetFrames(nsIDOMWindow** aFrames) return NS_OK; } -struct nsCloseEvent : public PLEvent { +class nsCloseEvent : public nsRunnable { +public: nsCloseEvent (nsGlobalWindow *aWindow) : mWindow(aWindow) { } - void HandleEvent() { + NS_IMETHOD Run() { if (mWindow) mWindow->ReallyCloseWindow(); + return NS_OK; } - nsresult PostCloseEvent(); - nsRefPtr mWindow; }; -static void* PR_CALLBACK HandleCloseEvent(PLEvent* aEvent) -{ - nsCloseEvent *event = NS_STATIC_CAST(nsCloseEvent*, aEvent); - event->HandleEvent(); - return nsnull; -} -static void PR_CALLBACK DestroyCloseEvent(PLEvent* aEvent) -{ - nsCloseEvent *event = NS_STATIC_CAST(nsCloseEvent*, aEvent); - delete event; -} - -nsresult -nsCloseEvent::PostCloseEvent() -{ - nsCOMPtr eventService(do_GetService(kEventQueueServiceCID)); - if (eventService) { - nsCOMPtr eventQueue; - eventService->GetThreadEventQueue(PR_GetCurrentThread(), getter_AddRefs(eventQueue)); - if (eventQueue) { - - PL_InitEvent(this, nsnull, ::HandleCloseEvent, ::DestroyCloseEvent); - return eventQueue->PostEvent(this); - } - } - - return NS_ERROR_FAILURE; -} - NS_IMETHODIMP nsGlobalWindow::Close() { @@ -4388,15 +4358,8 @@ nsGlobalWindow::Close() // to really close the window. rv = NS_ERROR_FAILURE; if (!nsContentUtils::IsCallerChrome()) { - nsCloseEvent *ev = new nsCloseEvent(this); - - if (ev) { - rv = ev->PostCloseEvent(); - - if (NS_FAILED(rv)) { - PL_DestroyEvent(ev); - } - } else rv = NS_ERROR_OUT_OF_MEMORY; + nsCOMPtr ev = new nsCloseEvent(this); + rv = NS_DispatchToCurrentThread(ev); } if (NS_FAILED(rv)) { diff --git a/mozilla/dom/src/base/nsJSEnvironment.cpp b/mozilla/dom/src/base/nsJSEnvironment.cpp index 5d569d097bf..9f423cefe38 100644 --- a/mozilla/dom/src/base/nsJSEnvironment.cpp +++ b/mozilla/dom/src/base/nsJSEnvironment.cpp @@ -72,7 +72,7 @@ #include "nsIObserverService.h" #include "nsGUIEvent.h" #include "nsScriptNameSpaceManager.h" -#include "nsIThread.h" +#include "nsThreadUtils.h" #include "nsITimer.h" #include "nsDOMClassInfo.h" #include "nsIAtom.h" @@ -143,8 +143,6 @@ static const char kJSRuntimeServiceContractID[] = static const char kDOMStringBundleURL[] = "chrome://global/locale/dom/dom.properties"; -static PRThread *gDOMThread; - static JSGCCallback gOldJSGCCallback; static PRBool sIsInitialized; @@ -2207,7 +2205,7 @@ DOMGCCallback(JSContext *cx, JSGCStatus status) { JSBool result = gOldJSGCCallback ? gOldJSGCCallback(cx, status) : JS_TRUE; - if (status == JSGC_BEGIN && PR_GetCurrentThread() != gDOMThread) + if (status == JSGC_BEGIN && !NS_IsMainThread()) return JS_FALSE; // XPCJSRuntime::GCCallback does marking from the JSGC_MARK_END callback. @@ -2231,7 +2229,6 @@ nsJSEnvironment::Startup() gNameSpaceManager = nsnull; sRuntimeService = nsnull; sRuntime = nsnull; - gDOMThread = nsnull; gOldJSGCCallback = nsnull; sIsInitialized = PR_FALSE; sDidShutdown = PR_FALSE; @@ -2305,19 +2302,8 @@ nsJSEnvironment::Init() rv = sRuntimeService->GetRuntime(&sRuntime); NS_ENSURE_SUCCESS(rv, rv); - gDOMThread = PR_GetCurrentThread(); - -#ifdef DEBUG // Let's make sure that our main thread is the same as the xpcom main thread. - { - nsCOMPtr t; - PRThread* mainThread; - rv = nsIThread::GetMainThread(getter_AddRefs(t)); - NS_ASSERTION(NS_SUCCEEDED(rv) && t, "bad"); - rv = t->GetPRThread(&mainThread); - NS_ASSERTION(NS_SUCCEEDED(rv) && mainThread == gDOMThread, "bad"); - } -#endif + NS_ASSERTION(NS_IsMainThread(), "bad"); NS_ASSERTION(!gOldJSGCCallback, "nsJSEnvironment initialized more than once"); diff --git a/mozilla/embedding/browser/activex/src/common/StdAfx.h b/mozilla/embedding/browser/activex/src/common/StdAfx.h index 56d2396f17b..17230438a40 100644 --- a/mozilla/embedding/browser/activex/src/common/StdAfx.h +++ b/mozilla/embedding/browser/activex/src/common/StdAfx.h @@ -61,10 +61,8 @@ #include "prthread.h" #include "prprf.h" -#include "plevent.h" #include "nsIComponentManager.h" #include "nsIServiceManager.h" -#include "nsIEventQueueService.h" #include "nsStringAPI.h" #include "nsCOMPtr.h" #include "nsComponentManagerUtils.h" @@ -80,6 +78,7 @@ #include "nsIDOMDocumentType.h" #include "nsIDOMElement.h" +#undef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #define _ATL_APARTMENT_THREADED #define _ATL_STATIC_REGISTRY diff --git a/mozilla/embedding/browser/activex/src/control/StdAfx.h b/mozilla/embedding/browser/activex/src/control/StdAfx.h index 9d503010ed5..262e63510d8 100644 --- a/mozilla/embedding/browser/activex/src/control/StdAfx.h +++ b/mozilla/embedding/browser/activex/src/control/StdAfx.h @@ -61,7 +61,6 @@ #include "prthread.h" #include "prprf.h" -#include "plevent.h" #include "nsIComponentManager.h" #include "nsIServiceManager.h" #include "nsWidgetsCID.h" @@ -114,6 +113,7 @@ #include "nsIDOMMouseEvent.h" #include "nsIDOMEventReceiver.h" +#undef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #define _ATL_APARTMENT_THREADED #define _ATL_STATIC_REGISTRY diff --git a/mozilla/embedding/browser/activex/src/plugin/StdAfx.h b/mozilla/embedding/browser/activex/src/plugin/StdAfx.h index 81dcc13b78b..7f66d61a90b 100644 --- a/mozilla/embedding/browser/activex/src/plugin/StdAfx.h +++ b/mozilla/embedding/browser/activex/src/plugin/StdAfx.h @@ -49,6 +49,7 @@ #define STRICT +#undef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #define _ATL_APARTMENT_THREADED #define _ATL_STATIC_REGISTRY diff --git a/mozilla/embedding/browser/gtk/src/EmbedPrivate.cpp b/mozilla/embedding/browser/gtk/src/EmbedPrivate.cpp index 5306a85ba42..140dfe31016 100644 --- a/mozilla/embedding/browser/gtk/src/EmbedPrivate.cpp +++ b/mozilla/embedding/browser/gtk/src/EmbedPrivate.cpp @@ -45,9 +45,6 @@ #include "nsIDirectoryService.h" #include "nsAppDirectoryServiceDefs.h" -// for NS_APPSHELL_CID -#include - // for do_GetInterface #include // for do_CreateInstance @@ -96,13 +93,10 @@ #include "nsIDOMDocument.h" #endif -static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); - PRUint32 EmbedPrivate::sWidgetCount = 0; char *EmbedPrivate::sPath = nsnull; char *EmbedPrivate::sCompPath = nsnull; -nsIAppShell *EmbedPrivate::sAppShell = nsnull; nsVoidArray *EmbedPrivate::sWindowList = nsnull; nsILocalFile *EmbedPrivate::sProfileDir = nsnull; nsISupports *EmbedPrivate::sProfileLock = nsnull; @@ -568,21 +562,6 @@ EmbedPrivate::PushStartup(void) rv = RegisterAppComponents(); NS_ASSERTION(NS_SUCCEEDED(rv), "Warning: Failed to register app components.\n"); - - // XXX startup appshell service? - // XXX create offscreen window for appshell service? - // XXX remove X prop from offscreen window? - - nsCOMPtr appShell; - appShell = do_CreateInstance(kAppShellCID); - if (!appShell) { - NS_WARNING("Failed to create appshell in EmbedPrivate::PushStartup!\n"); - return; - } - sAppShell = appShell.get(); - NS_ADDREF(sAppShell); - sAppShell->Create(0, nsnull); - sAppShell->Spinup(); } } @@ -602,13 +581,6 @@ EmbedPrivate::PopStartup(void) sAppFileLocProvider = nsnull; } - if (sAppShell) { - // Shutdown the appshell service. - sAppShell->Spindown(); - NS_RELEASE(sAppShell); - sAppShell = 0; - } - // shut down XPCOM/Embedding XRE_TermEmbedding(); } diff --git a/mozilla/embedding/browser/photon/src/PtMozilla.cpp b/mozilla/embedding/browser/photon/src/PtMozilla.cpp index fc09ab02ed3..42720c66fab 100644 --- a/mozilla/embedding/browser/photon/src/PtMozilla.cpp +++ b/mozilla/embedding/browser/photon/src/PtMozilla.cpp @@ -79,7 +79,6 @@ #include "nsIURIFixup.h" #include "nsPIDOMWindow.h" -#include "nsIEventQueueService.h" #include "nsIServiceManager.h" #include "nsIComponentRegistrar.h" #include "nsUnknownContentTypeHandler.h" diff --git a/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp b/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp index 6f87fb24f04..ca0c2ec4b09 100644 --- a/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp +++ b/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp @@ -61,8 +61,6 @@ #include "nsIScreen.h" #include "nsIScreenManager.h" #include "nsIScriptContext.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" #include "nsIGenericFactory.h" #include "nsIJSContextStack.h" #include "nsIObserverService.h" @@ -89,25 +87,10 @@ #include "jsinterp.h" // for js_AllocStack() and js_FreeStack() -#ifdef XP_UNIX -// please see bug 78421 for the eventual "right" fix for this -#define HAVE_LAME_APPSHELL -#endif - -#ifdef HAVE_LAME_APPSHELL -#include "nsIAppShell.h" -// for NS_APPSHELL_CID -#include -#endif - #ifdef USEWEAKREFS #include "nsIWeakReference.h" #endif -#ifdef HAVE_LAME_APPSHELL -static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); -#endif - static const char *sJSStackContractID="@mozilla.org/js/xpc/ContextStack;1"; /**************************************************************** @@ -277,74 +260,6 @@ void nsWatcherWindowEnumerator::WindowRemoved(nsWatcherWindowEntry *inInfo) { inInfo->mYounger : 0; } -/**************************************************************** - ********************* EventQueueAutoPopper ********************* - ****************************************************************/ - -class EventQueueAutoPopper { -public: - EventQueueAutoPopper(); - ~EventQueueAutoPopper(); - - nsresult Push(); - -protected: - nsCOMPtr mService; - nsCOMPtr mQueue; -#ifdef HAVE_LAME_APPSHELL - nsCOMPtr mAppShell; -#endif -}; - -EventQueueAutoPopper::EventQueueAutoPopper() : mQueue(nsnull) -{ -} - -EventQueueAutoPopper::~EventQueueAutoPopper() -{ -#ifdef HAVE_LAME_APPSHELL - if (mAppShell) { - if (mQueue) - mAppShell->ListenToEventQueue(mQueue, PR_FALSE); - mAppShell->Spindown(); - mAppShell = nsnull; - } -#endif - - if(mQueue) - mService->PopThreadEventQueue(mQueue); -} - -nsresult EventQueueAutoPopper::Push() -{ - if (mQueue) // only once - return NS_ERROR_FAILURE; - - mService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID); - if (!mService) - return NS_ERROR_FAILURE; - - // push a new queue onto it - mService->PushThreadEventQueue(getter_AddRefs(mQueue)); - if (!mQueue) - return NS_ERROR_FAILURE; - -#ifdef HAVE_LAME_APPSHELL - // listen to the event queue - mAppShell = do_CreateInstance(kAppShellCID); - if (!mAppShell) - return NS_ERROR_FAILURE; - - mAppShell->Create(0, nsnull); - mAppShell->Spinup(); - - // listen to the new queue - mAppShell->ListenToEventQueue(mQueue, PR_TRUE); -#endif - - return NS_OK; -} - /**************************************************************** ********************** JSContextAutoPopper ********************* ****************************************************************/ @@ -568,7 +483,6 @@ nsWindowWatcher::OpenWindowJSInternal(nsIDOMWindow *aParent, nsCOMPtr uriToLoad; // from aUrl, if any nsCOMPtr parentTreeOwner; // from the parent window, if any nsCOMPtr newDocShellItem; // from the new window - EventQueueAutoPopper queueGuard; JSContextAutoPopper callerContextGuard; NS_ENSURE_ARG_POINTER(_retval); @@ -681,13 +595,10 @@ nsWindowWatcher::OpenWindowJSInternal(nsIDOMWindow *aParent, parentChrome->IsWindowModal(&weAreModal); if (weAreModal) { - rv = queueGuard.Push(); - if (NS_SUCCEEDED(rv)) { - windowIsModal = PR_TRUE; - // in case we added this because weAreModal - chromeFlags |= nsIWebBrowserChrome::CHROME_MODAL | - nsIWebBrowserChrome::CHROME_DEPENDENT; - } + windowIsModal = PR_TRUE; + // in case we added this because weAreModal + chromeFlags |= nsIWebBrowserChrome::CHROME_MODAL | + nsIWebBrowserChrome::CHROME_DEPENDENT; } NS_ASSERTION(mWindowCreator, diff --git a/mozilla/embedding/tests/mfcembed/components/PrintingPromptService.cpp b/mozilla/embedding/tests/mfcembed/components/PrintingPromptService.cpp index eeb94b82018..644e0c52f31 100644 --- a/mozilla/embedding/tests/mfcembed/components/PrintingPromptService.cpp +++ b/mozilla/embedding/tests/mfcembed/components/PrintingPromptService.cpp @@ -41,6 +41,7 @@ #include "nsMemory.h" #include "nsString.h" #include "nsReadableUtils.h" +#include "nsThreadUtils.h" #include "nsIDOMWindow.h" #include "nsIEmbeddingSiteWindow.h" #include "nsIFactory.h" @@ -53,10 +54,6 @@ #include "nsPrintDialogUtil.h" #include "PrintProgressDialog.h" -// For PLEvent -#include "nsIEventQueueService.h" -#include "plevent.h" - static HINSTANCE gInstance; //***************************************************************************** @@ -103,11 +100,6 @@ private: CPrintProgressDialog* m_PPDlg; }; -// Define PL Callback Functions -static void* PR_CALLBACK HandlePLEvent(PLEvent* aEvent); -static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent); - - //***************************************************************************** NS_IMPL_ISUPPORTS2(CPrintingPromptService, nsIPrintingPromptService, nsIWebProgressListener) @@ -167,47 +159,13 @@ CPrintingPromptService::ShowPrintDialog(nsIDOMWindow *parent, nsIWebBrowserPrint } } - //----------------------------------------------------------- PRBool CPrintingPromptService::FirePauseEvent() { - static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - - nsCOMPtr event_service = do_GetService(kEventQueueServiceCID); - - if (!event_service) - { - NS_WARNING("Failed to get event queue service"); - return PR_FALSE; - } - - nsCOMPtr event_queue; - - event_service->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(event_queue)); - - if (!event_queue) - { - NS_WARNING("Failed to get event queue from service"); - return PR_FALSE; - } - - PLEvent *event = new PLEvent; - - if (!event) - { - NS_WARNING("Out of memory?"); - return PR_FALSE; - } - - PL_InitEvent(event, this, ::HandlePLEvent, ::DestroyPLEvent); - - // The event owns the content pointer now. - NS_ADDREF_THIS(); - - event_queue->PostEvent(event); - return PR_TRUE; + nsCOMPtr event = + NS_NewRunnableMethod(this, &CPrintingPromptService::NotifyObserver); + return NS_SUCCEEDED(NS_DispatchToCurrentThread(event)); } /* void showProgress (in nsIDOMWindow parent, in nsIWebBrowserPrint webBrowserPrint, in nsIPrintSettings printSettings, in nsIObserver openDialogObserver, in boolean isForPrinting, out nsIWebProgressListener webProgressListener, out nsIPrintProgressParams printProgressParams, out boolean notifyOnOpen); */ @@ -276,27 +234,6 @@ void CPrintingPromptService::NotifyObserver() } } -//------------------------------------------------------------------------ -void* PR_CALLBACK HandlePLEvent(PLEvent* aEvent) -{ - CPrintingPromptService *printingPromptService = (CPrintingPromptService*)PL_GetEventOwner(aEvent); - - NS_ASSERTION(printingPromptService, "The event owner is null."); - if (printingPromptService) { - printingPromptService->NotifyObserver(); - } - return nsnull; -} - -//------------------------------------------------------------------------ -void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent) -{ - CPrintingPromptService *printingPromptService = (CPrintingPromptService*)PL_GetEventOwner(aEvent); - NS_IF_RELEASE(printingPromptService); - - delete aEvent; -} - ////////////////////////////////////////////////////////////////////// // nsIWebProgressListener ////////////////////////////////////////////////////////////////////// diff --git a/mozilla/extensions/datetime/nsDateTimeChannel.cpp b/mozilla/extensions/datetime/nsDateTimeChannel.cpp index f40c87293ef..315e30746f7 100644 --- a/mozilla/extensions/datetime/nsDateTimeChannel.cpp +++ b/mozilla/extensions/datetime/nsDateTimeChannel.cpp @@ -51,7 +51,7 @@ #include "nsIStreamConverterService.h" #include "nsITXTToHTMLConv.h" #include "nsIProgressEventSink.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsCRT.h" @@ -192,9 +192,8 @@ nsDateTimeChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt) nsresult rv = NS_CheckPortSafety(mPort, "datetime"); if (NS_FAILED(rv)) return rv; - nsCOMPtr eventQ; - rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - if (NS_FAILED(rv)) return rv; + nsCOMPtr thread = do_GetCurrentThread(); + NS_ENSURE_STATE(thread); // // create transport @@ -208,7 +207,7 @@ nsDateTimeChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt) if (NS_FAILED(rv)) return rv; // not fatal if this fails - mTransport->SetEventSink(this, eventQ); + mTransport->SetEventSink(this, thread); // // create TXT to HTML stream converter diff --git a/mozilla/extensions/finger/nsFingerChannel.cpp b/mozilla/extensions/finger/nsFingerChannel.cpp index 96f1ed3467a..3c90b33eb3d 100644 --- a/mozilla/extensions/finger/nsFingerChannel.cpp +++ b/mozilla/extensions/finger/nsFingerChannel.cpp @@ -52,7 +52,7 @@ #include "nsIStreamConverterService.h" #include "nsITXTToHTMLConv.h" #include "nsIProgressEventSink.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsCRT.h" @@ -211,9 +211,8 @@ nsFingerChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt) nsresult rv = NS_CheckPortSafety(mPort, "finger"); if (NS_FAILED(rv)) return rv; - nsCOMPtr eventQ; - rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - if (NS_FAILED(rv)) return rv; + nsCOMPtr thread = do_GetCurrentThread(); + NS_ENSURE_STATE(thread); // // create transport @@ -227,7 +226,7 @@ nsFingerChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt) if (NS_FAILED(rv)) return rv; // not fatal if this fails - mTransport->SetEventSink(this, eventQ); + mTransport->SetEventSink(this, thread); rv = WriteRequest(mTransport); if (NS_FAILED(rv)) return rv; diff --git a/mozilla/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp b/mozilla/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp index 91e15dbe61e..524de11da92 100644 --- a/mozilla/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp +++ b/mozilla/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp @@ -47,7 +47,7 @@ extern "C" { #include "nsIPrefService.h" #include "nsIPrefBranch2.h" #include "nsIObserver.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsProxyRelease.h" #include "nsIAuthPrompt.h" #include "nsIStringBundle.h" @@ -282,31 +282,20 @@ ProxiedAuthCallback(gconstpointer in, nsMemory::Free(pass); } -struct nsGnomeVFSAuthParams +struct nsGnomeVFSAuthCallbackEvent : public nsRunnable { gconstpointer in; gsize in_size; gpointer out; gsize out_size; gpointer callback_data; + + NS_IMETHOD Run() { + ProxiedAuthCallback(in, in_size, out, out_size, callback_data); + return NS_OK; + } }; -PR_STATIC_CALLBACK(void *) -AuthCallbackEventHandler(PLEvent *ev) -{ - nsGnomeVFSAuthParams *params = (nsGnomeVFSAuthParams *) ev->owner; - ProxiedAuthCallback(params->in, params->in_size, - params->out, params->out_size, - params->callback_data); - return nsnull; -} - -PR_STATIC_CALLBACK(void) -AuthCallbackEventDestructor(PLEvent *ev) -{ - // ignored -} - static void AuthCallback(gconstpointer in, gsize in_size, @@ -314,30 +303,20 @@ AuthCallback(gconstpointer in, gsize out_size, gpointer callback_data) { - // Need to proxy this callback over to the main thread. This code is greatly - // simplified by the fact that we are making a synchronous callback. E.g., we - // don't need to allocate the PLEvent on the heap. + // Need to proxy this callback over to the main thread. Synchronous dispatch + // is required in order to provide data to the GnomeVFS callback. - nsCOMPtr eventQ; - NS_GetMainEventQ(getter_AddRefs(eventQ)); - if (!eventQ) - return; + nsRefPtr ev = new nsGnomeVFSAuthCallbackEvent(); + if (!ev) + return; // OOM - nsGnomeVFSAuthParams params; - params.in = in; - params.in_size = in_size; - params.out = out; - params.out_size = out_size; - params.callback_data = callback_data; + ev->in = in; + ev->in_size = in_size; + ev->out = out; + ev->out_size = out_size; + ev->callback_data = callback_data; - PLEvent ev; - PL_InitEvent(&ev, ¶ms, - AuthCallbackEventHandler, - AuthCallbackEventDestructor); - - void *result; - if (NS_FAILED(eventQ->PostSynchronousEvent(&ev, &result))) - PL_DestroyEvent(&ev); + NS_DispatchToMainThread(ev, NS_DISPATCH_SYNC); } //----------------------------------------------------------------------------- @@ -618,32 +597,25 @@ nsGnomeVFSInputStream::DoRead(char *aBuf, PRUint32 aCount, PRUint32 *aCountRead) } // This class is used to implement SetContentTypeOfChannel. -class nsGnomeVFSSetContentTypeEvent : public PLEvent +class nsGnomeVFSSetContentTypeEvent : public nsRunnable { public: nsGnomeVFSSetContentTypeEvent(nsIChannel *channel, const char *contentType) - : mContentType(contentType) + : mChannel(channel), mContentType(contentType) { - // stash channel reference in owner field. no AddRef here! see note + // stash channel reference in mChannel. no AddRef here! see note // in SetContentTypeOfchannel. - PL_InitEvent(this, channel, EventHandler, EventDestructor); } - PR_STATIC_CALLBACK(void *) EventHandler(PLEvent *ev) + NS_IMETHOD Run() { - nsGnomeVFSSetContentTypeEvent *self = (nsGnomeVFSSetContentTypeEvent *) ev; - ((nsIChannel *) self->owner)->SetContentType(self->mContentType); - return nsnull; - } - - PR_STATIC_CALLBACK(void) EventDestructor(PLEvent *ev) - { - nsGnomeVFSSetContentTypeEvent *self = (nsGnomeVFSSetContentTypeEvent *) ev; - delete self; + mChannel->SetContentType(mContentType); + return NS_OK; } private: - nsCString mContentType; + nsIChannel *mChannel; + nsCString mContentType; }; nsresult @@ -656,12 +628,7 @@ nsGnomeVFSInputStream::SetContentTypeOfChannel(const char *contentType) // thread's event queue to protect us against memory corruption. nsresult rv; - nsCOMPtr eventQ; - rv = NS_GetMainEventQ(getter_AddRefs(eventQ)); - if (NS_FAILED(rv)) - return rv; - - nsGnomeVFSSetContentTypeEvent *ev = + nsCOMPtr ev = new nsGnomeVFSSetContentTypeEvent(mChannel, contentType); if (!ev) { @@ -669,9 +636,7 @@ nsGnomeVFSInputStream::SetContentTypeOfChannel(const char *contentType) } else { - rv = eventQ->PostEvent(ev); - if (NS_FAILED(rv)) - PL_DestroyEvent(ev); + rv = NS_DispatchToMainThread(ev); } return rv; } @@ -698,14 +663,13 @@ nsGnomeVFSInputStream::Close() if (mChannel) { - nsresult rv; + nsresult rv = NS_OK; - nsCOMPtr eventQ; - rv = NS_GetMainEventQ(getter_AddRefs(eventQ)); - if (NS_SUCCEEDED(rv)) - rv = NS_ProxyRelease(eventQ, mChannel); + nsCOMPtr thread = do_GetMainThread(); + if (thread) + rv = NS_ProxyRelease(thread, mChannel); - NS_ASSERTION(NS_SUCCEEDED(rv), "leaking channel reference"); + NS_ASSERTION(thread && NS_SUCCEEDED(rv), "leaking channel reference"); mChannel = nsnull; } diff --git a/mozilla/extensions/irc/js/lib/dcc.js b/mozilla/extensions/irc/js/lib/dcc.js index c38b28bca45..74894ede804 100644 --- a/mozilla/extensions/irc/js/lib/dcc.js +++ b/mozilla/extensions/irc/js/lib/dcc.js @@ -130,10 +130,14 @@ function dcc_addhost(host, auth) }; try { - const EQS = getService("@mozilla.org/event-queue-service;1", - "nsIEventQueueService"); - var th = EQS.getSpecialEventQueue(EQS.CURRENT_THREAD_EVENT_QUEUE); - + var th; + if (jsenv.HAS_THREAD_MANAGER) { + th = getService("@mozilla.org/thread-manager;1").currentThread; + } else { + const EQS = getService("@mozilla.org/event-queue-service;1", + "nsIEventQueueService"); + th = EQS.getSpecialEventQueue(EQS.CURRENT_THREAD_EVENT_QUEUE); + } var dnsRecord = this._dnsSvc.asyncResolve(host, false, listener, th); } catch (ex) { dd("Error resolving host to IP: " + ex); diff --git a/mozilla/extensions/irc/js/lib/utils.js b/mozilla/extensions/irc/js/lib/utils.js index 998efdbae40..ad42b23bbec 100644 --- a/mozilla/extensions/irc/js/lib/utils.js +++ b/mozilla/extensions/irc/js/lib/utils.js @@ -120,6 +120,7 @@ jsenv.HAS_DOCUMENT = (typeof document == "object"); jsenv.HAS_NSPR_EVENTQ = jsenv.HAS_DOCUMENT; jsenv.HAS_STREAM_PROVIDER = ("nsIStreamProvider" in Components.interfaces); jsenv.HAS_SERVER_SOCKETS = ("nsIServerSocket" in Components.interfaces); +jsenv.HAS_THREAD_MANAGER = ("nsIThreadManager" in Components.interfaces); function dumpObject (o, pfx, sep) { diff --git a/mozilla/extensions/java/xpcom/nsJavaInterfaces.cpp b/mozilla/extensions/java/xpcom/nsJavaInterfaces.cpp index c83940a4ea3..7222dadcbe8 100644 --- a/mozilla/extensions/java/xpcom/nsJavaInterfaces.cpp +++ b/mozilla/extensions/java/xpcom/nsJavaInterfaces.cpp @@ -46,7 +46,6 @@ #include "nsIInputStream.h" #include "nsEnumeratorUtils.h" #include "nsAppFileLocProviderProxy.h" -#include "nsIEventQueueService.h" #include "nsXULAppAPI.h" #include "nsILocalFile.h" @@ -137,13 +136,6 @@ InitXPCOM_Impl(JNIEnv* env, jobject aMozBinDirectory, } NS_ENSURE_SUCCESS(rv, rv); - // init Event Queue - nsCOMPtr eventQService = - do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - rv = eventQService->CreateThreadEventQueue(); - NS_ENSURE_SUCCESS(rv, rv); - // create Java proxy for service manager returned by NS_InitXPCOM2 return GetNewOrUsedJavaObject(env, servMan, NS_GET_IID(nsIServiceManager), aResult); diff --git a/mozilla/extensions/java/xpcom/nsJavaXPCOMBindingUtils.cpp b/mozilla/extensions/java/xpcom/nsJavaXPCOMBindingUtils.cpp index cc8604920d7..910a82bb7ef 100644 --- a/mozilla/extensions/java/xpcom/nsJavaXPCOMBindingUtils.cpp +++ b/mozilla/extensions/java/xpcom/nsJavaXPCOMBindingUtils.cpp @@ -42,7 +42,7 @@ #include "jni.h" #include "nsIInterfaceInfoManager.h" #include "nsILocalFile.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsProxyRelease.h" @@ -742,11 +742,10 @@ JavaXPCOMInstance::JavaXPCOMInstance(nsISupports* aInstance, JavaXPCOMInstance::~JavaXPCOMInstance() { // Need to release these objects on the main thread. - nsCOMPtr eventQ; - nsresult rv = NS_GetMainEventQ(getter_AddRefs(eventQ)); - if (NS_SUCCEEDED(rv)) { - rv = NS_ProxyRelease(eventQ, mInstance); - rv += NS_ProxyRelease(eventQ, mIInfo); + nsCOMPtr thread = do_GetMainThread(); + if (thread) { + rv = NS_ProxyRelease(thread, mInstance); + rv |= NS_ProxyRelease(thread, mIInfo); } NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to release using NS_ProxyRelease"); } diff --git a/mozilla/extensions/jssh/nsJSSh.cpp b/mozilla/extensions/jssh/nsJSSh.cpp index fb3e7b89ca5..8389d4c0701 100644 --- a/mozilla/extensions/jssh/nsJSSh.cpp +++ b/mozilla/extensions/jssh/nsJSSh.cpp @@ -41,18 +41,14 @@ #include "nsIServiceManager.h" #include "nsIXPConnect.h" #include "nsIProxyObjectManager.h" -#include "nsIEventQueueService.h" #include "nsIScriptSecurityManager.h" #include "nsDependentString.h" #include "nsIIOService.h" #include "nsNetCID.h" #include "nsIChannel.h" -#include "nsIThread.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); //********************************************************************** @@ -202,20 +198,7 @@ FlushEventQueue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rv nsJSSh* shell; if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE; - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID); - nsCOMPtr eventQueue; - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(eventQueue)); - PRBool avail; - while(NS_SUCCEEDED(eventQueue->EventAvailable(avail)) && avail) { -#ifdef DEBUG - printf("."); -#endif - PLEvent *ev; - eventQueue->GetEvent(&ev); - eventQueue->HandleEvent(ev); - } + NS_ProcessPendingEvents(nsnull); return JS_TRUE; } @@ -226,28 +209,15 @@ Suspend(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) nsJSSh* shell; if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE; - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID); - nsCOMPtr eventQueue; - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(eventQueue)); + nsCOMPtr thread = do_GetCurrentThread(); + PR_AtomicIncrement(&shell->mSuspendCount); - PLEvent *ev; - while(shell->mSuspendCount) { + while (shell->mSuspendCount) { #ifdef DEBUG printf("|"); #endif - -// eventQueue->ProcessPendingEvents(); -// XXX We can't use ProcessPendingEvents() here, because the JSSh -// itself gets called from an AppShell's call to -// ProcessPendingEvents() (via a proxy-event) and -// ProcessPendingEvents() guards against recursive entry. We have -// to pump events manually: - - eventQueue->WaitForEvent(&ev); - eventQueue->HandleEvent(ev); + NS_ProcessNextEvent(thread); } return JS_TRUE; @@ -488,23 +458,12 @@ NS_INTERFACE_MAP_END NS_IMETHODIMP nsJSSh::Run() { nsCOMPtr proxied_shell; - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID); - nsCOMPtr currentEventQ; - eventQService->GetSpecialEventQueue(nsIEventQueueService::CURRENT_THREAD_EVENT_QUEUE, - getter_AddRefs(currentEventQ)); - nsCOMPtr mainEventQ; - eventQService->GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs(mainEventQ)); - if (!SameCOMIdentity(mainEventQ, currentEventQ)) { - nsCOMPtr proxyObjMgr = - do_GetService(kProxyObjectManagerCID); - NS_ASSERTION(proxyObjMgr, "no proxy object manager!"); - proxyObjMgr->GetProxyForObject(NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIJSSh), - (nsIJSSh*)this, - PROXY_SYNC, - getter_AddRefs(proxied_shell)); + if (!NS_IsMainThread()) { + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIJSSh), + (nsIJSSh*)this, + NS_PROXY_SYNC, + getter_AddRefs(proxied_shell)); } else { #ifdef DEBUG @@ -554,6 +513,19 @@ NS_IMETHODIMP nsJSSh::Run() } proxied_shell->Cleanup(); + + if (!NS_IsMainThread()) { + // Shutdown the current thread, which must be done from the main thread. + nsCOMPtr thread = do_GetCurrentThread(); + nsCOMPtr proxied_thread; + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIThread), + thread.get(), + NS_PROXY_ASYNC, + getter_AddRefs(proxied_thread)); + if (proxied_thread) + proxied_thread->Shutdown(); + } return NS_OK; } diff --git a/mozilla/extensions/jssh/nsJSShServer.cpp b/mozilla/extensions/jssh/nsJSShServer.cpp index c5c3050df44..eafbf977cad 100644 --- a/mozilla/extensions/jssh/nsJSShServer.cpp +++ b/mozilla/extensions/jssh/nsJSShServer.cpp @@ -42,11 +42,10 @@ #include "nsIComponentManager.h" #include "nsIInputStream.h" #include "nsIOutputStream.h" -#include "nsIThread.h" +#include "nsThreadUtils.h" #include "nsJSSh.h" static NS_DEFINE_CID(kServerSocketCID, NS_SERVERSOCKET_CID); -static NS_DEFINE_CID(kThreadCID, NS_THREAD_CID); //********************************************************************** // ConnectionListener helper class @@ -110,8 +109,9 @@ NS_IMETHODIMP ConnectionListener::OnSocketAccepted(nsIServerSocket *aServ, nsISo #endif nsCOMPtr shell = CreateJSSh(input, output, mStartupURI); - nsCOMPtr thread = do_CreateInstance(kThreadCID); - thread->Init(shell, 0, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD , PR_UNJOINABLE_THREAD); + + nsCOMPtr thread; + NS_NewThread(getter_AddRefs(thread), shell); return NS_OK; } @@ -210,8 +210,8 @@ nsJSShServer::RunShell(nsIInputStream *input, nsIOutputStream *output, { nsCOMPtr shell = CreateJSSh(input, output, nsCString(startupURI)); if (!blocking) { - nsCOMPtr thread = do_CreateInstance(kThreadCID); - thread->Init(shell, 0, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD , PR_UNJOINABLE_THREAD); + nsCOMPtr thread; + NS_NewThread(getter_AddRefs(thread), shell); } else shell->Run(); diff --git a/mozilla/extensions/pref/autoconfig/src/nsAutoConfig.cpp b/mozilla/extensions/pref/autoconfig/src/nsAutoConfig.cpp index 2b3d4b8faea..6a27cbd0204 100644 --- a/mozilla/extensions/pref/autoconfig/src/nsAutoConfig.cpp +++ b/mozilla/extensions/pref/autoconfig/src/nsAutoConfig.cpp @@ -44,11 +44,11 @@ #include "nsIURI.h" #include "nsIHttpChannel.h" #include "nsIFileStreams.h" +#include "nsThreadUtils.h" #include "nsAppDirectoryServiceDefs.h" #include "prmem.h" #include "nsIProfile.h" #include "nsIObserverService.h" -#include "nsIEventQueueService.h" #include "nsLiteralString.h" #include "nsIPromptService.h" #include "nsIServiceManager.h" @@ -353,19 +353,11 @@ nsresult nsAutoConfig::downloadAutoConfig() firstTime = PR_FALSE; - // Getting an event queue. If we start an AsyncOpen, the thread + // Getting the current thread. If we start an AsyncOpen, the thread // needs to wait before the reading of autoconfig is done - nsCOMPtr service = - do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr currentThreadQ; - rv = service->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(currentThreadQ)); - if (NS_FAILED(rv)) - return rv; + nsCOMPtr thread = do_GetCurrentThread(); + NS_ENSURE_STATE(thread); /* process events until we're finished. AutoConfig.jsc reading needs to be finished before the browser starts loading up @@ -375,18 +367,8 @@ nsresult nsAutoConfig::downloadAutoConfig() that mLoaded will be set to true in any case (success/failure) */ - while (!mLoaded) { - - PRBool isEventPending; - rv = currentThreadQ->PendingEvents(&isEventPending); - if (NS_FAILED(rv)) - return rv; - if (isEventPending) { - rv = currentThreadQ->ProcessPendingEvents(); - if (NS_FAILED(rv)) - return rv; - } - } + while (!mLoaded) + NS_ENSURE_STATE(NS_ProcessNextEvent(thread)); PRInt32 minutes = 0; rv = mPrefBranch->GetIntPref("autoadmin.refresh_interval", diff --git a/mozilla/extensions/pref/autoconfig/src/nsLDAPSyncQuery.cpp b/mozilla/extensions/pref/autoconfig/src/nsLDAPSyncQuery.cpp index c91938c2326..1de5f1f0eb3 100644 --- a/mozilla/extensions/pref/autoconfig/src/nsLDAPSyncQuery.cpp +++ b/mozilla/extensions/pref/autoconfig/src/nsLDAPSyncQuery.cpp @@ -44,7 +44,7 @@ #include "nsIProxyObjectManager.h" #include "nsXPIDLString.h" #include "nsILDAPErrors.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsReadableUtils.h" #include "nsILDAPMessage.h" @@ -144,10 +144,10 @@ nsLDAPSyncQuery::OnLDAPInit(nsILDAPConnection *aConn, nsresult aStatus) // get a proxy object so the callback happens on the main thread // - rv = NS_GetProxyForObject(NS_CURRENT_EVENTQ, + rv = NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, NS_GET_IID(nsILDAPMessageListener), NS_STATIC_CAST(nsILDAPMessageListener *, this), - PROXY_ASYNC | PROXY_ALWAYS, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, getter_AddRefs(selfProxy)); if (NS_FAILED(rv)) { FinishLDAPQuery(); @@ -283,10 +283,10 @@ nsLDAPSyncQuery::StartLDAPSearch() // get a proxy object so the callback happens on the main thread // - rv = NS_GetProxyForObject(NS_CURRENT_EVENTQ, + rv = NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, NS_GET_IID(nsILDAPMessageListener), NS_STATIC_CAST(nsILDAPMessageListener *, this), - PROXY_ASYNC | PROXY_ALWAYS, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, getter_AddRefs(selfProxy)); if (NS_FAILED(rv)) { NS_ERROR("nsLDAPSyncQuery::StartLDAPSearch(): couldn't " @@ -407,10 +407,10 @@ nsresult nsLDAPSyncQuery::InitConnection() // get a proxy object so the callback happens on the main thread // - rv = NS_GetProxyForObject(NS_CURRENT_EVENTQ, + rv = NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, NS_GET_IID(nsILDAPMessageListener), NS_STATIC_CAST(nsILDAPMessageListener *, this), - PROXY_ASYNC | PROXY_ALWAYS, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, getter_AddRefs(selfProxy)); if (NS_FAILED(rv)) { FinishLDAPQuery(); @@ -461,22 +461,7 @@ NS_IMETHODIMP nsLDAPSyncQuery::GetQueryResults(nsILDAPURL *aServerURL, mServerURL = aServerURL; mProtocolVersion = aProtocolVersion; - nsCOMPtr currentThreadQ; - nsCOMPtr service; - - // Get the eventQueue Service - // - service = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) { - return rv; - } - - // Get the eventQ for the Current Thread - // - rv = service->PushThreadEventQueue(getter_AddRefs(currentThreadQ)); - if (NS_FAILED(rv)) { - return rv; - } + nsCOMPtr currentThread = do_GetCurrentThread(); // Start an LDAP query. // InitConnection will bind to the ldap server and post a OnLDAPMessage @@ -484,10 +469,8 @@ NS_IMETHODIMP nsLDAPSyncQuery::GetQueryResults(nsILDAPURL *aServerURL, // be carried out by chain of events // rv = InitConnection(); - if (NS_FAILED(rv)) { - service->PopThreadEventQueue(currentThreadQ); + if (NS_FAILED(rv)) return rv; - } // We want this LDAP query to be synchronous while the XPCOM LDAP is // async in nature. So this eventQueue handling will wait for the @@ -499,26 +482,8 @@ NS_IMETHODIMP nsLDAPSyncQuery::GetQueryResults(nsILDAPURL *aServerURL, // Run the event loop, // mFinished is a control variable // - while (!mFinished) { - - PRBool isEventPending; - rv = currentThreadQ->PendingEvents(&isEventPending); - if (NS_FAILED(rv)) { - service->PopThreadEventQueue(currentThreadQ); - return rv; - } - if (isEventPending) { - rv = currentThreadQ->ProcessPendingEvents(); - if (NS_FAILED(rv)) { - service->PopThreadEventQueue(currentThreadQ); - return rv; - } - } - - } - rv = service->PopThreadEventQueue(currentThreadQ); - if (NS_FAILED(rv)) - return rv; + while (!mFinished) + NS_ENSURE_STATE(NS_ProcessNextEvent(currentThread)); // Return results // diff --git a/mozilla/extensions/webdav/tests/davshell.js b/mozilla/extensions/webdav/tests/davshell.js index cde5f351795..453ac8d3f76 100644 --- a/mozilla/extensions/webdav/tests/davshell.js +++ b/mozilla/extensions/webdav/tests/davshell.js @@ -180,15 +180,14 @@ OperationListener.prototype = } } -const evQSvc = getService("@mozilla.org/event-queue-service;1", - "nsIEventQueueService"); -const evQ = evQSvc.getSpecialEventQueue(CI.nsIEventQueueService.CURRENT_THREAD_EVENT_QUEUE); +const thrd = + C.classes["@mozilla.org/thread-manager;1"].getService().currentThread; function runEventPump() { pumpRunning = true; while (pumpRunning) { - evQ.processPendingEvents(); + thrd.processNextEvent(); } } diff --git a/mozilla/extensions/webservices/security/src/nsWSAUtils.cpp b/mozilla/extensions/webservices/security/src/nsWSAUtils.cpp index 75b46d8332e..400c667de6b 100755 --- a/mozilla/extensions/webservices/security/src/nsWSAUtils.cpp +++ b/mozilla/extensions/webservices/security/src/nsWSAUtils.cpp @@ -45,14 +45,12 @@ #include "nsIDNSRecord.h" #include "nsICancelable.h" #include "nsIRequest.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsAutoPtr.h" #include "nsNetCID.h" static const char kSecurityProperties[] = "chrome://global/locale/webservices/security.properties"; -static NS_DEFINE_CID(kDNSServiceCID, NS_DNSSERVICE_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); class nsDNSListener : public nsIDNSListener { @@ -228,7 +226,7 @@ nsWSAUtils::GetOfficialHostName(nsIURI* aServiceURI, return NS_ERROR_NULL_POINTER; nsresult rv; - nsCOMPtr dns(do_GetService(kDNSServiceCID, &rv)); + nsCOMPtr dns(do_GetService(NS_DNSSERVICE_CONTRACTID, &rv)); if (NS_FAILED(rv)) return rv; @@ -239,36 +237,21 @@ nsWSAUtils::GetOfficialHostName(nsIURI* aServiceURI, nsRefPtr listener = new nsDNSListener(); NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY); - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr eventQ; - rv = eventQService->PushThreadEventQueue(getter_AddRefs(eventQ)); - - if (NS_FAILED(rv)) - return rv; + nsCOMPtr thread = do_GetCurrentThread(); + NS_ENSURE_STATE(thread); nsCOMPtr dummy; rv = dns->AsyncResolve(host, nsIDNSService::RESOLVE_CANONICAL_NAME, - listener, eventQ, getter_AddRefs(dummy)); + listener, thread, getter_AddRefs(dummy)); - PLEvent *ev; - while (NS_SUCCEEDED(rv) && !listener->mLookupFinished) { - rv = eventQ->WaitForEvent(&ev); - NS_ASSERTION(NS_SUCCEEDED(rv), "WaitForEvent failed"); - if (NS_SUCCEEDED(rv)) { - rv = eventQ->HandleEvent(ev); - NS_ASSERTION(NS_SUCCEEDED(rv), "HandleEvent failed"); + while (!listener->mLookupFinished) { + if (!NS_ProcessNextEvent(thread)) { + rv = NS_ERROR_UNEXPECTED; + break; } } aResult.Assign(listener->mOfficialHostName); - - eventQService->PopThreadEventQueue(eventQ); - return rv; } @@ -295,4 +278,3 @@ nsDNSListener::OnLookupComplete(nsICancelable* aRequest, mLookupFinished = PR_TRUE; return NS_OK; } - diff --git a/mozilla/extensions/webservices/security/src/nsWSAUtils.h b/mozilla/extensions/webservices/security/src/nsWSAUtils.h index 8d9896d384e..5829f97997c 100755 --- a/mozilla/extensions/webservices/security/src/nsWSAUtils.h +++ b/mozilla/extensions/webservices/security/src/nsWSAUtils.h @@ -39,7 +39,6 @@ #define nsWSAUtils_h__ #include "nsIDNSListener.h" -#include "nsIEventQueueService.h" #include "nsIURI.h" #include "nsCOMPtr.h" #include "nsString.h" diff --git a/mozilla/intl/strres/src/nsStringBundle.cpp b/mozilla/intl/strres/src/nsStringBundle.cpp index 829bad1752d..296c5bdd2d1 100644 --- a/mozilla/intl/strres/src/nsStringBundle.cpp +++ b/mozilla/intl/strres/src/nsStringBundle.cpp @@ -74,9 +74,6 @@ #include "nsIStringStream.h" #endif -// eventQ -#include "nsIEventQueueService.h" - #include "prenv.h" #include "nsCRT.h" diff --git a/mozilla/intl/strres/tests/StringBundleTest.cpp b/mozilla/intl/strres/tests/StringBundleTest.cpp index 154c4b07d69..96a6c9718ed 100644 --- a/mozilla/intl/strres/tests/StringBundleTest.cpp +++ b/mozilla/intl/strres/tests/StringBundleTest.cpp @@ -37,7 +37,6 @@ #include "nsCOMPtr.h" #include "nsIStringBundle.h" -#include "nsIEventQueueService.h" #include #include "nsIURL.h" diff --git a/mozilla/ipc/ipcd/client/src/ipcdclient.cpp b/mozilla/ipc/ipcd/client/src/ipcdclient.cpp index aa28e969e5b..2cc3d90c478 100644 --- a/mozilla/ipc/ipcd/client/src/ipcdclient.cpp +++ b/mozilla/ipc/ipcd/client/src/ipcdclient.cpp @@ -44,7 +44,7 @@ #include "ipcm.h" #include "nsIFile.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsDirectoryServiceUtils.h" #include "nsDirectoryServiceDefs.h" #include "nsCOMPtr.h" @@ -81,8 +81,8 @@ public: // this may be null nsCOMPtr observer; - // the message observer is called via this event queue - nsCOMPtr eventQ; + // the message observer is called on this thread + nsCOMPtr thread; // incoming messages are added to this list ipcMessageQ pendingQ; @@ -130,9 +130,9 @@ ipcTargetData::SetObserver(ipcIMessageObserver *aObserver, PRBool aOnCurrentThre observer = aObserver; if (aOnCurrentThread) - NS_GetCurrentEventQ(getter_AddRefs(eventQ)); + NS_GetCurrentThread(getter_AddRefs(thread)); else - eventQ = nsnull; + thread = nsnull; } /* ------------------------------------------------------------------------- */ @@ -400,65 +400,27 @@ WaitTarget(const nsID &aTarget, /* ------------------------------------------------------------------------- */ -static void -PostEvent(nsIEventTarget *eventTarget, PLEvent *ev) -{ - if (!ev) - return; - - nsresult rv = eventTarget->PostEvent(ev); - if (NS_FAILED(rv)) - { - NS_WARNING("PostEvent failed"); - PL_DestroyEvent(ev); - } -} - -static void -PostEventToMainThread(PLEvent *ev) -{ - nsCOMPtr eventQ; - NS_GetMainEventQ(getter_AddRefs(eventQ)); - if (!eventQ) - { - NS_WARNING("unable to get reference to main event queue"); - PL_DestroyEvent(ev); - return; - } - PostEvent(eventQ, ev); -} - -/* ------------------------------------------------------------------------- */ - -class ipcEvent_ClientState : public PLEvent +class ipcEvent_ClientState : public nsRunnable { public: ipcEvent_ClientState(PRUint32 aClientID, PRUint32 aClientState) : mClientID(aClientID) , mClientState(aClientState) { - PL_InitEvent(this, nsnull, HandleEvent, DestroyEvent); } - PR_STATIC_CALLBACK(void *) HandleEvent(PLEvent *ev) + NS_IMETHOD Run() { // maybe we've been shutdown! if (!gClientState) return nsnull; - ipcEvent_ClientState *self = (ipcEvent_ClientState *) ev; - for (PRInt32 i=0; iclientObservers.Count(); ++i) - gClientState->clientObservers[i]->OnClientStateChange(self->mClientID, - self->mClientState); + gClientState->clientObservers[i]->OnClientStateChange(mClientID, + mClientState); return nsnull; } - PR_STATIC_CALLBACK(void) DestroyEvent(PLEvent *ev) - { - delete (ipcEvent_ClientState *) ev; - } - private: PRUint32 mClientID; PRUint32 mClientState; @@ -466,48 +428,55 @@ private: /* ------------------------------------------------------------------------- */ -class ipcEvent_ProcessPendingQ : public PLEvent +class ipcEvent_ProcessPendingQ : public nsRunnable { public: ipcEvent_ProcessPendingQ(const nsID &aTarget) : mTarget(aTarget) { - PL_InitEvent(this, nsnull, HandleEvent, DestroyEvent); } - PR_STATIC_CALLBACK(void *) HandleEvent(PLEvent *ev) + NS_IMETHOD Run() { - ProcessPendingQ(((ipcEvent_ProcessPendingQ *) ev)->mTarget); - return nsnull; - } - - PR_STATIC_CALLBACK(void) DestroyEvent(PLEvent *ev) - { - delete (ipcEvent_ProcessPendingQ *) ev; + ProcessPendingQ(mTarget); + return NS_OK; } private: const nsID mTarget; }; +static void +RunEvent(void *arg) +{ + nsIRunnable *ev = NS_STATIC_CAST(nsIRunnable *, arg); + ev->Run(); + NS_RELEASE(ev); +} + static void CallProcessPendingQ(const nsID &target, ipcTargetData *td) { // we assume that we are inside td's monitor - PLEvent *ev = new ipcEvent_ProcessPendingQ(target); + nsIRunnable *ev = new ipcEvent_ProcessPendingQ(target); if (!ev) return; + NS_ADDREF(ev); nsresult rv; - if (td->eventQ) - rv = td->eventQ->PostEvent(ev); - else - rv = IPC_DoCallback((ipcCallbackFunc) PL_HandleEvent, ev); + if (td->thread) + { + rv = td->thread->Dispatch(ev, NS_DISPATCH_NORMAL); + NS_RELEASE(ev); + } + else + { + rv = IPC_DoCallback(RunEvent, ev); + } - if (NS_FAILED(rv)) - PL_DestroyEvent(ev); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "failed to process pending queue"); } /* ------------------------------------------------------------------------- */ @@ -1087,8 +1056,10 @@ IPC_OnMessageAvailable(ipcMessage *msg) case IPCM_MSG_PSH_CLIENT_STATE: { ipcMessageCast status(msg); - PostEventToMainThread(new ipcEvent_ClientState(status->ClientID(), - status->ClientState())); + nsCOMPtr ev = + new ipcEvent_ClientState(status->ClientID(), + status->ClientState()); + NS_DispatchToMainThread(ev); return; } } diff --git a/mozilla/ipc/ipcd/extensions/dconnect/test/TestClient.js b/mozilla/ipc/ipcd/extensions/dconnect/test/TestClient.js index 8403fcdd4ee..646b985d638 100644 --- a/mozilla/ipc/ipcd/extensions/dconnect/test/TestClient.js +++ b/mozilla/ipc/ipcd/extensions/dconnect/test/TestClient.js @@ -43,7 +43,6 @@ const ipcIService = Components.interfaces.ipcIService; const ipcIDConnectService = Components.interfaces.ipcIDConnectService; const nsIFile = Components.interfaces.nsIFile; const nsILocalFile = Components.interfaces.nsILocalFile; -const nsIEventQueueService = Components.interfaces.nsIEventQueueService; // XXX use directory service for this const TEST_PATH = "/tmp"; @@ -92,14 +91,6 @@ function doTest() dump("localObj.equals(file) = " + localObj.equals(file) + "\n"); } -function setupEventQ() -{ - var eqs = Components.classes["@mozilla.org/event-queue-service;1"] - .getService(nsIEventQueueService); - eqs.createMonitoredThreadEventQueue(); -} - -setupEventQ(); findServer(); dump("\n---------------------------------------------------\n"); doTest(); diff --git a/mozilla/ipc/ipcd/extensions/dconnect/test/TestDConnect.cpp b/mozilla/ipc/ipcd/extensions/dconnect/test/TestDConnect.cpp index 8eabe13c60c..4010aa5f5ab 100644 --- a/mozilla/ipc/ipcd/extensions/dconnect/test/TestDConnect.cpp +++ b/mozilla/ipc/ipcd/extensions/dconnect/test/TestDConnect.cpp @@ -39,7 +39,7 @@ #include "ipcIDConnectService.h" #include "ipcCID.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsIServiceManager.h" #include "nsIComponentRegistrar.h" @@ -63,8 +63,6 @@ } \ PR_END_MACRO -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); -static nsIEventQueue* gEventQ = nsnull; static PRBool gKeepRunning = PR_TRUE; static ipcIService *gIpcServ = nsnull; @@ -219,17 +217,6 @@ int main(int argc, char **argv) if (registrar) registrar->AutoRegister(nsnull); - // Create the Event Queue for this thread... - nsCOMPtr eqs = - do_GetService(kEventQueueServiceCID, &rv); - RETURN_IF_FAILED(rv, "do_GetService(EventQueueService)"); - - rv = eqs->CreateMonitoredThreadEventQueue(); - RETURN_IF_FAILED(rv, "CreateMonitoredThreadEventQueue"); - - rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - RETURN_IF_FAILED(rv, "GetThreadEventQueue"); - nsCOMPtr ipcServ(do_GetService(IPC_SERVICE_CONTRACTID, &rv)); RETURN_IF_FAILED(rv, "do_GetService(ipcServ)"); NS_ADDREF(gIpcServ = ipcServ); @@ -244,20 +231,16 @@ int main(int argc, char **argv) gIpcServ->AddName("DConnectServer"); } - PLEvent *ev; + nsCOMPtr thread = do_GetCurrentThread(); while (gKeepRunning) - { - gEventQ->WaitForEvent(&ev); - gEventQ->HandleEvent(ev); - } + NS_ProcessNextEvent(thread); NS_RELEASE(gIpcServ); printf("*** processing remaining events\n"); // process any remaining events - while (NS_SUCCEEDED(gEventQ->GetEvent(&ev)) && ev) - gEventQ->HandleEvent(ev); + NS_ProcessPendingEvents(thread); printf("*** done\n"); } // this scopes the nsCOMPtrs diff --git a/mozilla/ipc/ipcd/extensions/dconnect/test/TestServer.js b/mozilla/ipc/ipcd/extensions/dconnect/test/TestServer.js index a72e133bc9f..56cb8244448 100644 --- a/mozilla/ipc/ipcd/extensions/dconnect/test/TestServer.js +++ b/mozilla/ipc/ipcd/extensions/dconnect/test/TestServer.js @@ -41,9 +41,7 @@ * can connect and control this process. */ -const ipcIService = Components.interfaces.ipcIService; -const nsIEventQueueService = Components.interfaces.nsIEventQueueService; -const nsIEventQueue = Components.interfaces.nsIEventQueue; +const ipcIService = Components.interfaces.ipcIService; function registerServer() { @@ -53,13 +51,13 @@ function registerServer() function runEventQ() { - var eqs = Components.classes["@mozilla.org/event-queue-service;1"] - .getService(nsIEventQueueService); - eqs.createMonitoredThreadEventQueue(); - var queue = eqs.getSpecialEventQueue(eqs.CURRENT_THREAD_EVENT_QUEUE); + var thread = + Components.classes["@mozilla.org/thread-manager;1"]. + getService().currentThread; // this never returns - queue.eventLoop(); + while (true) + thread.processNextEvent(); } registerServer(); diff --git a/mozilla/ipc/ipcd/extensions/lock/test/Makefile.in b/mozilla/ipc/ipcd/extensions/lock/test/Makefile.in index 93d1f48d0e8..4e77914eb0c 100644 --- a/mozilla/ipc/ipcd/extensions/lock/test/Makefile.in +++ b/mozilla/ipc/ipcd/extensions/lock/test/Makefile.in @@ -48,6 +48,7 @@ MOZILLA_INTERNAL_API = 1 REQUIRES = ipcd \ nspr \ xpcom \ + string \ $(NULL) CPPSRCS = \ diff --git a/mozilla/ipc/ipcd/extensions/lock/test/TestIPCLocks.cpp b/mozilla/ipc/ipcd/extensions/lock/test/TestIPCLocks.cpp index 907a1e76dc2..b723e43645b 100644 --- a/mozilla/ipc/ipcd/extensions/lock/test/TestIPCLocks.cpp +++ b/mozilla/ipc/ipcd/extensions/lock/test/TestIPCLocks.cpp @@ -47,7 +47,7 @@ #include "ipcILockService.h" #include "ipcLockCID.h" #include "nsServiceManagerUtils.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsCOMPtr.h" #include "nsXPCOM.h" #include "prproces.h" @@ -144,22 +144,6 @@ static const char *kLockNames[] = { static nsresult DoTest() { - nsresult rv; - - nsCOMPtr eqs = - do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return rv; - - rv = eqs->CreateMonitoredThreadEventQueue(); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr eq; - rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eq)); - if (NS_FAILED(rv)) - return rv; - nsCOMPtr lockService = do_GetService(IPC_LOCKSERVICE_CONTRACTID); diff --git a/mozilla/ipc/ipcd/extensions/transmngr/test/tmModuleTest.cpp b/mozilla/ipc/ipcd/extensions/transmngr/test/tmModuleTest.cpp index 5d1dccd4d65..ab02d158592 100644 --- a/mozilla/ipc/ipcd/extensions/transmngr/test/tmModuleTest.cpp +++ b/mozilla/ipc/ipcd/extensions/transmngr/test/tmModuleTest.cpp @@ -44,7 +44,7 @@ // core & xpcom ns includes #include "nsDebug.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsIServiceManager.h" #include "nsIComponentRegistrar.h" #include "nsString.h" @@ -80,8 +80,6 @@ PRUint32 dataLen = 10; // includes the null terminator for "test data } \ PR_END_MACRO -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); -static nsIEventQueue* gEventQ = nsnull; static PRBool gKeepRunning = PR_TRUE; //static PRInt32 gMsgCount = 0; static ipcIService *gIpcServ = nsnull; @@ -195,16 +193,6 @@ int main(PRInt32 argc, char *argv[]) if (registrar) registrar->AutoRegister(nsnull); - // Create the Event Queue for this thread... - nsCOMPtr eqs = do_GetService(kEventQueueServiceCID, &rv); - RETURN_IF_FAILED(rv, "do_GetService(EventQueueService)"); - - rv = eqs->CreateMonitoredThreadEventQueue(); - RETURN_IF_FAILED(rv, "CreateMonitoredThreadEventQueue"); - - rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - RETURN_IF_FAILED(rv, "GetThreadEventQueue"); - // Need to make sure the ipc system has been started printf("tmModuleTest: getting ipc service\n"); nsCOMPtr ipcServ(do_GetService("@mozilla.org/ipc/service;1", &rv)); @@ -229,6 +217,7 @@ int main(PRInt32 argc, char *argv[]) gTransServ->Attach(nsDependentCString(queueName), observ, PR_TRUE); printf("tmModuleTest: observing queue [%s]\n", queueName); + nsCOMPtr thread = do_GetCurrentThread(); // run specific patterns based on the mode int i = 0; // wasn't working inside the cases @@ -242,7 +231,7 @@ int main(PRInt32 argc, char *argv[]) } // listen for events while (gKeepRunning) - gEventQ->ProcessPendingEvents(); + NS_ProcessNextEvent(thread); printf("tmModuleTest: end standard\n"); break; case 'b': @@ -253,7 +242,7 @@ int main(PRInt32 argc, char *argv[]) } // listen for events while (gKeepRunning) - gEventQ->ProcessPendingEvents(); + NS_ProcessNextEvent(thread); printf("tmModuleTest: end broadcast\n"); break; case 'f': @@ -270,7 +259,7 @@ int main(PRInt32 argc, char *argv[]) } // listen for events while (gKeepRunning) - gEventQ->ProcessPendingEvents(); + NS_ProcessNextEvent(thread); // detach gTransServ->Detach(nsDependentCString(queueName)); printf("tmModuleTest: end flush\n"); @@ -289,7 +278,7 @@ int main(PRInt32 argc, char *argv[]) printf("tmModuleTest: start listener\n"); // listen for events while (gKeepRunning) - gEventQ->ProcessPendingEvents(); + NS_ProcessNextEvent(thread); printf("tmModuleTest: end listener\n"); break; default : @@ -305,9 +294,8 @@ int main(PRInt32 argc, char *argv[]) printf("tmModuleTest: processing remaining events\n"); // process any remaining events - PLEvent *ev; - while (NS_SUCCEEDED(gEventQ->GetEvent(&ev)) && ev) - gEventQ->HandleEvent(ev); + + NS_ProcessPendingEvents(thread); printf("tmModuleTest: done\n"); } // this scopes the nsCOMPtrs diff --git a/mozilla/ipc/ipcd/test/TestIPC.cpp b/mozilla/ipc/ipcd/test/TestIPC.cpp index 1100d674f0e..0e253a5645a 100644 --- a/mozilla/ipc/ipcd/test/TestIPC.cpp +++ b/mozilla/ipc/ipcd/test/TestIPC.cpp @@ -41,7 +41,7 @@ #include "ipcCID.h" #include "ipcLockCID.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsIServiceManager.h" #include "nsIComponentRegistrar.h" @@ -72,8 +72,6 @@ static const nsID kTestTargetID = } \ PR_END_MACRO -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); -static nsIEventQueue* gEventQ = nsnull; static PRBool gKeepRunning = PR_TRUE; static ipcIService *gIpcServ = nsnull; static ipcILockService *gIpcLockServ = nsnull; @@ -201,17 +199,6 @@ int main(int argc, char **argv) if (registrar) registrar->AutoRegister(nsnull); - // Create the Event Queue for this thread... - nsCOMPtr eqs = - do_GetService(kEventQueueServiceCID, &rv); - RETURN_IF_FAILED(rv, "do_GetService(EventQueueService)"); - - rv = eqs->CreateMonitoredThreadEventQueue(); - RETURN_IF_FAILED(rv, "CreateMonitoredThreadEventQueue"); - - rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - RETURN_IF_FAILED(rv, "GetThreadEventQueue"); - printf("*** getting ipc service\n"); nsCOMPtr ipcServ(do_GetService(IPC_SERVICE_CONTRACTID, &rv)); RETURN_IF_FAILED(rv, "do_GetService(ipcServ)"); @@ -313,19 +300,17 @@ int main(int argc, char **argv) rv = gIpcLockServ->AcquireLock("foo", PR_TRUE); printf("*** sync AcquireLock returned [rv=%x]\n", rv); - PLEvent *ev; - while (gKeepRunning) { - gEventQ->WaitForEvent(&ev); - gEventQ->HandleEvent(ev); - } + nsCOMPtr thread = do_GetCurrentThread(); + + while (gKeepRunning) + NS_ProcessNextEvent(thread); NS_RELEASE(gIpcServ); printf("*** processing remaining events\n"); // process any remaining events - while (NS_SUCCEEDED(gEventQ->GetEvent(&ev)) && ev) - gEventQ->HandleEvent(ev); + NS_ProcessPendingEvents(thread); printf("*** done\n"); } // this scopes the nsCOMPtrs diff --git a/mozilla/js/jsd/jsd_xpc.cpp b/mozilla/js/jsd/jsd_xpc.cpp index 9e044ef961b..0dcbaf81f20 100644 --- a/mozilla/js/jsd/jsd_xpc.cpp +++ b/mozilla/js/jsd/jsd_xpc.cpp @@ -50,7 +50,8 @@ #include "nsIObserverService.h" #include "nsICategoryManager.h" #include "nsIJSRuntimeService.h" -#include "nsIEventQueueService.h" +#include "nsIThreadInternal.h" +#include "nsThreadUtils.h" #include "nsMemory.h" #include "jsdebug.h" #include "nsReadableUtils.h" @@ -118,8 +119,6 @@ jsds_GCCallbackProc (JSContext *cx, JSGCStatus status); ******************************************************************************/ const char implementationString[] = "Mozilla JavaScript Debugger Service"; -static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1"; const char jsdARObserverCtrID[] = "@mozilla.org/js/jsd/app-start-observer;2"; @@ -2942,40 +2941,28 @@ jsdService::WrapValue(jsdIValue **_rval) NS_IMETHODIMP jsdService::EnterNestedEventLoop (jsdINestCallback *callback, PRUint32 *_rval) { - nsCOMPtr appShell(do_CreateInstance(kAppShellCID)); - NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE); - nsCOMPtr - eventService(do_GetService(kEventQueueServiceCID)); - NS_ENSURE_TRUE(eventService, NS_ERROR_FAILURE); - - appShell->Create(0, nsnull); - appShell->Spinup(); - + // Nesting event queues is a thing of the past. Now, we just spin the + // current event loop. + nsCOMPtr stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1")); nsresult rv = NS_OK; PRUint32 nestLevel = ++mNestedLoopLevel; - nsCOMPtr eventQ; - if (stack && NS_SUCCEEDED(stack->Push(nsnull)) && - NS_SUCCEEDED(eventService->PushThreadEventQueue(getter_AddRefs(eventQ)))) - { - if (NS_SUCCEEDED(rv) && callback) { + nsCOMPtr thread = do_GetCurrentThread(); + + if (stack && NS_SUCCEEDED(stack->Push(nsnull))) { + if (callback) { Pause(nsnull); rv = callback->OnNest(); UnPause(nsnull); } - while(NS_SUCCEEDED(rv) && mNestedLoopLevel >= nestLevel) - { - void* data; - PRBool isRealEvent; - //PRBool processEvent; - - rv = appShell->GetNativeEvent(isRealEvent, data); - if(NS_SUCCEEDED(rv)) - appShell->DispatchNativeEvent(isRealEvent, data); - } + while (NS_SUCCEEDED(rv) && mNestedLoopLevel >= nestLevel) { + if (!NS_ProcessNextEvent(thread)) + rv = NS_ERROR_UNEXPECTED; + } + JSContext* cx; stack->Pop(&cx); NS_ASSERTION(cx == nsnull, "JSContextStack mismatch"); @@ -2983,9 +2970,6 @@ jsdService::EnterNestedEventLoop (jsdINestCallback *callback, PRUint32 *_rval) else rv = NS_ERROR_FAILURE; - eventService->PopThreadEventQueue(eventQ); - appShell->Spindown(); - NS_ASSERTION (mNestedLoopLevel <= nestLevel, "nested event didn't unwind properly"); if (mNestedLoopLevel == nestLevel) diff --git a/mozilla/js/src/xpconnect/src/nsXPConnect.cpp b/mozilla/js/src/xpconnect/src/nsXPConnect.cpp index 1e161e90c5a..52a83ccd4d2 100644 --- a/mozilla/js/src/xpconnect/src/nsXPConnect.cpp +++ b/mozilla/js/src/xpconnect/src/nsXPConnect.cpp @@ -49,7 +49,6 @@ NS_IMPL_THREADSAFE_ISUPPORTS2(nsXPConnect,nsIXPConnect,nsISupportsWeakReference) nsXPConnect* nsXPConnect::gSelf = nsnull; JSBool nsXPConnect::gOnceAliveNowDead = JS_FALSE; -PRThread* nsXPConnect::gMainThread = nsnull; const char XPC_CONTEXT_STACK_CONTRACTID[] = "@mozilla.org/js/xpc/ContextStack;1"; const char XPC_RUNTIME_CONTRACTID[] = "@mozilla.org/js/xpc/RuntimeService;1"; @@ -326,19 +325,6 @@ nsXPConnect::CreateRuntime() return nsnull != mRuntime; } -// static -PRThread* -nsXPConnect::FindMainThread() -{ - nsCOMPtr t; - nsresult rv; - rv = nsIThread::GetMainThread(getter_AddRefs(t)); - NS_ASSERTION(NS_SUCCEEDED(rv) && t, "bad"); - rv = t->GetPRThread(&gMainThread); - NS_ASSERTION(NS_SUCCEEDED(rv) && gMainThread, "bad"); - return gMainThread; -} - /***************************************************************************/ typedef PRBool (*InfoTester)(nsIInterfaceInfoManager* manager, const void* data, diff --git a/mozilla/js/src/xpconnect/src/xpcjsruntime.cpp b/mozilla/js/src/xpconnect/src/xpcjsruntime.cpp index 32d4f5a6aab..46237e526d8 100644 --- a/mozilla/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/mozilla/js/src/xpconnect/src/xpcjsruntime.cpp @@ -236,8 +236,7 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status) { case JSGC_BEGIN: { - if(self->GetMainThreadOnlyGC() && - PR_GetCurrentThread() != nsXPConnect::GetMainThread()) + if(self->GetMainThreadOnlyGC() && !NS_IsMainThread()) { return JS_FALSE; } diff --git a/mozilla/js/src/xpconnect/src/xpcprivate.h b/mozilla/js/src/xpconnect/src/xpcprivate.h index 7b950b9da6c..ba2881b7048 100644 --- a/mozilla/js/src/xpconnect/src/xpcprivate.h +++ b/mozilla/js/src/xpconnect/src/xpcprivate.h @@ -93,9 +93,8 @@ #include "nsReadableUtils.h" #include "nsXPIDLString.h" -#include "nsIThread.h" +#include "nsThreadUtils.h" #include "nsIJSContextStack.h" -#include "prthread.h" #include "nsDeque.h" #include "nsVoidArray.h" @@ -455,9 +454,6 @@ public: static JSBool IsISupportsDescendant(nsIInterfaceInfo* info); - static PRThread* GetMainThread() - {return gMainThread ? gMainThread : FindMainThread();} - nsIXPCSecurityManager* GetDefaultSecurityManager() const {return mDefaultSecurityManager;} @@ -498,7 +494,6 @@ private: // Singleton instance static nsXPConnect* gSelf; static JSBool gOnceAliveNowDead; - static PRThread* gMainThread; XPCJSRuntime* mRuntime; nsCOMPtr mInterfaceInfoManager; @@ -2099,8 +2094,7 @@ private: #ifdef XPC_CHECK_WRAPPER_THREADSAFETY public: - PRThread* mThread; // Don't want to overload _mOwningThread - static PRThread* gMainThread; + nsCOMPtr mThread; // Don't want to overload _mOwningThread #endif }; diff --git a/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp b/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp index d4995439c27..ffa3e342bcf 100644 --- a/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp @@ -53,10 +53,6 @@ static void DEBUG_CheckClassInfoClaims(XPCWrappedNative* wrapper); #define DEBUG_CheckClassInfoClaims(wrapper) ((void)0) #endif -#ifdef XPC_CHECK_WRAPPER_THREADSAFETY -PRThread* XPCWrappedNative::gMainThread = nsnull; -#endif - #ifdef XPC_TRACK_WRAPPER_STATS static int DEBUG_TotalWrappedNativeCount; static int DEBUG_TotalLiveWrappedNativeCount; @@ -806,12 +802,9 @@ XPCWrappedNative::Init(XPCCallContext& ccx, JSObject* parent, } #ifdef XPC_CHECK_WRAPPER_THREADSAFETY - if(!gMainThread) - gMainThread = nsXPConnect::GetMainThread(); + mThread = do_GetCurrentThread(); - mThread = PR_GetCurrentThread(); - - if(HasProto() && GetProto()->ClassIsMainThreadOnly() && gMainThread != mThread) + if(HasProto() && GetProto()->ClassIsMainThreadOnly() && !NS_IsMainThread()) DEBUG_ReportWrapperThreadSafetyError(ccx, "MainThread only wrapper created on the wrong thread", this); #endif @@ -3099,18 +3092,17 @@ void DEBUG_CheckWrapperThreadSafety(const XPCWrappedNative* wrapper) if(proto && proto->ClassIsThreadSafe()) return; - PRThread* currentThread = PR_GetCurrentThread(); - + PRBool val; if(proto && proto->ClassIsMainThreadOnly()) { - if(currentThread != wrapper->gMainThread) + if(!NS_IsMainThread()) { XPCCallContext ccx(NATIVE_CALLER); DEBUG_ReportWrapperThreadSafetyError(ccx, "Main Thread Only wrapper accessed on another thread", wrapper); } } - else if(currentThread != wrapper->mThread) + else if(NS_SUCCEEDED(wrapper->mThread->IsOnCurrentThread(&val)) && !val) { XPCCallContext ccx(NATIVE_CALLER); DEBUG_ReportWrapperThreadSafetyError(ccx, diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 4ab041b3241..b0c8ee6ce1e 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -122,8 +122,6 @@ #include "nsIObjectLoadingContent.h" #include "nsContentErrors.h" -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - #include "nsIDOMWindowInternal.h" #include "nsIMenuFrame.h" @@ -1939,9 +1937,6 @@ nsCSSFrameConstructor::nsCSSFrameConstructor(nsIDocument *aDocument, // now what? } - // XXXbz this should be in Init() or something! - mEventQueueService = do_GetService(kEventQueueServiceCID); - #ifdef DEBUG static PRBool gFirstTime = PR_TRUE; if (gFirstTime) { @@ -10833,12 +10828,8 @@ nsCSSFrameConstructor::WillDestroyFrameTree() mQuoteList.Clear(); mCounterManager.Clear(); - // Cancel all pending reresolves - mRestyleEventQueue = nsnull; - nsCOMPtr eventQueue; - mEventQueueService->GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs(eventQueue)); - eventQueue->RevokeEvents(this); + // Cancel all pending re-resolves + mRestyleEvent.Revoke(); } //STATIC @@ -13482,7 +13473,7 @@ nsCSSFrameConstructor::PostRestyleEvent(nsIContent* aContent, // Nothing to do here return; } - + RestyleData existingData; existingData.mRestyleHint = nsReStyleHint(0); existingData.mChangeHint = NS_STYLE_HINT_NONE; @@ -13494,64 +13485,40 @@ nsCSSFrameConstructor::PostRestyleEvent(nsIContent* aContent, mPendingRestyles.Put(aContent, existingData); - nsCOMPtr eventQueue; - mEventQueueService->GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs(eventQueue)); - - if (eventQueue != mRestyleEventQueue) { - RestyleEvent* ev = new RestyleEvent(this); - if (NS_FAILED(eventQueue->PostEvent(ev))) { - PL_DestroyEvent(ev); + if (!mRestyleEvent.IsPending()) { + nsRefPtr ev = new RestyleEvent(this); + if (NS_FAILED(NS_DispatchToCurrentThread(ev))) { + NS_WARNING("failed to dispatch restyle event"); // XXXbz and what? } else { - mRestyleEventQueue = eventQueue; + mRestyleEvent = ev; } } } -void nsCSSFrameConstructor::RestyleEvent::HandleEvent() { - nsCSSFrameConstructor* constructor = - NS_STATIC_CAST(nsCSSFrameConstructor*, owner); +NS_IMETHODIMP nsCSSFrameConstructor::RestyleEvent::Run() { + if (!mConstructor) + return NS_OK; // event was revoked + nsIViewManager* viewManager = - constructor->mPresShell->GetViewManager(); + mConstructor->mPresShell->GetViewManager(); NS_ASSERTION(viewManager, "Must have view manager for update"); viewManager->BeginUpdateViewBatch(); // Force flushing of any pending content notifications that might have queued // up while our event was pending. That will ensure that we don't construct // frames for content right now that's still waiting to be notified on, - constructor->mPresShell->GetDocument()-> + mConstructor->mPresShell->GetDocument()-> FlushPendingNotifications(Flush_ContentAndNotify); // Make sure that any restyles that happen from now on will go into // a new event. - constructor->mRestyleEventQueue = nsnull; + mConstructor->mRestyleEvent.Forget(); - constructor->ProcessPendingRestyles(); + mConstructor->ProcessPendingRestyles(); viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); -} -PR_STATIC_CALLBACK(void*) -HandleRestyleEvent(PLEvent* aEvent) -{ - nsCSSFrameConstructor::RestyleEvent* evt = - NS_STATIC_CAST(nsCSSFrameConstructor::RestyleEvent*, aEvent); - evt->HandleEvent(); - return nsnull; -} - -PR_STATIC_CALLBACK(void) -DestroyRestyleEvent(PLEvent* aEvent) -{ - delete NS_STATIC_CAST(nsCSSFrameConstructor::RestyleEvent*, aEvent); -} - -nsCSSFrameConstructor::RestyleEvent::RestyleEvent(nsCSSFrameConstructor* aConstructor) -{ - NS_PRECONDITION(aConstructor, "Must have a constructor!"); - - PL_InitEvent(this, aConstructor, - ::HandleRestyleEvent, ::DestroyRestyleEvent); + return NS_OK; } nsresult diff --git a/mozilla/layout/base/nsCSSFrameConstructor.h b/mozilla/layout/base/nsCSSFrameConstructor.h index e5c6217ea13..00c3d9f114f 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.h +++ b/mozilla/layout/base/nsCSSFrameConstructor.h @@ -50,9 +50,7 @@ #include "nsCounterManager.h" #include "nsDataHashtable.h" #include "nsHashKeys.h" -#include "plevent.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" +#include "nsThreadUtils.h" class nsIDocument; struct nsFrameItems; @@ -83,7 +81,7 @@ class nsCSSFrameConstructor { public: nsCSSFrameConstructor(nsIDocument *aDocument, nsIPresShell* aPresShell); - ~nsCSSFrameConstructor(void) {} + ~nsCSSFrameConstructor(void) { } // Maintain global objects - gXBLService static nsIXBLService * GetXBLService(); @@ -1010,20 +1008,23 @@ public: nsCOMPtr mContent; }; - struct RestyleEvent; - friend struct RestyleEvent; + class RestyleEvent; + friend class RestyleEvent; - struct RestyleEvent : public PLEvent { - RestyleEvent(nsCSSFrameConstructor* aConstructor); - ~RestyleEvent() { } - void HandleEvent(); + class RestyleEvent : public nsRunnable { + public: + NS_DECL_NSIRUNNABLE + RestyleEvent(nsCSSFrameConstructor *aConstructor) + : mConstructor(aConstructor) { + NS_PRECONDITION(aConstructor, "Must have a constructor!"); + } + void Revoke() { mConstructor = nsnull; } + private: + nsCSSFrameConstructor *mConstructor; }; friend class nsFrameConstructorState; -protected: - nsCOMPtr mRestyleEventQueue; - private: #ifdef ACCESSIBILITY // If the frame is visible, return the frame type @@ -1053,9 +1054,9 @@ private: PRPackedBool mQuotesDirty; PRPackedBool mCountersDirty; - nsCOMPtr mTempFrameTreeState; + nsRevocableEventPtr mRestyleEvent; - nsCOMPtr mEventQueueService; + nsCOMPtr mTempFrameTreeState; nsDataHashtable mPendingRestyles; diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp index 3050373b28b..00c7f5129aa 100644 --- a/mozilla/layout/base/nsDocumentViewer.cpp +++ b/mozilla/layout/base/nsDocumentViewer.cpp @@ -117,9 +117,6 @@ #include "nsIClipboardHelper.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" - #include "nsPIDOMWindow.h" #include "nsIFocusController.h" @@ -155,8 +152,6 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printsettings-service;1"; // Printing Events -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" #include "nsPrintPreviewListener.h" #include "nsIDOMHTMLFrameElement.h" diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp index ef08e59daf9..7ae40ecfa4a 100644 --- a/mozilla/layout/base/nsFrameManager.cpp +++ b/mozilla/layout/base/nsFrameManager.cpp @@ -54,7 +54,6 @@ #include "nsCSSFrameConstructor.h" #include "nsStyleContext.h" #include "nsStyleChangeList.h" -#include "nsIEventQueueService.h" #include "nsIServiceManager.h" #include "nsCOMPtr.h" #include "prthread.h" @@ -113,9 +112,6 @@ #define NOISY_TRACE_FRAME(_msg,_frame); #endif -// Class IID's -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - // IID's //---------------------------------------------------------------------- diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index a00d863b8ac..d305c7deee3 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -160,6 +160,7 @@ #include "nsIObjectLoadingContent.h" #include "nsNetUtil.h" #include "nsEventDispatcher.h" +#include "nsThreadUtils.h" // Drag & Drop, Clipboard #include "nsWidgetsCID.h" @@ -167,9 +168,6 @@ #include "nsIClipboardHelper.h" #include "nsIDocShellTreeItem.h" #include "nsIURI.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" -#include "nsEventQueueUtils.h" #include "nsIScrollableFrame.h" #include "prtime.h" #include "prlong.h" @@ -1306,7 +1304,7 @@ protected: void WillDoReflow(); void DidDoReflow(); nsresult ProcessReflowCommands(PRBool aInterruptible); - nsresult ClearReflowEventStatus(); + void ClearReflowEventStatus(); void PostReflowEvent(); // Note: when PR_FALSE is returned, AlreadyInQueue assumes the command will @@ -1314,9 +1312,22 @@ protected: // mReflowCommandTable (AlreadyInQueue will insert it in that table). PRBool AlreadyInQueue(nsHTMLReflowCommand* aReflowCommand); - friend struct ReflowEvent; friend class nsPresShellEventCB; + class ReflowEvent; + friend class ReflowEvent; + + class ReflowEvent : public nsRunnable { + public: + NS_DECL_NSIRUNNABLE + ReflowEvent(PresShell *aPresShell) : mPresShell(aPresShell) { + NS_ASSERTION(aPresShell, "Null parameters!"); + } + void Revoke() { mPresShell = nsnull; } + private: + PresShell *mPresShell; + }; + // Utility to determine if we're in the middle of a drag. PRBool IsDragInProgress ( ) const ; @@ -1383,11 +1394,12 @@ protected: PRInt16 mSelectionFlags; PRPackedBool mBatchReflows; // When set to true, the pres shell batches reflow commands. PresShellViewEventListener *mViewEventListener; - nsCOMPtr mReflowEventQueue; FrameArena mFrameArena; StackArena* mStackArena; nsCOMPtr mDragService; PRInt32 mRCCreatedDuringLoad; // Counter to keep track of reflow commands created during doc + + nsRevocableEventPtr mReflowEvent; // used for list of posted events and attribute changes. To be done // after reflow. @@ -1927,14 +1939,8 @@ PresShell::Destroy() NS_RELEASE(mViewEventListener); } - // Revoke pending events - mReflowEventQueue = nsnull; - nsCOMPtr eventQueue; - nsresult rv = NS_GetCurrentEventQ(getter_AddRefs(eventQueue), - nsContentUtils::EventQueueService()); - if (NS_SUCCEEDED(rv)) { - eventQueue->RevokeEvents(this); - } + // Revoke any pending reflow event + mReflowEvent.Revoke(); CancelAllReflowCommands(); @@ -6354,96 +6360,57 @@ PresShell::Thaw() //-------------- Begin Reflow Event Definition ------------------------ -struct ReflowEvent : public PLEvent { - ReflowEvent(nsIPresShell* aPresShell); - ~ReflowEvent() { } - - void HandleEvent() { - nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (presShell) { +NS_IMETHODIMP +PresShell::ReflowEvent::Run() { + // Take an owning reference to the PresShell during this call to ensure + // that it doesn't get killed off prematurely. + nsRefPtr ps = mPresShell; + if (ps) { #ifdef DEBUG - if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) { - printf("\n*** Handling reflow event: PresShell=%p, event=%p\n", (void*)presShell.get(), (void*)this); - } -#endif - // XXX Statically cast the pres shell pointer so that we can call - // protected methods on the pres shell. (the ReflowEvent struct - // is a friend of the PresShell class) - PresShell* ps = NS_REINTERPRET_CAST(PresShell*, presShell.get()); - PRBool isBatching; - ps->ClearReflowEventStatus(); - ps->GetReflowBatchingStatus(&isBatching); - if (!isBatching) { - // Set a kung fu death grip on the view manager associated with the pres shell - // before processing that pres shell's reflow commands. Fixes bug 54868. - nsCOMPtr viewManager = presShell->GetViewManager(); - - viewManager->BeginUpdateViewBatch(); - ps->ProcessReflowCommands(PR_TRUE); - viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); - - // Now, explicitly release the pres shell before the view manager - presShell = nsnull; - viewManager = nsnull; - } + if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) { + printf("\n*** Handling reflow event: PresShell=%p, event=%p\n", (void*)ps, (void*)this); + } +#endif + // NOTE: the ReflowEvent class is a friend of the PresShell class + PRBool isBatching; + ps->ClearReflowEventStatus(); + ps->GetReflowBatchingStatus(&isBatching); + if (!isBatching) { + // Set a kung fu death grip on the view manager associated with the pres shell + // before processing that pres shell's reflow commands. Fixes bug 54868. + nsCOMPtr viewManager = ps->GetViewManager(); + + viewManager->BeginUpdateViewBatch(); + ps->ProcessReflowCommands(PR_TRUE); + viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); + + // Now, explicitly release the pres shell before the view manager + ps = nsnull; + viewManager = nsnull; } - else - mPresShell = 0; } - - nsWeakPtr mPresShell; -}; - -static void* PR_CALLBACK HandlePLEvent(PLEvent* aEvent) -{ - ReflowEvent* event = NS_STATIC_CAST(ReflowEvent*, aEvent); - event->HandleEvent(); - return nsnull; -} - -static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent) -{ - ReflowEvent* event = NS_STATIC_CAST(ReflowEvent*, aEvent); - delete event; -} - - -ReflowEvent::ReflowEvent(nsIPresShell* aPresShell) -{ - NS_ASSERTION(aPresShell, "Null parameters!"); - - mPresShell = do_GetWeakReference(aPresShell); - - PL_InitEvent(this, aPresShell, ::HandlePLEvent, ::DestroyPLEvent); + return NS_OK; } //-------------- End Reflow Event Definition --------------------------- - void PresShell::PostReflowEvent() { - nsCOMPtr eventQueue; - nsContentUtils::EventQueueService()-> - GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs(eventQueue)); + if (mReflowEvent.IsPending() || mIsDestroying || mIsReflowing || + mReflowCommands.Count() == 0) + return; - if (eventQueue != mReflowEventQueue && !mIsDestroying && - !mIsReflowing && mReflowCommands.Count() > 0) { - ReflowEvent* ev = new ReflowEvent(NS_STATIC_CAST(nsIPresShell*, this)); - // OOM note: both PostEvent and PL_DestroyEvent accept a null arg. - if (NS_FAILED(eventQueue->PostEvent(ev))) { - NS_ERROR("failed to post reflow event"); - PL_DestroyEvent(ev); - } - else { - mReflowEventQueue = eventQueue; + nsRefPtr ev = new ReflowEvent(this); + if (NS_FAILED(NS_DispatchToCurrentThread(ev))) { + NS_WARNING("failed to dispatch reflow event"); + } else { + mReflowEvent = ev; #ifdef DEBUG - if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) { - printf("\n*** PresShell::PostReflowEvent(), this=%p, event=%p\n", (void*)this, (void*)ev); - } -#endif + if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) { + printf("\n*** PresShell::PostReflowEvent(), this=%p, event=%p\n", (void*)this, (void*)ev); } +#endif } } @@ -6642,11 +6609,10 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible) return NS_OK; } -nsresult +void PresShell::ClearReflowEventStatus() { - mReflowEventQueue = nsnull; - return NS_OK; + mReflowEvent.Forget(); } nsresult diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index 3f3432888c3..b9d3c84adb2 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -98,45 +98,12 @@ #include "nsIFontMetrics.h" #endif -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - -class RedisplayTextEvent : public PLEvent +NS_IMETHODIMP +nsComboboxControlFrame::RedisplayTextEvent::Run() { -public: - RedisplayTextEvent(nsComboboxControlFrame* aComboboxControlFrame); - - void HandleEvent() - { - NS_STATIC_CAST(nsComboboxControlFrame*, owner) -> - HandleRedisplayTextEvent(); - } -}; - -PR_STATIC_CALLBACK(void*) -HandleRedisplayTextPLEvent(PLEvent* aEvent) -{ - NS_ASSERTION(nsnull != aEvent, "Event is null"); - RedisplayTextEvent* event = NS_STATIC_CAST(RedisplayTextEvent*, aEvent); - - event->HandleEvent(); - - return nsnull; -} - -PR_STATIC_CALLBACK(void) -DestroyRedisplayTextPLEvent(PLEvent* aEvent) -{ - NS_ASSERTION(nsnull != aEvent, "Event is null"); - RedisplayTextEvent* event = NS_STATIC_CAST(RedisplayTextEvent*, aEvent); - - delete event; -} - -RedisplayTextEvent::RedisplayTextEvent(nsComboboxControlFrame* aComboboxControlFrame) -{ - PL_InitEvent(this, aComboboxControlFrame, - ::HandleRedisplayTextPLEvent, - ::DestroyRedisplayTextPLEvent); + if (mControlFrame) + mControlFrame->HandleRedisplayTextEvent(); + return NS_OK; } class nsPresState; @@ -339,7 +306,6 @@ nsComboboxControlFrame::nsComboboxControlFrame(nsStyleContext* aContext) mItemDisplayWidth = 0; mInRedisplayText = PR_FALSE; - mRedisplayTextEventPosted = PR_FALSE; mRecentSelectedIndex = -1; @@ -1592,31 +1558,15 @@ nsComboboxControlFrame::RedisplayText(PRInt32 aIndex) // Don't call ActuallyDisplayText(PR_TRUE) directly here since that // could cause recursive frame construction. See bug 283117 and the comment in // HandleRedisplayTextEvent() below. - nsCOMPtr eventQueue; - rv = nsContentUtils::EventQueueService()-> - GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs(eventQueue)); - if (eventQueue) { - RedisplayTextEvent* event = new RedisplayTextEvent(this); - if (event) { - // Revoke outstanding events to avoid out-of-order events which could mean - // displaying the wrong text. - if (mRedisplayTextEventPosted) { - eventQueue->RevokeEvents(this); - mRedisplayTextEventPosted = PR_FALSE; - } - rv = eventQueue->PostEvent(event); + // Revoke outstanding events to avoid out-of-order events which could mean + // displaying the wrong text. + mRedisplayTextEvent.Revoke(); - if (NS_SUCCEEDED(rv)) { - mRedisplayTextEventPosted = PR_TRUE; - } else { - PL_DestroyEvent(event); - } - } else { - rv = NS_ERROR_OUT_OF_MEMORY; - } - } + nsRefPtr event = new RedisplayTextEvent(this); + rv = NS_DispatchToCurrentThread(event); + if (NS_SUCCEEDED(rv)) + mRedisplayTextEvent = event; } return rv; } @@ -1638,7 +1588,7 @@ nsComboboxControlFrame::HandleRedisplayTextEvent() // into the correct parent (mDisplayFrame). See bug 282607. NS_PRECONDITION(!mInRedisplayText, "Nested RedisplayText"); mInRedisplayText = PR_TRUE; - mRedisplayTextEventPosted = PR_FALSE; + mRedisplayTextEvent.Forget(); ActuallyDisplayText(PR_TRUE); mDisplayFrame->AddStateBits(NS_FRAME_IS_DIRTY); @@ -1941,14 +1891,8 @@ nsComboboxControlFrame::CreateFrameFor(nsPresContext* aPresContext, void nsComboboxControlFrame::Destroy() { - // Revoke queued RedisplayTextEvents - nsCOMPtr eventQueue; - nsContentUtils::EventQueueService()-> - GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs(eventQueue)); - if (eventQueue) { - eventQueue->RevokeEvents(this); - } + // Revoke any pending RedisplayTextEvent + mRedisplayTextEvent.Revoke(); nsFormControlFrame::RegUnRegAccessKey(NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); diff --git a/mozilla/layout/forms/nsComboboxControlFrame.h b/mozilla/layout/forms/nsComboboxControlFrame.h index a129a877ceb..11e4117662a 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.h +++ b/mozilla/layout/forms/nsComboboxControlFrame.h @@ -64,6 +64,7 @@ #include "nsIScrollableViewProvider.h" #include "nsIStatefulFrame.h" #include "nsIDOMMouseListener.h" +#include "nsThreadUtils.h" class nsIView; class nsStyleContext; @@ -87,7 +88,6 @@ class nsComboboxControlFrame : public nsAreaFrame, { public: friend nsIFrame* NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags); - friend class RedisplayTextEvent; nsComboboxControlFrame(nsStyleContext* aContext); ~nsComboboxControlFrame(); @@ -205,6 +205,18 @@ public: nsRect aAbsoluteTwipsRect, nsRect aAbsolutePixelRect); protected: + class RedisplayTextEvent; + friend class RedisplayTextEvent; + + class RedisplayTextEvent : public nsRunnable { + public: + NS_DECL_NSIRUNNABLE + RedisplayTextEvent(nsComboboxControlFrame *c) : mControlFrame(c) {} + void Revoke() { mControlFrame = nsnull; } + private: + nsComboboxControlFrame *mControlFrame; + }; + void ShowPopup(PRBool aShowPopup); void ShowList(nsPresContext* aPresContext, PRBool aShowList); void SetButtonFrameSize(const nsSize& aSize); @@ -249,7 +261,8 @@ protected: PRPackedBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down PRPackedBool mInRedisplayText; - PRPackedBool mRedisplayTextEventPosted; + + nsRevocableEventPtr mRedisplayTextEvent; PRInt32 mRecentSelectedIndex; PRInt32 mDisplayedIndex; diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp index fc74c32aaf9..0e8b2d2986a 100644 --- a/mozilla/layout/generic/nsFrame.cpp +++ b/mozilla/layout/generic/nsFrame.cpp @@ -1485,10 +1485,9 @@ nsFrame::FireDOMEvent(const nsAString& aDOMEventName, nsIContent *aContent) nsCOMPtr domNode = do_QueryInterface(aContent ? aContent : mContent); if (domNode) { - nsPLDOMEvent *event = new nsPLDOMEvent(domNode, aDOMEventName); - if (event && NS_FAILED(event->PostDOMEvent())) { - PL_DestroyEvent(event); - } + nsRefPtr event = new nsPLDOMEvent(domNode, aDOMEventName); + if (!event || NS_FAILED(event->PostDOMEvent())) + NS_WARNING("Failed to dispatch nsPLDOMEvent"); } } diff --git a/mozilla/layout/generic/nsGfxScrollFrame.cpp b/mozilla/layout/generic/nsGfxScrollFrame.cpp index 8c6c772ede0..c4af84d6a9f 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.cpp +++ b/mozilla/layout/generic/nsGfxScrollFrame.cpp @@ -74,7 +74,6 @@ #include "nsContentCreatorFunctions.h" #include "nsISupportsPrimitives.h" #include "nsIPresShell.h" -#include "nsIEventQueueService.h" #include "nsReflowPath.h" #include "nsAutoPtr.h" #include "nsPresState.h" @@ -88,8 +87,6 @@ #include "nsDisplayList.h" #include "nsBidiUtils.h" -static const char kEventQueueServiceCID[] = NS_EVENTQUEUESERVICE_CONTRACTID; - //---------------------------------------------------------------------- //----------nsHTMLScrollFrame------------------------------------------- @@ -1310,14 +1307,11 @@ nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsContainerFrame* aOuter, nsGfxScrollFrameInner::~nsGfxScrollFrameInner() { - if (mScrollEventQueue) { - mScrollEventQueue->RevokeEvents(this); - } } NS_IMETHODIMP_(nsrefcnt) nsGfxScrollFrameInner::AddRef(void) { - return 1; + return 2; } NS_IMETHODIMP_(nsrefcnt) nsGfxScrollFrameInner::Release(void) @@ -1811,24 +1805,19 @@ void nsGfxScrollFrameInner::CurPosAttributeChanged(nsIContent* aContent) } /* ============= Scroll events ========== */ -PR_STATIC_CALLBACK(void*) HandleScrollEvent(PLEvent* aEvent) -{ - NS_ASSERTION(nsnull != aEvent,"Event is null"); - nsGfxScrollFrameInner* inner = NS_STATIC_CAST(nsGfxScrollFrameInner*, aEvent->owner); - inner->FireScrollEvent(); - return nsnull; -} -PR_STATIC_CALLBACK(void) DestroyScrollEvent(PLEvent* aEvent) +NS_IMETHODIMP +nsGfxScrollFrameInner::ScrollEvent::Run() { - NS_ASSERTION(nsnull != aEvent,"Event is null"); - delete aEvent; + if (mInner) + mInner->FireScrollEvent(); + return NS_OK; } void nsGfxScrollFrameInner::FireScrollEvent() { - mScrollEventQueue = nsnull; + mScrollEvent.Forget(); nsScrollbarEvent event(PR_TRUE, NS_SCROLL_EVENT, nsnull); nsEventStatus status = nsEventStatus_eIgnore; @@ -1852,26 +1841,15 @@ nsGfxScrollFrameInner::FireScrollEvent() void nsGfxScrollFrameInner::PostScrollEvent() { - nsCOMPtr service = do_GetService(kEventQueueServiceCID); - NS_ASSERTION(service, "No event service"); - nsCOMPtr eventQueue; - service->GetSpecialEventQueue( - nsIEventQueueService::UI_THREAD_EVENT_QUEUE, getter_AddRefs(eventQueue)); - NS_ASSERTION(eventQueue, "Event queue is null"); - - if (eventQueue == mScrollEventQueue) + if (mScrollEvent.IsPending()) return; - - PLEvent* ev = new PLEvent; - if (!ev) - return; - PL_InitEvent(ev, this, ::HandleScrollEvent, ::DestroyScrollEvent); - if (mScrollEventQueue) { - mScrollEventQueue->RevokeEvents(this); + nsRefPtr ev = new ScrollEvent(this); + if (NS_FAILED(NS_DispatchToCurrentThread(ev))) { + NS_WARNING("failed to dispatch ScrollEvent"); + } else { + mScrollEvent = ev; } - eventQueue->PostEvent(ev); - mScrollEventQueue = eventQueue; } PRBool diff --git a/mozilla/layout/generic/nsGfxScrollFrame.h b/mozilla/layout/generic/nsGfxScrollFrame.h index ea0ceaeb057..972e1f35b8a 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.h +++ b/mozilla/layout/generic/nsGfxScrollFrame.h @@ -47,7 +47,7 @@ #include "nsIScrollPositionListener.h" #include "nsIStatefulFrame.h" #include "nsGUIEvent.h" -#include "nsIEventQueue.h" +#include "nsThreadUtils.h" #include "nsIScrollableView.h" class nsISupportsArray; @@ -98,6 +98,15 @@ public: void PostScrollEvent(); void FireScrollEvent(); + class ScrollEvent : public nsRunnable { + public: + NS_DECL_NSIRUNNABLE + ScrollEvent(nsGfxScrollFrameInner *inner) : mInner(inner) {} + void Revoke() { mInner = nsnull; } + private: + nsGfxScrollFrameInner *mInner; + }; + void SetScrollbarEnabled(nsIBox* aBox, nscoord aMaxPos, PRBool aReflow=PR_TRUE); PRBool SetCoordAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize, PRBool aReflow=PR_TRUE); nscoord GetCoordAttribute(nsIBox* aFrame, nsIAtom* atom, nscoord defaultValue); @@ -149,7 +158,7 @@ public: const nsRect& aOldScrollArea, const nsRect& aScrollArea); - nsCOMPtr mScrollEventQueue; + nsRevocableEventPtr mScrollEvent; nsIScrollableView* mScrollableView; nsIBox* mHScrollbarBox; nsIBox* mVScrollbarBox; diff --git a/mozilla/layout/generic/nsImageFrame.cpp b/mozilla/layout/generic/nsImageFrame.cpp index 2d1a917cf55..7daa74564cf 100644 --- a/mozilla/layout/generic/nsImageFrame.cpp +++ b/mozilla/layout/generic/nsImageFrame.cpp @@ -91,9 +91,6 @@ #include "imgIContainer.h" #include "imgILoader.h" -#include "nsIEventQueueService.h" -#include "plevent.h" - #include "nsContentPolicyUtils.h" #include "nsCSSFrameConstructor.h" #include "nsIPrefBranch2.h" diff --git a/mozilla/layout/generic/nsObjectFrame.h b/mozilla/layout/generic/nsObjectFrame.h index a2f3cf00435..2b1d82efd61 100644 --- a/mozilla/layout/generic/nsObjectFrame.h +++ b/mozilla/layout/generic/nsObjectFrame.h @@ -40,6 +40,10 @@ #ifndef nsObjectFrame_h___ #define nsObjectFrame_h___ +#ifdef XP_WIN +#include +#endif + #include "nsIObjectFrame.h" #include "nsFrame.h" diff --git a/mozilla/layout/generic/nsSelection.cpp b/mozilla/layout/generic/nsSelection.cpp index 993fa61479d..19bf635bd92 100644 --- a/mozilla/layout/generic/nsSelection.cpp +++ b/mozilla/layout/generic/nsSelection.cpp @@ -83,6 +83,7 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID); #include "nsIDOMText.h" #include "nsContentUtils.h" +#include "nsThreadUtils.h" //included for desired x position; #include "nsPresContext.h" @@ -96,8 +97,6 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID); #include "nsIDeviceContext.h" #include "nsITimer.h" #include "nsIServiceManager.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" // notifications #include "nsIDOMDocument.h" @@ -145,7 +144,6 @@ static NS_DEFINE_IID(kCSubtreeIteratorCID, NS_SUBTREEITERATOR_CID); class nsSelectionIterator; class nsFrameSelection; class nsAutoScrollTimer; -struct nsScrollSelectionIntoViewEvent; PRBool IsValidSelectionPoint(nsFrameSelection *aFrameSel, nsIContent *aContent); PRBool IsValidSelectionPoint(nsFrameSelection *aFrameSel, nsIDOMNode *aDomNode); @@ -262,8 +260,24 @@ public: private: friend class nsSelectionIterator; - friend struct nsScrollSelectionIntoViewEvent; + class ScrollSelectionIntoViewEvent; + friend class ScrollSelectionIntoViewEvent; + + class ScrollSelectionIntoViewEvent : public nsRunnable { + public: + NS_DECL_NSIRUNNABLE + ScrollSelectionIntoViewEvent(nsTypedSelection *aTypedSelection, + SelectionRegion aRegion) + : mTypedSelection(aTypedSelection), + mRegion(aRegion) { + NS_ASSERTION(aTypedSelection, "null parameter"); + } + void Revoke() { mTypedSelection = nsnull; } + private: + nsTypedSelection *mTypedSelection; + SelectionRegion mRegion; + }; void setAnchorFocusRange(PRInt32 aIndex); //pass in index into FrameSelection NS_IMETHOD selectFrames(nsPresContext* aPresContext, nsIContentIterator *aInnerIter, nsIContent *aContent, nsIDOMRange *aRange, nsIPresShell *aPresShell, PRBool aFlags); @@ -287,9 +301,8 @@ private: SelectionType mType;//type of this nsTypedSelection; nsAutoScrollTimer *mAutoScrollTimer; // timer for autoscrolling. nsCOMArray mSelectionListeners; - PRBool mTrueDirection; - nsCOMPtr mEventQueue; - PRBool mScrollEventPosted; + PRPackedBool mTrueDirection; + nsRevocableEventPtr mScrollEvent; CachedOffsetForFrame *mCachedOffsetForFrame; }; @@ -3879,7 +3892,6 @@ nsTypedSelection::nsTypedSelection(nsFrameSelection *aList) mFixupState = PR_FALSE; mDirection = eDirNext; mAutoScrollTimer = nsnull; - mScrollEventPosted = PR_FALSE; mCachedOffsetForFrame = nsnull; } @@ -3890,7 +3902,6 @@ nsTypedSelection::nsTypedSelection() mFixupState = PR_FALSE; mDirection = eDirNext; mAutoScrollTimer = nsnull; - mScrollEventPosted = PR_FALSE; mCachedOffsetForFrame = nsnull; } @@ -3909,10 +3920,7 @@ void nsTypedSelection::DetachFromPresentation() { NS_RELEASE(mAutoScrollTimer); } - if (mEventQueue && mScrollEventPosted) { - mEventQueue->RevokeEvents(this); - mScrollEventPosted = PR_FALSE; - } + mScrollEvent.Revoke(); if (mCachedOffsetForFrame) { delete mCachedOffsetForFrame; @@ -6670,88 +6678,33 @@ nsTypedSelection::ScrollRectIntoView(nsIScrollableView *aScrollableView, return rv; } -static void* PR_CALLBACK HandlePLEvent(PLEvent* aEvent); -static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent); - -struct nsScrollSelectionIntoViewEvent : public PLEvent { - nsScrollSelectionIntoViewEvent(nsTypedSelection *aTypedSelection, SelectionRegion aRegion) { - if (!aTypedSelection) - return; - - mTypedSelection = aTypedSelection; - mRegion = aRegion; - - PL_InitEvent(this, aTypedSelection, ::HandlePLEvent, ::DestroyPLEvent); - } - - ~nsScrollSelectionIntoViewEvent() {} - - void HandleEvent() { - mTypedSelection->mScrollEventPosted = PR_FALSE; - - if (!mTypedSelection) - return; - - mTypedSelection->ScrollIntoView(mRegion, PR_TRUE); - } - - nsTypedSelection *mTypedSelection; - SelectionRegion mRegion; -}; - -static void* PR_CALLBACK HandlePLEvent(PLEvent* aEvent) +NS_IMETHODIMP +nsTypedSelection::ScrollSelectionIntoViewEvent::Run() { - nsScrollSelectionIntoViewEvent* event = - NS_STATIC_CAST(nsScrollSelectionIntoViewEvent*, aEvent); - NS_ASSERTION(nsnull != event,"Event is null"); - event->HandleEvent(); - return nsnull; -} + if (!mTypedSelection) + return NS_OK; // event revoked -static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent) -{ - nsScrollSelectionIntoViewEvent* event = - NS_STATIC_CAST(nsScrollSelectionIntoViewEvent*, aEvent); - NS_ASSERTION(nsnull != event,"Event is null"); - delete event; + mTypedSelection->mScrollEvent.Forget(); + mTypedSelection->ScrollIntoView(mRegion, PR_TRUE); + return NS_OK; } nsresult nsTypedSelection::PostScrollSelectionIntoViewEvent(SelectionRegion aRegion) { - static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); + // If we've already posted an event, revoke it and place a new one at the + // end of the queue to make sure that any new pending reflow events are + // processed before we scroll. This will insure that we scroll to the + // correct place on screen. + mScrollEvent.Revoke(); - if (!mEventQueue) { - nsresult rv; + nsRefPtr ev = + new ScrollSelectionIntoViewEvent(this, aRegion); + nsresult rv = NS_DispatchToCurrentThread(ev); + NS_ENSURE_SUCCESS(rv, rv); - // Cache the event queue of the current UI thread - nsCOMPtr eventService = do_GetService(kEventQueueServiceCID, &rv); - if (NS_SUCCEEDED(rv) && (nsnull != eventService)) { // XXX this implies that the UI is the current thread. - rv = eventService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mEventQueue)); - } - } - - if (mEventQueue) { - if (mScrollEventPosted) { - // We've already posted an event, revoke it and - // place a new one at the end of the queue to make - // sure that any new pending reflow events are processed - // before we scroll. This will insure that we scroll - // to the correct place on screen. - - mEventQueue->RevokeEvents(this); - mScrollEventPosted = PR_FALSE; - } - - nsScrollSelectionIntoViewEvent *ev = new nsScrollSelectionIntoViewEvent(this, aRegion); - if (ev) { - mEventQueue->PostEvent(ev); - mScrollEventPosted = PR_TRUE; - return NS_OK; - } - } - - return NS_ERROR_FAILURE; + mScrollEvent = ev; + return NS_OK; } NS_IMETHODIMP diff --git a/mozilla/layout/printing/nsPrintEngine.cpp b/mozilla/layout/printing/nsPrintEngine.cpp index 355e06c4014..7d4f6bde08f 100644 --- a/mozilla/layout/printing/nsPrintEngine.cpp +++ b/mozilla/layout/printing/nsPrintEngine.cpp @@ -64,10 +64,8 @@ static const char sPrintSettingsServiceContractID[] = "@mozilla.org/gfx/printset static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printsettings-service;1"; // Printing Events -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" -#include "nsEventQueueUtils.h" #include "nsPrintPreviewListener.h" +#include "nsThreadUtils.h" // Printing #include "nsIWebBrowserPrint.h" @@ -162,9 +160,6 @@ static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingpro #include "nsIContentViewerContainer.h" #include "nsIContentViewer.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" - #include "nsPIDOMWindow.h" #include "nsIFocusController.h" @@ -3731,66 +3726,30 @@ nsPrintEngine::Observe(nsISupports *aSubject, const char *aTopic, const PRUnicha //--------------------------------------------------------------- //-- PLEvent Notification //--------------------------------------------------------------- -PR_STATIC_CALLBACK(void*) HandlePLEvent(PLEvent* aEvent) -{ - nsIDocumentViewerPrint *docViewerPrint = (nsIDocumentViewerPrint*)PL_GetEventOwner(aEvent); - - NS_ASSERTION(docViewerPrint, "The event owner is null."); - if (docViewerPrint) { - docViewerPrint->OnDonePrinting(); +class nsPrintCompletionEvent : public nsRunnable { +public: + nsPrintCompletionEvent(nsIDocumentViewerPrint *docViewerPrint) + : mDocViewerPrint(docViewerPrint) { + NS_ASSERTION(mDocViewerPrint, "mDocViewerPrint is null."); } - return nsnull; -} + NS_IMETHOD Run() { + if (mDocViewerPrint) + mDocViewerPrint->OnDonePrinting(); + return NS_OK; + } -//------------------------------------------------------------------------ -PR_STATIC_CALLBACK(void) DestroyPLEvent(PLEvent* aEvent) -{ - nsIDocumentViewerPrint *docViewerPrint = (nsIDocumentViewerPrint*)PL_GetEventOwner(aEvent); - NS_IF_RELEASE(docViewerPrint); +private: + nsCOMPtr mDocViewerPrint; +}; - delete aEvent; -} //----------------------------------------------------------- void nsPrintEngine::FirePrintCompletionEvent() { - static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - - nsCOMPtr event_service = do_GetService(kEventQueueServiceCID); - - if (!event_service) - { - NS_WARNING("Failed to get event queue service"); - return; - } - - nsCOMPtr event_queue; - - event_service->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(event_queue)); - - if (!event_queue) - { - NS_WARNING("Failed to get event queue from service"); - return; - } - - PLEvent *event = new PLEvent; - - if (!event) - { - NS_WARNING("Out of memory?"); - return; - } - - PL_InitEvent(event, mDocViewerPrint, ::HandlePLEvent, ::DestroyPLEvent); - - // The event owns the docviewer pointer now. - NS_ADDREF(mDocViewerPrint); - - event_queue->PostEvent(event); - return; + nsCOMPtr event = new nsPrintCompletionEvent(mDocViewerPrint); + if (NS_FAILED(NS_DispatchToCurrentThread(event))) + NS_WARNING("failed to dispatch print completion event"); } //--------------------------------------------------------------- diff --git a/mozilla/layout/style/nsCSSLoader.cpp b/mozilla/layout/style/nsCSSLoader.cpp index 650609c69a4..44044f2267c 100644 --- a/mozilla/layout/style/nsCSSLoader.cpp +++ b/mozilla/layout/style/nsCSSLoader.cpp @@ -77,9 +77,7 @@ #include "nsICSSLoader.h" #include "nsICSSParser.h" #include "nsICSSImportRule.h" -#include "plevent.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsHTMLAtoms.h" #ifdef MOZ_XUL @@ -141,7 +139,7 @@ static const char* const gStateStrings[] = { /******************************** * SheetLoadData implementation * ********************************/ -NS_IMPL_ISUPPORTS1(SheetLoadData, nsIUnicharStreamLoaderObserver) +NS_IMPL_ISUPPORTS2(SheetLoadData, nsIUnicharStreamLoaderObserver, nsIRunnable) SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader, const nsSubstring& aTitle, @@ -241,6 +239,14 @@ SheetLoadData::~SheetLoadData() NS_IF_RELEASE(mNext); } +NS_IMETHODIMP +SheetLoadData::Run() +{ + mLoader->HandleLoadEvent(this); + mLoader->DestroyLoadEvent(this); + return NS_OK; +} + /************************* * Loader Implementation * *************************/ @@ -1924,26 +1930,6 @@ CSSLoaderImpl::InternalLoadNonDocumentSheet(nsIURI* aURL, return rv; } -PR_BEGIN_EXTERN_C -PR_STATIC_CALLBACK(void*) HandleStyleSheetLoadedEvent(PLEvent* aEvent); -PR_STATIC_CALLBACK(void) DestroyStyleSheetLoadedEvent(PLEvent* aEvent); -PR_END_EXTERN_C - -PR_STATIC_CALLBACK(void*) -HandleStyleSheetLoadedEvent(PLEvent* aEvent) -{ - SheetLoadData* data = NS_STATIC_CAST(SheetLoadData*, aEvent); - data->mLoader->HandleLoadEvent(data); - return nsnull; -} - -PR_STATIC_CALLBACK(void) -DestroyStyleSheetLoadedEvent(PLEvent* aEvent) -{ - SheetLoadData* data = NS_STATIC_CAST(SheetLoadData*, aEvent); - data->mLoader->DestroyLoadEvent(data); -} - nsresult CSSLoaderImpl::PostLoadEvent(nsIURI* aURI, nsICSSStyleSheet* aSheet, @@ -1957,13 +1943,7 @@ CSSLoaderImpl::PostLoadEvent(nsIURI* aURI, // observer, since we may need to unblock the parser // NS_PRECONDITION(aObserver, "Must have observer"); - nsCOMPtr eventQ; - nsresult rv = nsContentUtils::EventQueueService()-> - GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs(eventQ)); - NS_ENSURE_TRUE(eventQ, rv); - - SheetLoadData* evt = + SheetLoadData *evt = new SheetLoadData(this, EmptyString(), // title doesn't matter here aParserToUnblock, aURI, @@ -1974,9 +1954,11 @@ CSSLoaderImpl::PostLoadEvent(nsIURI* aURI, NS_ENSURE_TRUE(evt, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(evt); - - PL_InitEvent(evt, this, ::HandleStyleSheetLoadedEvent, - ::DestroyStyleSheetLoadedEvent); + + if (!mPostedEvents.AppendElement(evt)) { + NS_RELEASE(evt); + return NS_ERROR_OUT_OF_MEMORY; + } // We'll unblock onload when we destroy the event, so make sure to block it // now. We unblock from destruction, not firing, just in case events get @@ -1984,15 +1966,11 @@ CSSLoaderImpl::PostLoadEvent(nsIURI* aURI, if (mDocument) { mDocument->BlockOnload(); } - - if (!mPostedEvents.AppendElement(evt)) { - PL_DestroyEvent(evt); - return NS_ERROR_OUT_OF_MEMORY; - } - rv = eventQ->PostEvent(evt); + nsresult rv = NS_DispatchToCurrentThread(evt); if (NS_FAILED(rv)) { - PL_DestroyEvent(evt); + NS_WARNING("failed to dispatch stylesheet load event"); + DestroyLoadEvent(evt); } else { // We want to notify the observer for this data. We didn't want to set // this earlier, since we would have returned an error _and_ notified. diff --git a/mozilla/layout/style/nsCSSLoader.h b/mozilla/layout/style/nsCSSLoader.h index 75b95932b25..f721e7d474f 100644 --- a/mozilla/layout/style/nsCSSLoader.h +++ b/mozilla/layout/style/nsCSSLoader.h @@ -62,6 +62,7 @@ class nsICSSImportRule; class nsMediaList; #include "nsICSSLoader.h" +#include "nsIRunnable.h" #include "nsIUnicharStreamLoader.h" #include "nsCOMPtr.h" #include "nsCOMArray.h" @@ -69,7 +70,6 @@ class nsMediaList; #include "nsURIHashKey.h" #include "nsInterfaceHashtable.h" #include "nsDataHashtable.h" -#include "plevent.h" /** * OVERALL ARCHITECTURE @@ -103,7 +103,7 @@ class nsMediaList; * Data needed to properly load a stylesheet * *********************************************/ -class SheetLoadData : public PLEvent, +class SheetLoadData : public nsIRunnable, public nsIUnicharStreamLoaderObserver { public: @@ -135,6 +135,7 @@ public: already_AddRefed GetReferrerURI(); NS_DECL_ISUPPORTS + NS_DECL_NSIRUNNABLE NS_DECL_NSIUNICHARSTREAMLOADEROBSERVER // Hold a ref to the CSSLoader so we can call back to it to let it diff --git a/mozilla/layout/xul/base/src/nsImageBoxFrame.cpp b/mozilla/layout/xul/base/src/nsImageBoxFrame.cpp index 7fa18677dc0..81e1aade6b1 100644 --- a/mozilla/layout/xul/base/src/nsImageBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsImageBoxFrame.cpp @@ -83,13 +83,13 @@ #include "nsIDOMHTMLMapElement.h" #include "nsBoxLayoutState.h" #include "nsIDOMDocument.h" -#include "nsIEventQueueService.h" #include "nsTransform2D.h" #include "nsITheme.h" #include "nsIServiceManager.h" #include "nsIURI.h" #include "nsNetUtil.h" +#include "nsThreadUtils.h" #include "nsGUIEvent.h" #include "nsEventDispatcher.h" #include "nsDisplayList.h" @@ -98,73 +98,46 @@ #define ONLOAD_CALLED_TOO_EARLY 1 -static void PR_CALLBACK -HandleImagePLEvent(nsIContent *aContent, PRUint32 aMessage, - PRUint32 aEventFlags) +class nsImageBoxFrameEvent : public nsRunnable { - if (!aContent) { - NS_ERROR("null node passed to HandleImagePLEvent!"); +public: + nsImageBoxFrameEvent(nsIContent *content, PRUint32 message) + : mContent(content), mMessage(message) {} - return; - } + NS_IMETHOD Run(); - nsIDocument* doc = aContent->GetOwnerDoc(); +private: + nsCOMPtr mContent; + PRUint32 mMessage; +}; +NS_IMETHODIMP +nsImageBoxFrameEvent::Run() +{ + nsIDocument* doc = mContent->GetOwnerDoc(); if (!doc) { - return; + return NS_OK; } nsIPresShell *pres_shell = doc->GetShellAt(0); if (!pres_shell) { - return; + return NS_OK; } nsCOMPtr pres_context = pres_shell->GetPresContext(); if (!pres_context) { - return; + return NS_OK; } nsEventStatus status = nsEventStatus_eIgnore; - nsEvent event(PR_TRUE, aMessage); + nsEvent event(PR_TRUE, mMessage); - event.flags |= aEventFlags; - nsEventDispatcher::Dispatch(aContent, pres_context, &event, nsnull, &status); + event.flags |= NS_EVENT_FLAG_CANT_BUBBLE; + nsEventDispatcher::Dispatch(mContent, pres_context, &event, nsnull, &status); + return NS_OK; } -static void* PR_CALLBACK -HandleImageOnloadPLEvent(PLEvent *aEvent) -{ - nsIContent *content = (nsIContent *)PL_GetEventOwner(aEvent); - - HandleImagePLEvent(content, NS_IMAGE_LOAD, - NS_EVENT_FLAG_CANT_BUBBLE); - - // XXXldb Why not put this in DestroyImagePLEvent? - NS_RELEASE(content); - - return nsnull; -} - -static void* PR_CALLBACK -HandleImageOnerrorPLEvent(PLEvent *aEvent) -{ - nsIContent *content = (nsIContent *)PL_GetEventOwner(aEvent); - - HandleImagePLEvent(content, NS_IMAGE_ERROR, NS_EVENT_FLAG_CANT_BUBBLE); - - // XXXldb Why not put this in DestroyImagePLEvent? - NS_RELEASE(content); - - return nsnull; -} - -static void PR_CALLBACK -DestroyImagePLEvent(PLEvent* aEvent) -{ - delete aEvent; -} - -// Fire off a PLEvent that'll asynchronously call the image elements +// Fire off an event that'll asynchronously call the image elements // onload handler once handled. This is needed since the image library // can't decide if it wants to call it's observer methods // synchronously or asynchronously. If an image is loaded from the @@ -175,62 +148,12 @@ DestroyImagePLEvent(PLEvent* aEvent) void FireImageDOMEvent(nsIContent* aContent, PRUint32 aMessage) { - static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); + NS_ASSERTION(aMessage == NS_IMAGE_LOAD || aMessage == NS_IMAGE_ERROR, + "invalid message"); - nsCOMPtr event_service = - do_GetService(kEventQueueServiceCID); - - if (!event_service) { - NS_WARNING("Failed to get event queue service"); - - return; - } - - nsCOMPtr event_queue; - - event_service->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(event_queue)); - - if (!event_queue) { - NS_WARNING("Failed to get event queue from service"); - - return; - } - - PLEvent *event = new PLEvent; - - if (!event) { - // Out of memory, but none of our callers care, so just warn and - // don't fire the event - - NS_WARNING("Out of memory?"); - - return; - } - - PLHandleEventProc f; - - switch (aMessage) { - case NS_IMAGE_LOAD : - f = ::HandleImageOnloadPLEvent; - - break; - case NS_IMAGE_ERROR : - f = ::HandleImageOnerrorPLEvent; - - break; - default: - NS_WARNING("Huh, I don't know how to fire this type of event?!"); - - return; - } - - PL_InitEvent(event, aContent, f, ::DestroyImagePLEvent); - - // The event owns the content pointer now. - NS_ADDREF(aContent); - - event_queue->PostEvent(event); + nsCOMPtr event = new nsImageBoxFrameEvent(aContent, aMessage); + if (NS_FAILED(NS_DispatchToCurrentThread(event))) + NS_WARNING("failed to dispatch image event"); } // diff --git a/mozilla/layout/xul/base/src/tree/src/nsTreeSelection.cpp b/mozilla/layout/xul/base/src/tree/src/nsTreeSelection.cpp index 850213a38b0..8c0b39c03ff 100644 --- a/mozilla/layout/xul/base/src/tree/src/nsTreeSelection.cpp +++ b/mozilla/layout/xul/base/src/tree/src/nsTreeSelection.cpp @@ -55,6 +55,7 @@ #include "nsXULAtoms.h" #include "nsPLDOMEvent.h" #include "nsEventDispatcher.h" +#include "nsAutoPtr.h" // A helper class for managing our ranges of selection. struct nsTreeRange @@ -612,21 +613,12 @@ NS_IMETHODIMP nsTreeSelection::SetCurrentIndex(PRInt32 aIndex) nsCOMPtr treeDOMNode(do_QueryInterface(treeElt)); NS_ENSURE_TRUE(treeDOMNode, NS_ERROR_UNEXPECTED); - nsPLDOMEvent *event = new nsPLDOMEvent(treeDOMNode, + nsRefPtr event = new nsPLDOMEvent(treeDOMNode, NS_LITERAL_STRING("DOMMenuItemActive")); + if (!event) + return NS_ERROR_OUT_OF_MEMORY; - nsresult rv; - if (event) { - rv = event->PostDOMEvent(); - if (NS_FAILED(rv)) { - PL_DestroyEvent(event); - } - } - else { - rv = NS_ERROR_OUT_OF_MEMORY; - } - - return rv; + return event->PostDOMEvent(); } #define ADD_NEW_RANGE(macro_range, macro_selection, macro_start, macro_end) \ diff --git a/mozilla/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp b/mozilla/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp index 6c2abf03bcc..21e57da1d4b 100644 --- a/mozilla/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp +++ b/mozilla/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp @@ -402,10 +402,10 @@ NS_IMETHODIMP nsAbQueryLDAPMessageListener::OnLDAPInit(nsILDAPConnection *aConn, NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr proxyListener; - rv = NS_GetProxyForObject(NS_UI_THREAD_EVENTQ, + rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsILDAPMessageListener), NS_STATIC_CAST(nsILDAPMessageListener *, this), - PROXY_SYNC | PROXY_ALWAYS, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(proxyListener)); rv = ldapOperation->Init(mConnection, proxyListener, nsnull); @@ -471,13 +471,11 @@ nsresult nsAbQueryLDAPMessageListener::OnLDAPMessageBind (nsILDAPMessage *aMessa mSearchOperation = do_CreateInstance(NS_LDAPOPERATION_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr proxyMgr = - do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr proxyListener; - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsILDAPMessageListener), - this, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs(proxyListener)); + rv = NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsILDAPMessageListener), + this, NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs(proxyListener)); NS_ENSURE_SUCCESS(rv, rv); rv = mSearchOperation->Init (mConnection, proxyListener, nsnull); diff --git a/mozilla/mailnews/addrbook/src/nsAbLDAPReplicationData.cpp b/mozilla/mailnews/addrbook/src/nsAbLDAPReplicationData.cpp index 2d38724d578..5ab5f52319d 100644 --- a/mozilla/mailnews/addrbook/src/nsAbLDAPReplicationData.cpp +++ b/mozilla/mailnews/addrbook/src/nsAbLDAPReplicationData.cpp @@ -144,10 +144,10 @@ NS_IMETHODIMP nsAbLDAPProcessReplicationData::OnLDAPInit(nsILDAPConnection *aCon } nsCOMPtr listener; - nsresult rv = NS_GetProxyForObject(NS_CURRENT_EVENTQ, + nsresult rv = NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, NS_GET_IID(nsILDAPMessageListener), NS_STATIC_CAST(nsILDAPMessageListener*, this), - PROXY_SYNC | PROXY_ALWAYS, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(listener)); if(NS_FAILED(rv)) { Done(PR_FALSE); diff --git a/mozilla/mailnews/addrbook/src/nsAbLDAPReplicationQuery.cpp b/mozilla/mailnews/addrbook/src/nsAbLDAPReplicationQuery.cpp index 09cfd009a2f..8bffa34a2e9 100644 --- a/mozilla/mailnews/addrbook/src/nsAbLDAPReplicationQuery.cpp +++ b/mozilla/mailnews/addrbook/src/nsAbLDAPReplicationQuery.cpp @@ -165,10 +165,10 @@ NS_IMETHODIMP nsAbLDAPReplicationQuery::ConnectToLDAPServer(nsILDAPURL *aURL, co // Initiate LDAP message listener to the current thread nsCOMPtr listener; - rv = NS_GetProxyForObject(NS_CURRENT_EVENTQ, + rv = NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, NS_GET_IID(nsILDAPMessageListener), NS_STATIC_CAST(nsILDAPMessageListener*, mDataProcessor), - PROXY_SYNC | PROXY_ALWAYS, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(listener)); if (!listener) return NS_ERROR_FAILURE; diff --git a/mozilla/mailnews/addrbook/src/nsAbOutlookDirectory.cpp b/mozilla/mailnews/addrbook/src/nsAbOutlookDirectory.cpp index 5887a3bcb61..2f3ebf198c5 100644 --- a/mozilla/mailnews/addrbook/src/nsAbOutlookDirectory.cpp +++ b/mozilla/mailnews/addrbook/src/nsAbOutlookDirectory.cpp @@ -1027,10 +1027,10 @@ NS_IMETHODIMP nsAbOutlookDirectory::StartSearch(void) NS_ENSURE_SUCCESS(retCode, retCode) ; nsCOMPtr proxyListener; - retCode = NS_GetProxyForObject(NS_UI_THREAD_EVENTQ, + retCode = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIAbDirectoryQueryResultListener), NS_STATIC_CAST(nsIAbDirectoryQueryResultListener *, new nsAbDirSearchListener(this)), - PROXY_SYNC | PROXY_ALWAYS, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(proxyListener)); NS_ENSURE_SUCCESS(retCode, retCode) ; diff --git a/mozilla/mailnews/addrbook/src/nsAbRDFDataSource.cpp b/mozilla/mailnews/addrbook/src/nsAbRDFDataSource.cpp index e19948139ba..6fbe4bfe82b 100644 --- a/mozilla/mailnews/addrbook/src/nsAbRDFDataSource.cpp +++ b/mozilla/mailnews/addrbook/src/nsAbRDFDataSource.cpp @@ -48,8 +48,6 @@ #include "nsRDFCID.h" #include "nsIRDFNode.h" #include "nsEnumeratorUtils.h" -#include "nsIThread.h" -#include "nsIEventQueueService.h" #include "nsIProxyObjectManager.h" #include "nsString.h" @@ -57,6 +55,7 @@ #include "nsXPIDLString.h" #include "nsAutoLock.h" #include "nsIServiceManager.h" +#include "nsThreadUtils.h" // this is used for notification of observers using nsVoidArray typedef struct _nsAbRDFNotification { @@ -136,34 +135,21 @@ nsresult nsAbRDFDataSource::CreateProxyObserver (nsIRDFObserver* observer, { nsresult rv; - nsCOMPtr eventQSvc = do_GetService (NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - // Get the UI event queue - nsCOMPtr uiQueue; - rv = eventQSvc->GetSpecialEventQueue ( - nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs (uiQueue)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr proxyMgr = - do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - // Proxy the observer on the UI queue + // Proxy the observer on the UI thread /* * TODO - * Currenly using PROXY_ASYNC, however + * Currenly using NS_PROXY_ASYNC, however * this can flood the event queue if * rate of events on the observer is * greater that the time to process the * events. * This causes the UI to pause. */ - rv = proxyMgr->GetProxyForObject (uiQueue, + rv = NS_GetProxyForObject ( + NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIRDFObserver), observer, - PROXY_ASYNC | PROXY_ALWAYS, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, (void** )proxyObserver); return rv; @@ -232,12 +218,6 @@ nsresult nsAbRDFDataSource::NotifyObservers(nsIRDFResource *subject, return NS_OK; - // Get the current thread - nsCOMPtr currentThread; - rv = nsIThread::GetCurrent (getter_AddRefs(currentThread)); - NS_ENSURE_SUCCESS (rv, rv); - - // Get the main thread, which is the UI thread /* * TODO * Is the main thread always guaranteed to be @@ -249,12 +229,8 @@ nsresult nsAbRDFDataSource::NotifyObservers(nsIRDFResource *subject, * RDF datasources that are not UI specific * but are used in the UI? */ - nsCOMPtr uiThread; - rv = nsIThread::GetMainThread (getter_AddRefs(uiThread)); - NS_ENSURE_SUCCESS (rv, rv); - nsCOMPtr observers; - if (currentThread == uiThread) + if (NS_IsMainThread()) { /* * Since this is the UI Thread use the diff --git a/mozilla/mailnews/addrbook/src/nsAddrDatabase.cpp b/mozilla/mailnews/addrbook/src/nsAddrDatabase.cpp index 894bf3427c8..caf501abe92 100644 --- a/mozilla/mailnews/addrbook/src/nsAddrDatabase.cpp +++ b/mozilla/mailnews/addrbook/src/nsAddrDatabase.cpp @@ -43,6 +43,7 @@ #include "nsIEnumerator.h" #include "nsString.h" #include "nsReadableUtils.h" +#include "nsAutoPtr.h" #include "nsRDFCID.h" #include "nsUnicharUtils.h" #include "nsMsgUtils.h" @@ -3619,12 +3620,9 @@ NS_IMETHODIMP nsAddrDatabase::AddListDirNode(nsIMdbRow * listRow) { nsresult rv = NS_OK; - nsCOMPtr proxyMgr = - do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); - NS_WITH_PROXIED_SERVICE(nsIRDFService, rdfService, kRDFServiceCID, NS_UI_THREAD_EVENTQ, &rv); + static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); + NS_WITH_PROXIED_SERVICE(nsIRDFService, rdfService, kRDFServiceCID, + NS_PROXY_TO_MAIN_THREAD, &rv); if (NS_SUCCEEDED(rv)) { nsCOMPtr parentResource; @@ -3637,8 +3635,11 @@ NS_IMETHODIMP nsAddrDatabase::AddListDirNode(nsIMdbRow * listRow) rv = rdfService->GetResource(NS_ConvertUTF16toUTF8(parentURI), getter_AddRefs(parentResource)); nsCOMPtr parentDir; - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID( nsIAbDirectory), - parentResource, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs( parentDir)); + rv = NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID( nsIAbDirectory), + parentResource, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs( parentDir)); if (parentDir) { m_dbDirectory = parentDir; diff --git a/mozilla/mailnews/addrbook/src/nsLDAPAutoCompleteSession.cpp b/mozilla/mailnews/addrbook/src/nsLDAPAutoCompleteSession.cpp index 3762a63e89e..740557b7608 100644 --- a/mozilla/mailnews/addrbook/src/nsLDAPAutoCompleteSession.cpp +++ b/mozilla/mailnews/addrbook/src/nsLDAPAutoCompleteSession.cpp @@ -581,10 +581,10 @@ nsLDAPAutoCompleteSession::OnLDAPInit(nsILDAPConnection *aConn, nsresult aStatus // get a proxy object so the callback happens on the main thread // - rv = NS_GetProxyForObject(NS_UI_THREAD_EVENTQ, + rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsILDAPMessageListener), NS_STATIC_CAST(nsILDAPMessageListener *, this), - PROXY_ASYNC | PROXY_ALWAYS, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, getter_AddRefs(selfProxy)); if (NS_FAILED(rv)) { NS_ERROR("nsLDAPAutoCompleteSession::OnLDAPInit(): couldn't " @@ -866,10 +866,10 @@ nsLDAPAutoCompleteSession::StartLDAPSearch() // get a proxy object so the callback happens on the main thread // - rv = NS_GetProxyForObject(NS_UI_THREAD_EVENTQ, + rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsILDAPMessageListener), NS_STATIC_CAST(nsILDAPMessageListener *, this), - PROXY_ASYNC | PROXY_ALWAYS, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, getter_AddRefs(selfProxy)); if (NS_FAILED(rv)) { NS_ERROR("nsLDAPAutoCompleteSession::StartLDAPSearch(): couldn't " @@ -1170,10 +1170,10 @@ nsLDAPAutoCompleteSession::InitConnection() // get a proxy object so the callback happens on the main thread // - rv = NS_GetProxyForObject(NS_UI_THREAD_EVENTQ, + rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsILDAPMessageListener), NS_STATIC_CAST(nsILDAPMessageListener *, this), - PROXY_ASYNC | PROXY_ALWAYS, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, getter_AddRefs(selfProxy)); if (NS_FAILED(rv)) { NS_ERROR("nsLDAPAutoCompleteSession::InitConnection(): couldn't " diff --git a/mozilla/mailnews/base/src/nsMsgAccountManager.cpp b/mozilla/mailnews/base/src/nsMsgAccountManager.cpp index a1eae491c7c..a927211f6f0 100644 --- a/mozilla/mailnews/base/src/nsMsgAccountManager.cpp +++ b/mozilla/mailnews/base/src/nsMsgAccountManager.cpp @@ -76,7 +76,6 @@ #include "nsIMsgPurgeService.h" #include "nsIObserverService.h" #include "nsIMsgMailSession.h" -#include "nsIEventQueueService.h" #include "nsIDirectoryService.h" #include "nsAppDirectoryServiceDefs.h" #include "nsMsgFolderFlags.h" @@ -94,6 +93,7 @@ #include "nsIDBFolderInfo.h" #include "nsIMsgHdr.h" #include "nsILineInputStream.h" +#include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsEscape.h" @@ -112,7 +112,6 @@ static NS_DEFINE_CID(kMsgAccountCID, NS_MSGACCOUNT_CID); static NS_DEFINE_CID(kMsgFolderCacheCID, NS_MSGFOLDERCACHE_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); // use this to search for all servers with the given hostname/iid and // put them in "servers" @@ -1052,12 +1051,6 @@ PRBool PR_CALLBACK nsMsgAccountManager::cleanupOnExit(nsHashKey *aKey, void *aDa nsCOMPtr accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - nsCOMPtr eventQueue; - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(eventQueue)); if (isImap) urlListener = do_QueryInterface(accountManager, &rv); @@ -1094,6 +1087,8 @@ PRBool PR_CALLBACK nsMsgAccountManager::cleanupOnExit(nsHashKey *aKey, void *aDa if (isImap && urlListener) { + nsIThread *thread = NS_GetCurrentThread(); + PRBool inProgress = PR_FALSE; if (cleanupInboxOnExit) { @@ -1104,8 +1099,7 @@ PRBool PR_CALLBACK nsMsgAccountManager::cleanupOnExit(nsHashKey *aKey, void *aDa PR_CEnterMonitor(folder); PR_CWait(folder, PR_MicrosecondsToInterval(1000UL)); PR_CExitMonitor(folder); - if (eventQueue) - eventQueue->ProcessPendingEvents(); + NS_ProcessPendingEvents(thread); } } if (emptyTrashOnExit) @@ -1117,8 +1111,7 @@ PRBool PR_CALLBACK nsMsgAccountManager::cleanupOnExit(nsHashKey *aKey, void *aDa PR_CEnterMonitor(folder); PR_CWait(folder, PR_MicrosecondsToInterval(1000UL)); PR_CExitMonitor(folder); - if (eventQueue) - eventQueue->ProcessPendingEvents(); + NS_ProcessPendingEvents(thread); } } } diff --git a/mozilla/mailnews/base/src/nsMsgPrintEngine.cpp b/mozilla/mailnews/base/src/nsMsgPrintEngine.cpp index bda17197d16..4fac1c6bb60 100644 --- a/mozilla/mailnews/base/src/nsMsgPrintEngine.cpp +++ b/mozilla/mailnews/base/src/nsMsgPrintEngine.cpp @@ -69,12 +69,8 @@ #include "nsIXULWindow.h" #include "nsIPrefService.h" #include "nsIPrefBranch.h" - -// For PLEvents -#include "plevent.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" -#include "nsIServiceManager.h" +#include "nsThreadUtils.h" +#include "nsAutoPtr.h" // Interfaces Needed #include "nsIBaseWindow.h" @@ -726,114 +722,61 @@ nsMsgPrintEngine::PrintMsgWindow() } //--------------------------------------------------------------- -//-- PLEvent Notification +//-- Event Notification //--------------------------------------------------------------- + +//--------------------------------------------------------------- +class nsPrintMsgWindowEvent : public nsRunnable +{ +public: + nsPrintMsgWindowEvent(nsMsgPrintEngine *mpe) + : mMsgPrintEngine(mpe) + {} + + NS_IMETHOD Run() + { + if (mMsgPrintEngine) + mMsgPrintEngine->PrintMsgWindow(); + return NS_OK; + } + +private: + nsRefPtr mMsgPrintEngine; +}; + //----------------------------------------------------------- -PRBool -FireEvent(nsMsgPrintEngine* aMPE, PLHandleEventProc handler, PLDestroyEventProc destructor) +class nsStartNextPrintOpEvent : public nsRunnable { - static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); +public: + nsStartNextPrintOpEvent(nsMsgPrintEngine *mpe) + : mMsgPrintEngine(mpe) + {} - nsCOMPtr event_service = do_GetService(kEventQueueServiceCID); - - if (!event_service) + NS_IMETHOD Run() { - NS_WARNING("Failed to get event queue service"); - return PR_FALSE; + if (mMsgPrintEngine) + mMsgPrintEngine->StartNextPrintOperation(); + return NS_OK; } - nsCOMPtr event_queue; - - event_service->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(event_queue)); - - if (!event_queue) - { - NS_WARNING("Failed to get event queue from service"); - return PR_FALSE; - } - - PLEvent *event = new PLEvent; - - if (!event) - { - NS_WARNING("Out of memory?"); - return PR_FALSE; - } - - PL_InitEvent(event, aMPE, handler, destructor); - - // The event owns the msgPrintEngine pointer now. - NS_ADDREF(aMPE); - - if (NS_FAILED(event_queue->PostEvent(event))) - { - NS_WARNING("Failed to post event"); - PL_DestroyEvent(event); - return PR_FALSE; - } - - return PR_TRUE; -} - -PR_STATIC_CALLBACK(void*) HandlePLEventPrintMsgWindow(PLEvent* aEvent) -{ - nsMsgPrintEngine *msgPrintEngine = (nsMsgPrintEngine*)PL_GetEventOwner(aEvent); - - NS_ASSERTION(msgPrintEngine, "The event owner is null."); - if (msgPrintEngine) - { - msgPrintEngine->PrintMsgWindow(); - } - - return nsnull; -} - -//------------------------------------------------------------------------ -PR_STATIC_CALLBACK(void) DestroyPLEventPrintMsgWindow(PLEvent* aEvent) -{ - nsMsgPrintEngine *msgPrintEngine = (nsMsgPrintEngine*)PL_GetEventOwner(aEvent); - NS_IF_RELEASE(msgPrintEngine); - - delete aEvent; -} +private: + nsRefPtr mMsgPrintEngine; +}; //----------------------------------------------------------- PRBool nsMsgPrintEngine::FirePrintEvent() { - return FireEvent(this, ::HandlePLEventPrintMsgWindow, - ::DestroyPLEventPrintMsgWindow); -} - -PR_STATIC_CALLBACK(void*) HandlePLEventStartNext(PLEvent* aEvent) -{ - nsMsgPrintEngine *msgPrintEngine = (nsMsgPrintEngine*)PL_GetEventOwner(aEvent); - - NS_ASSERTION(msgPrintEngine, "The event owner is null."); - if (msgPrintEngine) - { - msgPrintEngine->StartNextPrintOperation(); - } - - return nsnull; -} - -//------------------------------------------------------------------------ -PR_STATIC_CALLBACK(void) DestroyPLEventStartNext(PLEvent* aEvent) -{ - nsMsgPrintEngine *msgPrintEngine = (nsMsgPrintEngine*)PL_GetEventOwner(aEvent); - NS_IF_RELEASE(msgPrintEngine); - - delete aEvent; + nsCOMPtr event = new nsPrintMsgWindowEvent(this); + return NS_DispatchToCurrentThread(event); } //----------------------------------------------------------- PRBool nsMsgPrintEngine::FireStartNextEvent() { - return FireEvent(this, ::HandlePLEventStartNext, - ::DestroyPLEventStartNext); + nsCOMPtr event = new nsStartNextPrintOpEvent(this); + return NS_DispatchToCurrentThread(event); } /* void setStartupPPObserver (in nsIObserver startupPPObs); */ diff --git a/mozilla/mailnews/base/util/nsImapMoveCoalescer.cpp b/mozilla/mailnews/base/util/nsImapMoveCoalescer.cpp index 399acbc7197..ab2ff002e35 100755 --- a/mozilla/mailnews/base/util/nsImapMoveCoalescer.cpp +++ b/mozilla/mailnews/base/util/nsImapMoveCoalescer.cpp @@ -45,10 +45,8 @@ #include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later... #include "nsMsgFolderFlags.h" #include "nsIMsgHdr.h" -#include "nsIEventQueueService.h" #include "nsIMsgImapMailFolder.h" - -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); +#include "nsThreadUtils.h" NS_IMPL_ISUPPORTS1(nsImapMoveCoalescer, nsIUrlListener) @@ -287,14 +285,9 @@ NS_IMETHODIMP nsMoveCoalescerCopyListener::OnStopCopy(nsresult aStatus) nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr url; - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - nsCOMPtr eventQueue; - if (NS_SUCCEEDED(rv) && pEventQService) - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(eventQueue)); nsCOMPtr listener = do_QueryInterface(m_coalescer); - rv = imapService->SelectFolder(eventQueue, m_destFolder, listener, nsnull, getter_AddRefs(url)); + nsIThread *thread = NS_GetCurrentThread(); + rv = imapService->SelectFolder(thread, m_destFolder, listener, nsnull, getter_AddRefs(url)); } } return rv; diff --git a/mozilla/mailnews/base/util/nsMsgProtocol.cpp b/mozilla/mailnews/base/util/nsMsgProtocol.cpp index 7c830318d90..c600c33c5d7 100644 --- a/mozilla/mailnews/base/util/nsMsgProtocol.cpp +++ b/mozilla/mailnews/base/util/nsMsgProtocol.cpp @@ -59,7 +59,7 @@ #include "nsIStringBundle.h" #include "nsIProtocolProxyService.h" #include "nsIProxyInfo.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsIPrefBranch.h" #include "nsIPrefService.h" @@ -142,10 +142,7 @@ nsMsgProtocol::OpenNetworkSocketWithInfo(const char * aHostName, strans->SetSecurityCallbacks(callbacks); // creates cyclic reference! - nsCOMPtr eventQ; - NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - if (eventQ) - strans->SetEventSink(this, eventQ); + strans->SetEventSink(this, NS_GetCurrentThread()); m_socketIsOpen = PR_FALSE; m_transport = strans; @@ -1093,7 +1090,7 @@ public: // try to write again... if (NS_SUCCEEDED(rv)) - rv = aOutStream->AsyncWait(this, 0, 0, mMsgProtocol->mProviderEventQ); + rv = aOutStream->AsyncWait(this, 0, 0, mMsgProtocol->mProviderThread); NS_ASSERTION(NS_SUCCEEDED(rv) || rv == NS_BINDING_ABORTED, "unexpected error writing stream"); return NS_OK; @@ -1192,7 +1189,7 @@ NS_IMETHODIMP nsMsgFilePostHelper::OnDataAvailable(nsIRequest * /* aChannel */, // things off again. mProtInstance->mSuspendedWrite = PR_FALSE; mProtInstance->mAsyncOutStream->AsyncWait(mProtInstance->mProvider, 0, 0, - mProtInstance->mProviderEventQ); + mProtInstance->mProviderThread); } return NS_OK; @@ -1459,7 +1456,7 @@ nsresult nsMsgAsyncWriteProtocol::SetupTransportState() PR_TRUE, PR_TRUE); - rv = NS_GetCurrentEventQ(getter_AddRefs(mProviderEventQ)); + rv = NS_GetCurrentThread(getter_AddRefs(mProviderThread)); if (NS_FAILED(rv)) return rv; nsMsgProtocolStreamProvider *provider; @@ -1477,7 +1474,7 @@ nsresult nsMsgAsyncWriteProtocol::SetupTransportState() if (NS_FAILED(rv)) return rv; // wait for the output stream to become writable - rv = mAsyncOutStream->AsyncWait(mProvider, 0, 0, mProviderEventQ); + rv = mAsyncOutStream->AsyncWait(mProvider, 0, 0, mProviderThread); } // if m_transport return rv; @@ -1499,7 +1496,7 @@ nsresult nsMsgAsyncWriteProtocol::CloseSocket() mAsyncOutStream = 0; mProvider = 0; - mProviderEventQ = 0; + mProviderThread = 0; return rv; } @@ -1541,7 +1538,7 @@ PRInt32 nsMsgAsyncWriteProtocol::SendData(nsIURI * aURL, const char * dataBuffer // data to write (i.e. the pipe went empty). So resume the channel to kick // things off again. mSuspendedWrite = PR_FALSE; - mAsyncOutStream->AsyncWait(mProvider, 0, 0, mProviderEventQ); + mAsyncOutStream->AsyncWait(mProvider, 0, 0, mProviderThread); } return NS_OK; } diff --git a/mozilla/mailnews/base/util/nsMsgProtocol.h b/mozilla/mailnews/base/util/nsMsgProtocol.h index a811403574a..e5b0660cb83 100644 --- a/mozilla/mailnews/base/util/nsMsgProtocol.h +++ b/mozilla/mailnews/base/util/nsMsgProtocol.h @@ -43,6 +43,7 @@ #include "nsIOutputStream.h" #include "nsIChannel.h" #include "nsIURL.h" +#include "nsIThread.h" #include "nsILoadGroup.h" #include "nsCOMPtr.h" #include "nsIFileSpec.h" @@ -51,7 +52,6 @@ #include "nsIProgressEventSink.h" #include "nsITransport.h" #include "nsIAsyncOutputStream.h" -#include "nsIEventQueue.h" #include "nsIAuthModule.h" #define UNKNOWN_ERROR 101 @@ -217,7 +217,7 @@ public: nsCOMPtr m_WriteRequest; nsCOMPtr mAsyncOutStream; nsCOMPtr mProvider; - nsCOMPtr mProviderEventQ; + nsCOMPtr mProviderThread; // because we are reading the post data in asychronously, it's possible that we aren't sending it // out fast enough and the reading gets blocked. The following set of state variables are used to diff --git a/mozilla/mailnews/compose/src/nsMsgCopy.cpp b/mozilla/mailnews/compose/src/nsMsgCopy.cpp index 21dedc3774f..cc3f05c7265 100644 --- a/mozilla/mailnews/compose/src/nsMsgCopy.cpp +++ b/mozilla/mailnews/compose/src/nsMsgCopy.cpp @@ -56,13 +56,12 @@ #include "nsMsgCompUtils.h" #include "prcmon.h" #include "nsIMsgImapMailFolder.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsMsgSimulateError.h" #include "nsIMsgWindow.h" #include "nsIMsgProgress.h" static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); //////////////////////////////////////////////////////////////////////////////////// // This is the listener class for the copy operation. We have to create this class @@ -282,7 +281,7 @@ nsMsgCopy::DoCopy(nsIFileSpec *aDiskFile, nsIMsgFolder *dstFolder, return NS_ERROR_OUT_OF_MEMORY; copyListener->SetMsgComposeAndSendObject(aMsgSendObj); - nsCOMPtr eventQueue; + nsIThread *thread = nsnull; if (aIsDraft) { @@ -299,11 +298,7 @@ nsMsgCopy::DoCopy(nsIFileSpec *aDiskFile, nsIMsgFolder *dstFolder, // set the following only when we were in the middle of shutdown // process copyListener->mCopyInProgress = PR_TRUE; - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(eventQueue)); + thread = NS_GetCurrentThread(); } } nsCOMPtr copyService = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID, &rv); @@ -318,8 +313,8 @@ nsMsgCopy::DoCopy(nsIFileSpec *aDiskFile, nsIMsgFolder *dstFolder, PR_CEnterMonitor(copyListener); PR_CWait(copyListener, PR_MicrosecondsToInterval(1000UL)); PR_CExitMonitor(copyListener); - if (eventQueue) - eventQueue->ProcessPendingEvents(); + if (thread) + NS_ProcessPendingEvents(thread); } } diff --git a/mozilla/mailnews/compose/src/nsMsgCreate.cpp b/mozilla/mailnews/compose/src/nsMsgCreate.cpp index c02cddf1bec..0d0bba0c14a 100644 --- a/mozilla/mailnews/compose/src/nsMsgCreate.cpp +++ b/mozilla/mailnews/compose/src/nsMsgCreate.cpp @@ -37,7 +37,6 @@ * ***** END LICENSE BLOCK ***** */ #include "nsCOMPtr.h" #include "nsIURL.h" -#include "nsIEventQueueService.h" #include "nsIInputStream.h" #include "nsIOutputStream.h" #include "nsIGenericFactory.h" diff --git a/mozilla/mailnews/imap/public/nsIImapIncomingServer.idl b/mozilla/mailnews/imap/public/nsIImapIncomingServer.idl index d53b8751918..ada91f23e06 100644 --- a/mozilla/mailnews/imap/public/nsIImapIncomingServer.idl +++ b/mozilla/mailnews/imap/public/nsIImapIncomingServer.idl @@ -40,7 +40,7 @@ interface nsIUrlListener; interface nsIURI; interface nsIImapUrl; -interface nsIEventQueue; +interface nsIEventTarget; interface nsIImapProtocol; interface nsISupportsArray; interface nsIMsgFolder; @@ -56,7 +56,7 @@ interface nsMsgImapDeleteModels const long DeleteNoTrash = 2; /* delete is shift delete - don't create or use trash */ }; -[scriptable, uuid(a54c32c7-17ae-4733-b551-1725f15044f6)] +[scriptable, uuid(5e8f307e-4432-4b5e-8f92-0b0ffc3ee594)] interface nsIImapIncomingServer : nsISupports { attribute long maximumConnectionsNumber; @@ -88,7 +88,7 @@ interface nsIImapIncomingServer : nsISupports { nsIMsgFolder getPFC(in boolean createIfMissing); attribute boolean downloadBodiesOnGetNewMail; attribute boolean autoSyncOfflineStores; - void GetImapConnectionAndLoadUrl(in nsIEventQueue aClientEventQueue, + void GetImapConnectionAndLoadUrl(in nsIEventTarget aClientEventTarget, in nsIImapUrl aImapUrl, in nsISupports aConsumer); diff --git a/mozilla/mailnews/imap/public/nsIImapProtocol.idl b/mozilla/mailnews/imap/public/nsIImapProtocol.idl index 382a1c1e2bb..acc9e6efbd9 100644 --- a/mozilla/mailnews/imap/public/nsIImapProtocol.idl +++ b/mozilla/mailnews/imap/public/nsIImapProtocol.idl @@ -41,7 +41,7 @@ interface nsIUrlListener; interface nsIURI; interface nsIImapUrl; -interface nsIEventQueue; +interface nsIEventTarget; interface nsIImapProtocol; interface nsIImapIncomingServer; interface nsISupportsArray; @@ -49,7 +49,7 @@ interface nsIMsgFolder; interface nsIImapHostSessionList; interface nsIMsgWindow; -[scriptable, uuid(0f660d51-e3f1-4f80-86b5-66fa31732f2b)] +[scriptable, uuid(9410ec75-854c-4b0e-96f4-b485ffe1f0d4)] interface nsIImapProtocol : nsISupports { ///////////////////////////////////////////////////////////////////////// /* LoadUrl should really be pushed into a generic protocol interface @@ -79,7 +79,7 @@ interface nsIImapProtocol : nsISupports { // protocol data. The protocol also needs a host session list. ///////////////////////////////////////////////////////////////////////// void Initialize(in nsIImapHostSessionList aHostSessionList, in nsIImapIncomingServer aServer, - in nsIEventQueue aSinkEventQueue) ; + in nsIEventTarget aSinkEventTarget) ; void NotifyHdrsToDownload(out unsigned long keys, in unsigned long keyCount); void NotifyBodysToDownload(out unsigned long keys, in unsigned long count); diff --git a/mozilla/mailnews/imap/public/nsIImapService.idl b/mozilla/mailnews/imap/public/nsIImapService.idl index da2054f9624..87594e0a9e8 100644 --- a/mozilla/mailnews/imap/public/nsIImapService.idl +++ b/mozilla/mailnews/imap/public/nsIImapService.idl @@ -51,27 +51,27 @@ interface nsIImapProtocol; interface nsIImapMessageSink; interface nsIUrlListener; interface nsIURI; -interface nsIEventQueue; +interface nsIEventTarget; interface nsIMsgFolder; interface nsIMsgWindow; interface nsIImapIncomingServer; interface nsICacheSession; -[scriptable, uuid(4032dc12-8684-4458-9b41-647034d8c7d2)] +[scriptable, uuid(0819ca53-746b-4072-896a-87a452dc5a77)] interface nsIImapService : nsISupports { // As always, you can pass in null for the url listener and the url if you don't require either..... - // aClientEventQueue is the event queue of the event sinks. We post events into this queue. + // aClientEventTarget is the event queue of the event sinks. We post events into this queue. // mscott -- eventually this function will take in the account (identity/incoming server) associated with // the request - void selectFolder(in nsIEventQueue aClientEventQueue, + void selectFolder(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, in nsIMsgWindow aMsgWindow, out nsIURI aURL); - void liteSelectFolder(in nsIEventQueue aClientEventQueue, + void liteSelectFolder(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, out nsIURI aURL); @@ -87,52 +87,52 @@ interface nsIImapService : nsISupports in string additionalHeader, out nsIURI aOutURL); - void noop(in nsIEventQueue aClientEventQueue, + void noop(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, out nsIURI aURL); - void getHeaders(in nsIEventQueue aClientEventQueue, + void getHeaders(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, out nsIURI aURL, in string aMessageIdentifierList, in boolean aMessageIdsAreUID); - nsIURI getBodyStart(in nsIEventQueue aClientEventQueue, + nsIURI getBodyStart(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, in string aMessageIdentifierList, in long numBytes); - void expunge(in nsIEventQueue aClientEventQueue, + void expunge(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, out nsIURI aURL); - nsIURI updateFolderStatus(in nsIEventQueue aClientEventQueue, + nsIURI updateFolderStatus(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener); - void biff(in nsIEventQueue aClientEventQueue, + void biff(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, out nsIURI aURL, in unsigned long aUidHighWater); - void deleteMessages(in nsIEventQueue aClientEventQueue, + void deleteMessages(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, out nsIURI aURL, in string aMessageIdentifierList, in boolean aMessageIdsAreUID); - void deleteAllMessages(in nsIEventQueue aClientEventQueue, + void deleteAllMessages(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, out nsIURI aURL); - void addMessageFlags(in nsIEventQueue aClientEventQueue, + void addMessageFlags(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, out nsIURI aURL, @@ -140,7 +140,7 @@ interface nsIImapService : nsISupports in imapMessageFlagsType aFlags, in boolean aMessageIdsAreUID); - void subtractMessageFlags(in nsIEventQueue aClientEventQueue, + void subtractMessageFlags(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, out nsIURI aURL, @@ -148,7 +148,7 @@ interface nsIImapService : nsISupports in imapMessageFlagsType aFlags, in boolean aMessageIdsAreUID); - void setMessageFlags(in nsIEventQueue aClientEventQueue, + void setMessageFlags(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, out nsIURI aURL, @@ -156,23 +156,23 @@ interface nsIImapService : nsISupports in imapMessageFlagsType aFlags, in boolean aMessageIdsAreUID); - void discoverAllFolders(in nsIEventQueue aClientEventQueue, + void discoverAllFolders(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, in nsIMsgWindow aMsgWindow, out nsIURI aURL); - void discoverAllAndSubscribedFolders(in nsIEventQueue aClientEventQueue, + void discoverAllAndSubscribedFolders(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, out nsIURI aURL); - void discoverChildren(in nsIEventQueue aClientEventQueue, + void discoverChildren(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aImapMailFolder, in nsIUrlListener aUrlListener, in string folderPath, out nsIURI aURL); - void onlineMessageCopy(in nsIEventQueue aClientEventQueue, + void onlineMessageCopy(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aSrcFolder, in string aMessageIds, in nsIMsgFolder aDstFolder, @@ -184,7 +184,7 @@ interface nsIImapService : nsISupports in nsIMsgWindow aWindow); - void appendMessageFromFile(in nsIEventQueue aClientEventQueue, + void appendMessageFromFile(in nsIEventTarget aClientEventTarget, in nsIFileSpec aFileSpec, in nsIMsgFolder aDstFolder, in string aMessageId, @@ -198,37 +198,37 @@ interface nsIImapService : nsISupports void downloadMessagesForOffline(in string aMessageIds, in nsIMsgFolder aSrcFolder, in nsIUrlListener aListener, in nsIMsgWindow aMsgWindow); - nsIURI moveFolder(in nsIEventQueue aClientEventQueue, + nsIURI moveFolder(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aSrcFolder, in nsIMsgFolder aDstFolder, in nsIUrlListener aUrlListener, in nsIMsgWindow msgWindow); - nsIURI renameLeaf(in nsIEventQueue aClientEventQueue, + nsIURI renameLeaf(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aSrcFolder, in wstring aLeafName, in nsIUrlListener aUrlListener, in nsIMsgWindow msgWindow); - nsIURI deleteFolder(in nsIEventQueue aClientEventQueue, + nsIURI deleteFolder(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aFolder, in nsIUrlListener aUrlListener); - nsIURI createFolder(in nsIEventQueue aClientEventQueue, + nsIURI createFolder(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aParentFolder, in wstring aLeafName, in nsIUrlListener aUrlListener); - nsIURI listFolder(in nsIEventQueue aClientEventQueue, + nsIURI listFolder(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aMailFolder, in nsIUrlListener aUrlListener); - nsIURI subscribeFolder(in nsIEventQueue aClientEventQueue, + nsIURI subscribeFolder(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aMailFolder, in wstring mailboxName, in nsIUrlListener aUrlListener); - nsIURI unsubscribeFolder(in nsIEventQueue aClientEventQueue, + nsIURI unsubscribeFolder(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aMailFolder, in wstring mailboxName, in nsIUrlListener aUrlListener); @@ -237,30 +237,30 @@ interface nsIImapService : nsISupports // not subscribed to, in which case it will subscribe to the folder. // otherwise, it will try to create the folder. It will try to do this // with one url. - nsIURI ensureFolderExists(in nsIEventQueue aClientEventQueue, + nsIURI ensureFolderExists(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aParentFolder, in wstring aLeafName, in nsIUrlListener aUrlListener); - nsIURI getFolderAdminUrl(in nsIEventQueue aClientEventQueue, + nsIURI getFolderAdminUrl(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aMailFolder, in nsIMsgWindow aMsgWindow, in nsIUrlListener aUrlListener); - nsIURI issueCommandOnMsgs(in nsIEventQueue aClientEventQueue, + nsIURI issueCommandOnMsgs(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aMailFolder, in nsIMsgWindow aMsgWindow, in string aCommand, in string aMessageIdentifierList); - nsIURI fetchCustomMsgAttribute(in nsIEventQueue aClientEventQueue, + nsIURI fetchCustomMsgAttribute(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aMailFolder, in nsIMsgWindow aMsgWindow, in string aAttribute, in string aMessageIdentifierList); - nsIURI storeCustomKeywords(in nsIEventQueue aClientEventQueue, + nsIURI storeCustomKeywords(in nsIEventTarget aClientEventTarget, in nsIMsgFolder aMailFolder, in nsIMsgWindow aMsgWindow, in string flagsToAdd, diff --git a/mozilla/mailnews/imap/src/nsImapIncomingServer.cpp b/mozilla/mailnews/imap/src/nsImapIncomingServer.cpp index 8db83c95a3f..d08b7968d07 100644 --- a/mozilla/mailnews/imap/src/nsImapIncomingServer.cpp +++ b/mozilla/mailnews/imap/src/nsImapIncomingServer.cpp @@ -56,7 +56,7 @@ #include "nsIMsgIdentity.h" #include "nsIImapUrl.h" #include "nsIUrlListener.h" -#include "nsIEventQueue.h" +#include "nsThreadUtils.h" #include "nsImapProtocol.h" #include "nsISupportsArray.h" #include "nsVoidArray.h" @@ -75,7 +75,6 @@ #include "nsIRDFService.h" #include "nsRDFCID.h" #include "nsEnumeratorUtils.h" -#include "nsIEventQueueService.h" #include "nsIMsgMailNewsUrl.h" #include "nsIImapService.h" #include "nsMsgI18N.h" @@ -100,7 +99,6 @@ static NS_DEFINE_CID(kImapProtocolCID, NS_IMAPPROTOCOL_CID); static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kImapServiceCID, NS_IMAPSERVICE_CID); static NS_DEFINE_CID(kSubscribableServerCID, NS_SUBSCRIBABLESERVER_CID); static NS_DEFINE_CID(kCImapHostSessionListCID, NS_IIMAPHOSTSESSIONLIST_CID); @@ -430,14 +428,14 @@ nsImapIncomingServer::SetIsAOLServer(PRBool aBool) NS_IMETHODIMP -nsImapIncomingServer::GetImapConnectionAndLoadUrl(nsIEventQueue * aClientEventQueue, +nsImapIncomingServer::GetImapConnectionAndLoadUrl(nsIEventTarget * aClientEventTarget, nsIImapUrl* aImapUrl, nsISupports* aConsumer) { nsresult rv = NS_OK; nsCOMPtr aProtocol; - rv = GetImapConnection(aClientEventQueue, aImapUrl, getter_AddRefs(aProtocol)); + rv = GetImapConnection(aClientEventTarget, aImapUrl, getter_AddRefs(aProtocol)); if (NS_FAILED(rv)) return rv; nsCOMPtr mailnewsurl = do_QueryInterface(aImapUrl, &rv); @@ -476,16 +474,10 @@ NS_IMETHODIMP nsImapIncomingServer::RetryUrl(nsIImapUrl *aImapUrl) { nsresult rv; - nsCOMPtr aEventQueue; // Get current thread envent queue - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_SUCCEEDED(rv) && pEventQService) - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(aEventQueue)); nsCOMPtr protocolInstance; nsImapProtocol::LogImapUrl("creating protocol instance to retry queued url", aImapUrl); - rv = GetImapConnection(aEventQueue, aImapUrl, getter_AddRefs(protocolInstance)); + rv = GetImapConnection(NS_GetCurrentThread(), aImapUrl, getter_AddRefs(protocolInstance)); if (NS_SUCCEEDED(rv) && protocolInstance) { nsCOMPtr url = do_QueryInterface(aImapUrl, &rv); @@ -691,7 +683,7 @@ nsImapIncomingServer::ConnectionTimeOut(nsIImapProtocol* aConnection) } nsresult -nsImapIncomingServer::GetImapConnection(nsIEventQueue *aEventQueue, +nsImapIncomingServer::GetImapConnection(nsIEventTarget *aEventTarget, nsIImapUrl * aImapUrl, nsIImapProtocol ** aImapConnection) { @@ -853,10 +845,10 @@ nsImapIncomingServer::GetImapConnection(nsIEventQueue *aEventQueue, // (e.g., a folder delete or msg append) but we shouldn't create new connections // for these types of urls if we have a free connection. So we check the actual // required state here. - else if (cnt < ((PRUint32)maxConnections) && aEventQueue + else if (cnt < ((PRUint32)maxConnections) && aEventTarget && (!freeConnection || requiredState == nsIImapUrl::nsImapSelectedState)) { - rv = CreateProtocolInstance(aEventQueue, aImapConnection); + rv = CreateProtocolInstance(aEventTarget, aImapConnection); } else if (freeConnection) { @@ -876,7 +868,7 @@ nsImapIncomingServer::GetImapConnection(nsIEventQueue *aEventQueue, } nsresult -nsImapIncomingServer::CreateProtocolInstance(nsIEventQueue *aEventQueue, +nsImapIncomingServer::CreateProtocolInstance(nsIEventTarget *aEventTarget, nsIImapProtocol ** aImapConnection) { // create a new connection and add it to the connection cache @@ -899,7 +891,7 @@ nsImapIncomingServer::CreateProtocolInstance(nsIEventQueue *aEventQueue, nsCOMPtr hostSession = do_GetService(kCImapHostSessionListCID, &rv); if (NS_SUCCEEDED(rv)) - rv = protocolInstance->Initialize(hostSession, this, aEventQueue); + rv = protocolInstance->Initialize(hostSession, this, aEventTarget); } // take the protocol instance and add it to the connectionCache @@ -1003,16 +995,8 @@ nsImapIncomingServer::PerformExpand(nsIMsgWindow *aMsgWindow) nsCOMPtr imapService = do_GetService(kImapServiceCID, &rv); if (NS_FAILED(rv)) return rv; if (!imapService) return NS_ERROR_FAILURE; - nsCOMPtr queue; - // get the Event Queue for this thread... - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - if (!pEventQService) return NS_ERROR_FAILURE; - - rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - if (NS_FAILED(rv)) return rv; - rv = imapService->DiscoverAllFolders(queue, rootMsgFolder, this, aMsgWindow, nsnull); + rv = imapService->DiscoverAllFolders(NS_GetCurrentThread(), rootMsgFolder, + this, aMsgWindow, nsnull); return rv; } @@ -2569,19 +2553,13 @@ NS_IMETHODIMP nsImapIncomingServer::OnLogonRedirectionError(const PRUnichar *pEr if (urlQueueCnt > 0) { nsCOMPtr imapProtocol; - nsCOMPtr aEventQueue; - // Get current thread envent queue - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_SUCCEEDED(rv) && pEventQService) - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(aEventQueue)); if (aImapUrl) { nsCOMPtr protocolInstance ; m_waitingForConnectionInfo = PR_FALSE; - rv = GetImapConnection(aEventQueue, aImapUrl, getter_AddRefs(protocolInstance)); + rv = GetImapConnection(NS_GetCurrentThread(), aImapUrl, + getter_AddRefs(protocolInstance)); // If users cancel the login then we need to reset url state. if (rv == NS_BINDING_ABORTED) resetUrlState = PR_TRUE; @@ -2623,14 +2601,7 @@ NS_IMETHODIMP nsImapIncomingServer::OnLogonRedirectionReply(const PRUnichar *pHo PRBool urlRun = PR_FALSE; nsresult rv; nsCOMPtr imapProtocol; - nsCOMPtr aEventQueue; nsCAutoString cookie(pCookieData, pCookieSize); - // Get current thread envent queue - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_SUCCEEDED(rv) && pEventQService) - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(aEventQueue)); // we used to logoff the external requestor...we no longer need to do // that. @@ -2648,7 +2619,8 @@ NS_IMETHODIMP nsImapIncomingServer::OnLogonRedirectionReply(const PRUnichar *pHo nsCOMPtr aConsumer = (nsISupports*)m_urlConsumers.ElementAt(0); nsCOMPtr protocolInstance ; - rv = GetImapConnection(aEventQueue, aImapUrl, getter_AddRefs(protocolInstance)); + rv = GetImapConnection(NS_GetCurrentThread(), aImapUrl, + getter_AddRefs(protocolInstance)); m_waitingForConnectionInfo = PR_FALSE; if (NS_SUCCEEDED(rv) && protocolInstance) { @@ -2950,23 +2922,16 @@ nsImapIncomingServer::SubscribeToFolder(const PRUnichar *aName, PRBool subscribe rv = rootMsgFolder->FindSubFolder(folderCName, getter_AddRefs(msgFolder)); } - nsCOMPtr queue; - // get the Event Queue for this thread... - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - if (NS_FAILED(rv)) return rv; + nsIThread *thread = NS_GetCurrentThread(); nsAutoString unicodeName; rv = CopyMUTF7toUTF16(folderCName, unicodeName); NS_ENSURE_SUCCESS(rv, rv); if (subscribe) - rv = imapService->SubscribeFolder(queue, msgFolder, unicodeName.get(), nsnull, aUri); + rv = imapService->SubscribeFolder(thread, msgFolder, unicodeName.get(), nsnull, aUri); else - rv = imapService->UnsubscribeFolder(queue, msgFolder, unicodeName.get(), nsnull, nsnull); + rv = imapService->UnsubscribeFolder(thread, msgFolder, unicodeName.get(), nsnull, nsnull); if (NS_FAILED(rv)) return rv; return NS_OK; diff --git a/mozilla/mailnews/imap/src/nsImapIncomingServer.h b/mozilla/mailnews/imap/src/nsImapIncomingServer.h index 281f8b70d4d..11b730bbc4e 100644 --- a/mozilla/mailnews/imap/src/nsImapIncomingServer.h +++ b/mozilla/mailnews/imap/src/nsImapIncomingServer.h @@ -51,6 +51,9 @@ #include "nsAdapterEnumerator.h" #include "nsIMsgImapMailFolder.h" #include "nsCOMArray.h" + +class nsIEventTarget; + /* get some implementation from nsMsgIncomingServer */ class nsImapIncomingServer : public nsMsgIncomingServer, public nsIImapIncomingServer, @@ -114,10 +117,10 @@ protected: nsresult GetPFCForStringId(PRBool createIfMissing, PRInt32 stringId, nsIMsgFolder **aFolder); private: nsresult SubscribeToFolder(const PRUnichar *aName, PRBool subscribe); - nsresult GetImapConnection (nsIEventQueue* aEventQueue, + nsresult GetImapConnection (nsIEventTarget* aEventTarget, nsIImapUrl* aImapUrl, nsIImapProtocol** aImapConnection); - nsresult CreateProtocolInstance(nsIEventQueue *aEventQueue, + nsresult CreateProtocolInstance(nsIEventTarget *aEventTarget, nsIImapProtocol ** aImapConnection); nsresult RequestOverrideInfo(nsIMsgWindow *aMsgWindow); nsresult CreateHostSpecificPrefName(const char *prefPrefix, nsCAutoString &prefName); diff --git a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp index 1d5b5559f52..b67107a3ee8 100644 --- a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp +++ b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp @@ -53,7 +53,7 @@ #include "nsMsgDBCID.h" #include "nsMsgFolderFlags.h" #include "nsImapFlagAndUidState.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsIImapUrl.h" #include "nsImapUtils.h" #include "nsMsgUtils.h" @@ -117,7 +117,6 @@ static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); static NS_DEFINE_CID(kCMailDB, NS_MAILDB_CID); static NS_DEFINE_CID(kCImapDB, NS_IMAPDB_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kParseMailMsgStateCID, NS_PARSEMAILMSGSTATE_CID); static NS_DEFINE_CID(kCImapHostSessionList, NS_IIMAPHOSTSESSIONLIST_CID); @@ -221,12 +220,7 @@ nsImapMailFolder::nsImapMailFolder() : nsresult rv; - // Get current thread envent queue - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_SUCCEEDED(rv) && pEventQService) - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(m_eventQueue)); + m_thread = do_GetCurrentThread(); m_moveCoalescer = nsnull; m_boxFlags = 0; m_uidValidity = kUidUnknown; @@ -814,7 +808,7 @@ nsImapMailFolder::UpdateFolder(nsIMsgWindow *msgWindow) if (NS_FAILED(rv)) return rv; nsCOMPtr url; - rv = imapService->SelectFolder(m_eventQueue, this, m_urlListener, msgWindow, getter_AddRefs(url)); + rv = imapService->SelectFolder(m_thread, this, m_urlListener, msgWindow, getter_AddRefs(url)); if (NS_SUCCEEDED(rv)) m_urlRunning = PR_TRUE; if (url) @@ -884,8 +878,7 @@ NS_IMETHODIMP nsImapMailFolder::CreateSubfolder(const PRUnichar* folderName, nsI nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - rv = imapService->CreateFolder(m_eventQueue, this, - folderName, this, nsnull); + rv = imapService->CreateFolder(m_thread, this, folderName, this, nsnull); return rv; } @@ -1036,7 +1029,7 @@ NS_IMETHODIMP nsImapMailFolder::List() nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - rv = imapService->ListFolder(m_eventQueue, this, this, nsnull); + rv = imapService->ListFolder(m_thread, this, this, nsnull); return rv; } @@ -1092,7 +1085,7 @@ NS_IMETHODIMP nsImapMailFolder::CreateStorageIfMissing(nsIUrlListener* urlListen if (NS_SUCCEEDED(rv) && imapService) { nsCOMPtr uri; - imapService->EnsureFolderExists(m_eventQueue, msgParent, folderName.get(), urlListener, getter_AddRefs(uri)); + imapService->EnsureFolderExists(m_thread, msgParent, folderName.get(), urlListener, getter_AddRefs(uri)); } } @@ -1263,7 +1256,7 @@ NS_IMETHODIMP nsImapMailFolder::Compact(nsIUrlListener *aListener, nsIMsgWindow nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - return imapService->Expunge(m_eventQueue, this, aListener, nsnull); + return imapService->Expunge(m_thread, this, aListener, nsnull); } NS_IMETHODIMP nsImapMailFolder::CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow, nsISupportsArray *aFolderArray, PRBool aCompactOfflineAlso, nsISupportsArray *aOfflineFolderArray) @@ -1316,7 +1309,7 @@ NS_IMETHODIMP nsImapMailFolder::UpdateStatus(nsIUrlListener *aListener, nsIMsgWi nsCOMPtr uri; - rv = imapService->UpdateFolderStatus(m_eventQueue, this, aListener, getter_AddRefs(uri)); + rv = imapService->UpdateFolderStatus(m_thread, this, aListener, getter_AddRefs(uri)); if (uri) { nsCOMPtr mailNewsUrl = do_QueryInterface(uri); @@ -1452,14 +1445,14 @@ NS_IMETHODIMP nsImapMailFolder::EmptyTrash(nsIMsgWindow *aMsgWindow, } if (aListener) { - rv = imapService->DeleteAllMessages(m_eventQueue, trashFolder, + rv = imapService->DeleteAllMessages(m_thread, trashFolder, aListener, nsnull); } else { nsCOMPtr urlListener = do_QueryInterface(trashFolder); - rv = imapService->DeleteAllMessages(m_eventQueue, trashFolder, + rv = imapService->DeleteAllMessages(m_thread, trashFolder, urlListener, nsnull); } // return an error if this failed. We want the empty trash on exit code @@ -1578,7 +1571,7 @@ NS_IMETHODIMP nsImapMailFolder::Rename (const PRUnichar *newName, nsIMsgWindow * nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - return imapService->RenameLeaf(m_eventQueue, this, newName, this, msgWindow, + return imapService->RenameLeaf(m_thread, this, newName, this, msgWindow, nsnull); } @@ -2242,7 +2235,7 @@ NS_IMETHODIMP nsImapMailFolder::DeleteMessages(nsISupportsArray *messages, //need to take care of these two delete models nsImapMoveCopyMsgTxn* undoMsgTxn = new nsImapMoveCopyMsgTxn( this, &srcKeyArray, messageIds.get(), nsnull, - PR_TRUE, isMove, m_eventQueue, nsnull); + PR_TRUE, isMove, m_thread, nsnull); if (!undoMsgTxn) return NS_ERROR_OUT_OF_MEMORY; undoMsgTxn->SetTransactionType(nsIMessenger::eDeleteMsg); // we're adding this undo action before the delete is successful. This is evil, @@ -2449,7 +2442,7 @@ nsImapMailFolder::DeleteSubFolders(nsISupportsArray* folders, nsIMsgWindow *msgW { urlListener = do_QueryInterface(curFolder); if (deleteNoTrash) - rv = imapService->DeleteFolder(m_eventQueue, + rv = imapService->DeleteFolder(m_thread, curFolder, urlListener, nsnull); @@ -2464,7 +2457,7 @@ nsImapMailFolder::DeleteSubFolders(nsISupportsArray* folders, nsIMsgWindow *msgW if (!confirm) return NS_OK; } - rv = imapService->MoveFolder(m_eventQueue, + rv = imapService->MoveFolder(m_thread, curFolder, trashFolder, urlListener, @@ -3246,7 +3239,7 @@ NS_IMETHODIMP nsImapMailFolder::EndCopy(PRBool copySucceeded) nsCOMPtr copySupport; if (m_copyState) copySupport = do_QueryInterface(m_copyState); - rv = imapService->AppendMessageFromFile(m_eventQueue, + rv = imapService->AppendMessageFromFile(m_thread, m_copyState->m_tmpFileSpec, this, "", PR_TRUE, m_copyState->m_selectedState, @@ -3551,7 +3544,7 @@ NS_IMETHODIMP nsImapMailFolder::SetImapFlags(const char *uids, PRInt32 flags, ns nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - return imapService->SetMessageFlags(m_eventQueue, this, this, + return imapService->SetMessageFlags(m_thread, this, this, url, uids, flags, PR_TRUE); } @@ -3564,7 +3557,7 @@ NS_IMETHODIMP nsImapMailFolder::PlaybackOfflineFolderCreate(const PRUnichar *aFo nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - return imapService->CreateFolder(m_eventQueue, this, + return imapService->CreateFolder(m_thread, this, aFolderName, this, url); } @@ -3578,7 +3571,7 @@ NS_IMETHODIMP nsImapMailFolder::ReplayOfflineMoveCopy(nsMsgKey *msgKeys, PRUint3 nsCOMPtr resultUrl; nsCAutoString uids; AllocateUidStringFromKeys(msgKeys, numKeys, uids); - rv = imapService->OnlineMessageCopy(m_eventQueue, + rv = imapService->OnlineMessageCopy(m_thread, this, uids.get(), aDstFolder, @@ -3615,12 +3608,12 @@ NS_IMETHODIMP nsImapMailFolder::StoreImapFlags(PRInt32 flags, PRBool addFlags, if (addFlags) { - imapService->AddMessageFlags(m_eventQueue, this, aUrlListener ? aUrlListener : this, + imapService->AddMessageFlags(m_thread, this, aUrlListener ? aUrlListener : this, nsnull, msgIds.get(), flags, PR_TRUE); } else { - imapService->SubtractMessageFlags(m_eventQueue, this, aUrlListener ? aUrlListener : this, + imapService->SubtractMessageFlags(m_thread, this, aUrlListener ? aUrlListener : this, nsnull, msgIds.get(), flags, PR_TRUE); } @@ -3661,7 +3654,7 @@ NS_IMETHODIMP nsImapMailFolder::LiteSelect(nsIUrlListener *aUrlListener) nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - return imapService->LiteSelectFolder(m_eventQueue, this, aUrlListener, nsnull); + return imapService->LiteSelectFolder(m_thread, this, aUrlListener, nsnull); } nsresult nsImapMailFolder::GetFolderOwnerUserName(char **userName) @@ -3808,7 +3801,7 @@ NS_IMETHODIMP nsImapMailFolder::FolderPrivileges(nsIMsgWindow *window) nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - rv = imapService->GetFolderAdminUrl(m_eventQueue, this, window, this, nsnull); + rv = imapService->GetFolderAdminUrl(m_thread, this, window, this, nsnull); if (NS_SUCCEEDED(rv)) m_urlRunning = PR_TRUE; } @@ -3853,7 +3846,7 @@ NS_IMETHODIMP nsImapMailFolder::IssueCommandOnMsgs(const char *command, const ch nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - return imapService->IssueCommandOnMsgs(m_eventQueue, this, aWindow, command, uids, url); + return imapService->IssueCommandOnMsgs(m_thread, this, aWindow, command, uids, url); } NS_IMETHODIMP nsImapMailFolder::FetchCustomMsgAttribute(const char *attribute, const char *uids, nsIMsgWindow *aWindow, nsIURI **url) @@ -3862,7 +3855,7 @@ NS_IMETHODIMP nsImapMailFolder::FetchCustomMsgAttribute(const char *attribute, c nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - return imapService->FetchCustomMsgAttribute(m_eventQueue, this, aWindow, attribute, uids, url); + return imapService->FetchCustomMsgAttribute(m_thread, this, aWindow, attribute, uids, url); } nsresult nsImapMailFolder::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr, @@ -4214,7 +4207,7 @@ NS_IMETHODIMP nsImapMailFolder::DownloadAllForOffline(nsIUrlListener *listener, // selecting the folder with m_downloadingFolderForOfflineUse true will cause // us to fetch any message bodies we don't have. - rv = imapService->SelectFolder(m_eventQueue, this, listener, msgWindow, nsnull); + rv = imapService->SelectFolder(m_thread, this, listener, msgWindow, nsnull); if (NS_SUCCEEDED(rv)) m_urlRunning = PR_TRUE; } @@ -4347,7 +4340,7 @@ nsImapMailFolder::OnlineCopyCompleted(nsIImapProtocol *aProtocol, ImapOnlineCopy do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); - rv = imapService->AddMessageFlags(m_eventQueue, this, nsnull, nsnull, + rv = imapService->AddMessageFlags(m_thread, this, nsnull, nsnull, messageIds, kImapMsgDeletedFlag, PR_TRUE); @@ -6321,7 +6314,7 @@ nsImapMailFolder::CopyMessagesWithStream(nsIMsgFolder* srcFolder, nsImapMoveCopyMsgTxn* undoMsgTxn = new nsImapMoveCopyMsgTxn( srcFolder, &srcKeyArray, messageIds.get(), this, - PR_TRUE, isMove, m_eventQueue, urlListener); + PR_TRUE, isMove, m_thread, urlListener); if (!undoMsgTxn) return NS_ERROR_OUT_OF_MEMORY; if (isMove) @@ -6627,7 +6620,7 @@ nsresult nsImapMailFolder::CopyMessagesOffline(nsIMsgFolder* srcFolder, rv = QueryInterface(NS_GET_IID(nsIUrlListener), getter_AddRefs(urlListener)); nsImapOfflineTxn *undoMsgTxn = new nsImapOfflineTxn(srcFolder, &srcKeyArray, this, isMove, opType, message, - m_eventQueue, urlListener); + m_thread, urlListener); if (undoMsgTxn) { @@ -6700,7 +6693,7 @@ nsresult nsImapMailFolder::CopyMessagesOffline(nsIMsgFolder* srcFolder, keyArray.Add(fakeBase + sourceKeyIndex); nsImapOfflineTxn *undoMsgTxn = new nsImapOfflineTxn(this, &keyArray, this, isMove, nsIMsgOfflineImapOperation::kAddedHeader, - newMailHdr, m_eventQueue, urlListener); + newMailHdr, m_thread, urlListener); if (undoMsgTxn) { if (txnMgr) @@ -6731,7 +6724,7 @@ nsresult nsImapMailFolder::CopyMessagesOffline(nsIMsgFolder* srcFolder, srcKeyArray.Add(msgKey); nsImapOfflineTxn *undoMsgTxn = new nsImapOfflineTxn(srcFolder, &srcKeyArray, this, isMove, opType, mailHdr, - m_eventQueue, urlListener); + m_thread, urlListener); if (undoMsgTxn) { if (isMove) @@ -6891,7 +6884,7 @@ nsImapMailFolder::CopyMessages(nsIMsgFolder* srcFolder, copySupport = do_QueryInterface(m_copyState); if (imapService) - rv = imapService->OnlineMessageCopy(m_eventQueue, + rv = imapService->OnlineMessageCopy(m_thread, srcFolder, messageIds.get(), this, PR_TRUE, isMove, urlListener, nsnull, @@ -6901,7 +6894,7 @@ nsImapMailFolder::CopyMessages(nsIMsgFolder* srcFolder, { nsImapMoveCopyMsgTxn* undoMsgTxn = new nsImapMoveCopyMsgTxn( srcFolder, &srcKeyArray, messageIds.get(), this, - PR_TRUE, isMove, m_eventQueue, urlListener); + PR_TRUE, isMove, m_thread, urlListener); if (!undoMsgTxn) return NS_ERROR_OUT_OF_MEMORY; if (isMove) { @@ -6991,16 +6984,10 @@ nsImapFolderCopyState::StartNextCopy() nsXPIDLString folderName; m_srcFolder->GetName(getter_Copies(folderName)); - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - nsCOMPtr eventQueue; - if (NS_SUCCEEDED(rv) && pEventQService) - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(eventQueue)); - - rv = imapService->EnsureFolderExists(eventQueue, m_destParent, - folderName.get(), - this, nsnull); + rv = imapService->EnsureFolderExists(NS_GetCurrentThread(), + m_destParent, + folderName.get(), + this, nsnull); } return rv; } @@ -7282,7 +7269,7 @@ nsImapMailFolder::CopyFolder(nsIMsgFolder* srcFolder, return NS_OK; } } - rv = imapService->MoveFolder(m_eventQueue, + rv = imapService->MoveFolder(m_thread, srcFolder, this, urlListener, @@ -7346,7 +7333,7 @@ nsImapMailFolder::CopyFileMessage(nsIFileSpec* fileSpec, copySupport = do_QueryInterface(m_copyState); if (!isDraftOrTemplate) m_copyState->m_totalCount = 1; - rv = imapService->AppendMessageFromFile(m_eventQueue, fileSpec, this, + rv = imapService->AppendMessageFromFile(m_thread, fileSpec, this, messageId.get(), PR_TRUE, isDraftOrTemplate, urlListener, nsnull, @@ -7833,7 +7820,7 @@ NS_IMETHODIMP nsImapMailFolder::PerformExpand(nsIMsgWindow *aMsgWindow) nsCOMPtr imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) - rv = imapService->DiscoverChildren(m_eventQueue, this, this, + rv = imapService->DiscoverChildren(m_thread, this, this, m_onlineFolderName.get(), nsnull); } @@ -8166,7 +8153,7 @@ nsImapMailFolder::StoreCustomKeywords(nsIMsgWindow *aMsgWindow, const char *aFla NS_ENSURE_SUCCESS(rv, rv); nsCAutoString msgIds; AllocateUidStringFromKeys(aKeysToStore, aNumKeys, msgIds); - return imapService->StoreCustomKeywords(m_eventQueue, this, aMsgWindow, aFlagsToAdd, aFlagsToSubtract, msgIds.get(), _retval); + return imapService->StoreCustomKeywords(m_thread, this, aMsgWindow, aFlagsToAdd, aFlagsToSubtract, msgIds.get(), _retval); } NS_IMETHODIMP nsImapMailFolder::NotifyIfNewMail() @@ -8477,7 +8464,7 @@ NS_IMETHODIMP nsImapMailFolder::FetchMsgPreviewText(nsMsgKey *aKeysToFetch, PRUi AllocateImapUidString(keysToFetchFromServer.GetArray(), msgCount, nsnull, messageIds); - rv = imapService->GetBodyStart(m_eventQueue, this, aUrlListener, + rv = imapService->GetBodyStart(m_thread, this, aUrlListener, messageIds.get(), 2048, nsnull); *aAsyncResults = PR_TRUE; // the preview text will be available async... } diff --git a/mozilla/mailnews/imap/src/nsImapMailFolder.h b/mozilla/mailnews/imap/src/nsImapMailFolder.h index d334a6844c6..6c89807347d 100644 --- a/mozilla/mailnews/imap/src/nsImapMailFolder.h +++ b/mozilla/mailnews/imap/src/nsImapMailFolder.h @@ -54,12 +54,13 @@ #include "nsIMsgFilterList.h" #include "nsIMsgFilterPlugin.h" #include "prmon.h" -#include "nsIEventQueue.h" #include "nsIMsgImapMailFolder.h" #include "nsIMsgLocalMailFolder.h" #include "nsIImapMailFolderSink.h" #include "nsIImapServerSink.h" #include "nsIMsgFilterPlugin.h" +#include "nsIEventTarget.h" +#include "nsIThread.h" class nsImapMoveCoalescer; class nsHashtable; class nsHashKey; @@ -441,7 +442,7 @@ protected: PRInt32 m_numStatusRecentMessages; // used to store counts from Status command PRInt32 m_numStatusUnseenMessages; PRInt32 m_nextMessageByteLength; - nsCOMPtr m_eventQueue; + nsCOMPtr m_thread; nsCOMPtr m_urlListener; PRBool m_urlRunning; diff --git a/mozilla/mailnews/imap/src/nsImapProtocol.cpp b/mozilla/mailnews/imap/src/nsImapProtocol.cpp index ba1d3b9d71d..a1ab3d509e5 100644 --- a/mozilla/mailnews/imap/src/nsImapProtocol.cpp +++ b/mozilla/mailnews/imap/src/nsImapProtocol.cpp @@ -53,13 +53,12 @@ #include "nsIStringBundle.h" #include "nsMsgImapCID.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsISupportsObsolete.h" #include "nsImapCore.h" #include "nsImapProtocol.h" #include "nsIMsgMailNewsUrl.h" -#include "nscore.h" #include "nsIMAPHostSessionList.h" #include "nsIMAPBodyShell.h" #include "nsImapMailFolder.h" @@ -69,6 +68,7 @@ #include "nsIImapService.h" #include "nsISocketTransportService.h" #include "nsIStreamListenerTee.h" +#include "nsXPCOMCIDInternal.h" #include "nsNetUtil.h" #include "nsXPIDLString.h" #include "nsReadableUtils.h" @@ -106,15 +106,13 @@ PRLogModuleInfo *IMAP; #include "nsIProxyObjectManager.h" #include "nsIStreamConverterService.h" #include "nsIProxyInfo.h" -#include "nsEventQueueUtils.h" #include "nsISSLSocketControl.h" +#include "nsProxyRelease.h" #define ONE_SECOND ((PRUint32)1000) // one second static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID); -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID); #define OUTPUT_BUFFER_SIZE (4096*2) // mscott - i should be able to remove this if I can use nsMsgLineBuffer??? @@ -473,11 +471,11 @@ nsresult nsImapProtocol::Configure(PRInt32 TooFastTime, PRInt32 IdealTime, nsresult nsImapProtocol::Initialize(nsIImapHostSessionList * aHostSessionList, nsIImapIncomingServer *aServer, - nsIEventQueue * aSinkEventQueue) + nsIEventTarget * aSinkEventTarget) { - NS_PRECONDITION(aSinkEventQueue && aHostSessionList, - "oops...trying to initialize with a null sink event queue!"); - if (!aSinkEventQueue || !aHostSessionList || !aServer) + NS_PRECONDITION(aSinkEventTarget && aHostSessionList, + "oops...trying to initialize with a null sink event target!"); + if (!aSinkEventTarget || !aHostSessionList || !aServer) return NS_ERROR_NULL_POINTER; nsresult rv = m_downloadLineCache.GrowBuffer(kDownLoadCacheSize); @@ -490,7 +488,7 @@ nsresult nsImapProtocol::Initialize(nsIImapHostSessionList * aHostSessionList, n aServer->GetUseIdle(&m_useIdle); NS_ADDREF(m_flagState); - m_sinkEventQueue = aSinkEventQueue; + m_sinkEventTarget = aSinkEventTarget; m_hostSessionList = aHostSessionList; // no ref count...host session list has life time > connection m_parser.SetHostSessionList(aHostSessionList); m_parser.SetFlagState(m_flagState); @@ -613,9 +611,9 @@ nsImapProtocol::SetupSinkProxy() if (m_runningUrl) { - NS_ASSERTION(m_sinkEventQueue && m_thread, "fatal... null sink event queue or thread"); + NS_ASSERTION(m_sinkEventTarget && m_thread, "fatal... null sink event queue or thread"); - nsCOMPtr proxyManager(do_GetService(kProxyObjectManagerCID, &res)); + nsCOMPtr proxyManager(do_GetService(NS_XPCOMPROXY_CONTRACTID, &res)); if (proxyManager) // if we don't get one of these are as good as dead... { if (!m_imapMailFolderSink) @@ -623,10 +621,10 @@ nsImapProtocol::SetupSinkProxy() nsCOMPtr aImapMailFolderSink; res = m_runningUrl->GetImapMailFolderSink(getter_AddRefs(aImapMailFolderSink)); if (NS_SUCCEEDED(res) && aImapMailFolderSink) - res = proxyManager->GetProxyForObject(m_sinkEventQueue, + res = proxyManager->GetProxyForObject(m_sinkEventTarget, NS_GET_IID(nsIImapMailFolderSink), aImapMailFolderSink, - PROXY_SYNC | PROXY_ALWAYS, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(m_imapMailFolderSink)); } @@ -635,10 +633,10 @@ nsImapProtocol::SetupSinkProxy() nsCOMPtr aImapMessageSink; res = m_runningUrl->GetImapMessageSink(getter_AddRefs(aImapMessageSink)); if (NS_SUCCEEDED(res) && aImapMessageSink) - res = proxyManager->GetProxyForObject(m_sinkEventQueue, + res = proxyManager->GetProxyForObject(m_sinkEventTarget, NS_GET_IID(nsIImapMessageSink), aImapMessageSink, - PROXY_SYNC | PROXY_ALWAYS, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(m_imapMessageSink)); } if (!m_imapServerSink) @@ -646,10 +644,10 @@ nsImapProtocol::SetupSinkProxy() nsCOMPtr aImapServerSink; res = m_runningUrl->GetImapServerSink(getter_AddRefs(aImapServerSink)); if (NS_SUCCEEDED(res) && aImapServerSink) - res = proxyManager->GetProxyForObject( m_sinkEventQueue, + res = proxyManager->GetProxyForObject( m_sinkEventTarget, NS_GET_IID(nsIImapServerSink), aImapServerSink, - PROXY_SYNC | PROXY_ALWAYS, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(m_imapServerSink)); NS_ASSERTION(NS_SUCCEEDED(res), "couldn't get proxies"); } @@ -715,7 +713,12 @@ nsresult nsImapProtocol::SetupWithUrl(nsIURI * aURL, nsISupports* aConsumer) if (aRealStreamListener) { NS_ASSERTION(!m_channelListener, "shouldn't already have a channel listener"); - rv = NS_NewAsyncStreamListener(getter_AddRefs(m_channelListener), aRealStreamListener, m_sinkEventQueue); + rv = NS_GetProxyForObject(m_sinkEventTarget, + NS_GET_IID(nsIStreamListener), + aRealStreamListener, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, + getter_AddRefs(m_channelListener)); + if (NS_FAILED(rv)) return rv; } PRUint32 capability = kCapabilityUndefined; @@ -824,9 +827,8 @@ nsresult nsImapProtocol::SetupWithUrl(nsIURI * aURL, nsISupports* aConsumer) nsCOMPtr sink = do_QueryInterface(m_mockChannel); if (sink) { - nsCOMPtr eventQ; - NS_GetMainEventQ(getter_AddRefs(eventQ)); - m_transport->SetEventSink(sink, eventQ); + nsCOMPtr thread = do_GetMainThread(); + m_transport->SetEventSink(sink, thread); } // and if we have a cache entry that we are saving the message to, set the security info on it too. @@ -866,7 +868,16 @@ void nsImapProtocol::ReleaseUrlState(PRBool rerunning) } m_channelContext = nsnull; // this might be the url - null it out before the final release of the url m_imapMessageSink = nsnull; - m_channelListener = nsnull; + + // Proxy the release of the listener to the main thread. This is something + // that the xpcom proxy system should do for us! + if (m_channelListener) + { + nsCOMPtr thread = do_GetMainThread(); + nsIStreamListener *doomed = nsnull; + m_channelListener.swap(doomed); + NS_ProxyRelease(thread, doomed); + } m_channelInputStream = nsnull; m_channelOutputStream = nsnull; @@ -910,6 +921,19 @@ void nsImapProtocol::ReleaseUrlState(PRBool rerunning) } +class nsImapThreadShutdownEvent : public nsRunnable { +public: + nsImapThreadShutdownEvent(nsIThread *thread) : mThread(thread) { + } + NS_IMETHOD Run() { + mThread->Shutdown(); + return NS_OK; + } +private: + nsCOMPtr mThread; +}; + + NS_IMETHODIMP nsImapProtocol::Run() { nsImapProtocol *me = this; @@ -933,11 +957,15 @@ NS_IMETHODIMP nsImapProtocol::Run() me->m_runningUrl = nsnull; CloseStreams(); - me->m_sinkEventQueue = nsnull; + me->m_sinkEventTarget = nsnull; me->m_imapMailFolderSink = nsnull; me->m_imapMessageSink = nsnull; - m_iThread = nsnull; + // shutdown this thread, but do it from the main thread + nsCOMPtr ev = new nsImapThreadShutdownEvent(m_iThread); + if (NS_FAILED(NS_DispatchToMainThread(ev))) + NS_WARNING("Failed to dispatch nsImapThreadShutdownEvent"); + m_iThread = nsnull; return NS_OK; } @@ -1428,8 +1456,11 @@ PRBool nsImapProtocol::ProcessCurrentURL() { nsCOMPtr request = do_QueryInterface(m_mockChannel); NS_ASSERTION(request, "no request"); - if (request) - rv = m_channelListener->OnStopRequest(request, m_channelContext, NS_OK); + if (request) { + nsresult status; + request->GetStatus(&status); + rv = m_channelListener->OnStopRequest(request, m_channelContext, status); + } } SetFlag(IMAP_CLEAN_UP_URL_STATE); @@ -3593,6 +3624,8 @@ void nsImapProtocol::ProcessMailboxUpdate(PRBool handlePossibleUndo) if (NS_SUCCEEDED(res) && imapAction == nsIImapUrl::nsImapLiteSelectFolder) return; } + + PRBool entered_waitForBodyIdsMonitor = PR_FALSE; nsImapMailboxSpec *new_spec = GetServerStateParser().CreateCurrentMailboxSpec(); if (new_spec && !DeathSignalReceived()) @@ -3604,6 +3637,7 @@ void nsImapProtocol::ProcessMailboxUpdate(PRBool handlePossibleUndo) if (NS_SUCCEEDED(res) && imapAction == nsIImapUrl::nsImapExpungeFolder) new_spec->box_flags |= kJustExpunged; PR_EnterMonitor(m_waitForBodyIdsMonitor); + entered_waitForBodyIdsMonitor = PR_TRUE; UpdatedMailboxSpec(new_spec); } } @@ -3618,7 +3652,7 @@ void nsImapProtocol::ProcessMailboxUpdate(PRBool handlePossibleUndo) { WaitForPotentialListOfMsgsToFetch(&msgIdList, msgCount); - if (new_spec) + if (entered_waitForBodyIdsMonitor) PR_ExitMonitor(m_waitForBodyIdsMonitor); if (msgIdList && !DeathSignalReceived() && GetServerStateParser().LastCommandSuccessful()) @@ -3630,7 +3664,7 @@ void nsImapProtocol::ProcessMailboxUpdate(PRBool handlePossibleUndo) // this might be bogus, how are we going to do pane notification and stuff when we fetch bodies without // headers! } - else if (new_spec) // need to exit this monitor if death signal received + else if (entered_waitForBodyIdsMonitor) // need to exit this monitor if death signal received PR_ExitMonitor(m_waitForBodyIdsMonitor); // wait for a list of bodies to fetch. @@ -8295,14 +8329,8 @@ nsresult nsImapMockChannel::ReadFromImapConnection() NS_ENSURE_SUCCESS(rv, rv); // Assume AsyncRead is always called from the UI thread..... - nsCOMPtr queue; - // get the Event Queue for this thread... - nsCOMPtr pEventQService (do_GetService(kEventQueueServiceCID, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - NS_ENSURE_SUCCESS(rv, rv); - rv = imapServer->GetImapConnectionAndLoadUrl(queue, imapUrl, nsnull); + rv = imapServer->GetImapConnectionAndLoadUrl(NS_GetCurrentThread(), imapUrl, + nsnull); return rv; } diff --git a/mozilla/mailnews/imap/src/nsImapProtocol.h b/mozilla/mailnews/imap/src/nsImapProtocol.h index da074045198..9537a584dd0 100644 --- a/mozilla/mailnews/imap/src/nsImapProtocol.h +++ b/mozilla/mailnews/imap/src/nsImapProtocol.h @@ -43,7 +43,7 @@ #include "nsIImapUrl.h" #include "nsMsgProtocol.h" -#include "nsIEventQueue.h" +#include "nsIEventTarget.h" #include "nsIStreamListener.h" #include "nsIOutputStream.h" #include "nsIOutputStream.h" @@ -64,7 +64,6 @@ #include "nsIImapMiscellaneousSink.h" #include "nsImapServerResponseParser.h" -#include "nsImapProxyEvent.h" #include "nsImapFlagAndUidState.h" #include "nsIMAPNamespace.h" #include "nsVoidArray.h" @@ -353,8 +352,8 @@ private: // ******* Thread support ******* - nsCOMPtr m_sinkEventQueue; - nsCOMPtr m_iThread; + nsCOMPtr m_sinkEventTarget; + nsCOMPtr m_iThread; PRThread *m_thread; PRMonitor *m_dataAvailableMonitor; // used to notify the arrival of data from the server PRMonitor *m_urlReadyToRunMonitor; // used to notify the arrival of a new url to be processed diff --git a/mozilla/mailnews/imap/src/nsImapProxyEvent.cpp b/mozilla/mailnews/imap/src/nsImapProxyEvent.cpp deleted file mode 100644 index 6bb0228c683..00000000000 --- a/mozilla/mailnews/imap/src/nsImapProxyEvent.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nscore.h" -#include "msgCore.h" // precompiled header -#include "nspr.h" - -#include "nsIEventQueueService.h" - -#include "nsIImapMailFolderSink.h" -#include "nsIImapMessageSink.h" -#include "nsIImapExtensionSink.h" -#include "nsIImapUrl.h" -#include "nsIImapMiscellaneousSink.h" -#include "nsImapProxyEvent.h" -#include "nsIMAPNamespace.h" -#include "nsImapCore.h" -#include "nsCOMPtr.h" - -nsImapEvent::nsImapEvent() -{ - m_notifyCompletion = PR_FALSE; -} - -nsImapEvent::~nsImapEvent() -{ -} - -void -nsImapEvent::SetNotifyCompletion(PRBool notifyCompletion) -{ - m_notifyCompletion = notifyCompletion; -} - -void -nsImapEvent::InitEvent() -{ - PL_InitEvent(this, nsnull, imap_event_handler, imap_event_destructor); -} - -void -nsImapEvent::PostEvent(nsIEventQueue* aEventQ) -{ - NS_PRECONDITION(nsnull != aEventQ, "PostEvent: aEventQ is null"); - - InitEvent(); - aEventQ->PostEvent(this); -} - -void* PR_CALLBACK -nsImapEvent::imap_event_handler(PLEvent *aEvent) -{ - nsImapEvent* ev = (nsImapEvent*) aEvent; - ev->HandleEvent(); - return nsnull; -} - -void PR_CALLBACK -nsImapEvent::imap_event_destructor(PLEvent *aEvent) -{ - nsImapEvent* ev = (nsImapEvent*) aEvent; - delete ev; -} - -nsImapProxyBase::nsImapProxyBase(nsIImapProtocol* aProtocol, - nsIEventQueue* aEventQ, - PRThread* aThread) -{ - NS_ASSERTION (aProtocol && aEventQ && aThread, - "nsImapProxy: invalid aProtocol, aEventQ, or aThread"); - - m_protocol = aProtocol; - NS_IF_ADDREF(m_protocol); - - m_eventQueue = aEventQ; - NS_IF_ADDREF(m_eventQueue); - - m_thread = aThread; -} - -nsImapProxyBase::~nsImapProxyBase() -{ - NS_IF_RELEASE (m_protocol); - NS_IF_RELEASE(m_eventQueue); -} - diff --git a/mozilla/mailnews/imap/src/nsImapProxyEvent.h b/mozilla/mailnews/imap/src/nsImapProxyEvent.h deleted file mode 100644 index 216f3f64eb9..00000000000 --- a/mozilla/mailnews/imap/src/nsImapProxyEvent.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsImapProxyEvent_h__ -#define nsImapProxyEvent_h__ - -#include "plevent.h" -#include "prthread.h" -#include "nsISupports.h" -#include "nsIURL.h" -#include "nsIImapMailFolderSink.h" -#include "nsIImapMessageSink.h" -#include "nsIImapMiscellaneousSink.h" -#include "nsIImapIncomingServer.h" -#include "nsImapCore.h" -#include "nsIImapUrl.h" -#include "nsIImapMailFolderSink.h" -#include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later... - - -#include "nsCOMPtr.h" -class nsImapProxyBase -{ -public: - nsImapProxyBase(nsIImapProtocol* aProtocol, - nsIEventQueue* aEventQ, - PRThread* aThread); - virtual ~nsImapProxyBase(); - - nsIEventQueue* m_eventQueue; - PRThread* m_thread; - nsIImapProtocol* m_protocol; -}; - -/* ******* Imap Base Event struct ******** */ -struct nsImapEvent : public PLEvent -{ - nsImapEvent(); - virtual ~nsImapEvent(); - virtual void InitEvent(); - - NS_IMETHOD HandleEvent() = 0; - void PostEvent(nsIEventQueue* aEventQ); - virtual void SetNotifyCompletion(PRBool notifyCompletion); - - static void* PR_CALLBACK imap_event_handler(PLEvent* aEvent); - static void PR_CALLBACK imap_event_destructor(PLEvent *aEvent); - PRBool m_notifyCompletion; -}; - - -#endif diff --git a/mozilla/mailnews/imap/src/nsImapService.cpp b/mozilla/mailnews/imap/src/nsImapService.cpp index ed3deadb34f..49081fb8b27 100644 --- a/mozilla/mailnews/imap/src/nsImapService.cpp +++ b/mozilla/mailnews/imap/src/nsImapService.cpp @@ -57,7 +57,6 @@ #include "nsIDocShell.h" #include "nsIDocShellLoadInfo.h" #include "nsIRDFService.h" -#include "nsIEventQueueService.h" #include "nsXPIDLString.h" #include "nsReadableUtils.h" #include "nsRDFCID.h" @@ -100,13 +99,13 @@ #include "nsImapProtocol.h" #include "nsIMsgMailSession.h" #include "nsIStreamConverterService.h" +#include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsInt64.h" #define PREF_MAIL_ROOT_IMAP "mail.root.imap" // old - for backward compatibility only #define PREF_MAIL_ROOT_IMAP_REL "mail.root.imap-rel" -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kImapUrlCID, NS_IMAPURL_CID); static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID); @@ -202,15 +201,15 @@ nsImapService::GetFolderName(nsIMsgFolder* aImapFolder, } NS_IMETHODIMP -nsImapService::SelectFolder(nsIEventQueue * aClientEventQueue, +nsImapService::SelectFolder(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIMsgWindow *aMsgWindow, nsIURI ** aURL) { - NS_ASSERTION (aImapMailFolder && aClientEventQueue, + NS_ASSERTION (aImapMailFolder && aClientEventTarget, "Oops ... null pointer"); - if (!aImapMailFolder || !aClientEventQueue) + if (!aImapMailFolder || !aClientEventTarget) return NS_ERROR_NULL_POINTER; if (WeAreOffline()) @@ -253,7 +252,7 @@ nsImapService::SelectFolder(nsIEventQueue * aClientEventQueue, urlSpec.Append((const char *) folderName); rv = mailNewsUrl->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); @@ -265,12 +264,12 @@ nsImapService::SelectFolder(nsIEventQueue * aClientEventQueue, // lite select, used to verify UIDVALIDITY while going on/offline NS_IMETHODIMP -nsImapService::LiteSelectFolder(nsIEventQueue * aClientEventQueue, +nsImapService::LiteSelectFolder(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL) { - return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener, + return FolderCommand(aClientEventTarget, aImapMailFolder, aUrlListener, "/liteselect>", nsIImapUrl::nsImapLiteSelectFolder, aURL); } @@ -693,16 +692,8 @@ nsresult nsImapService::FetchMimePart(nsIImapUrl * aImapUrl, #if defined(DEBUG_mscott) || defined(DEBUG_bienvenu) NS_ASSERTION(0, "oops...someone still is reaching this part of the code"); #endif - nsCOMPtr queue; - // get the Event Queue for this thread... - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - - if (NS_FAILED(rv)) return rv; - - rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - if (NS_FAILED(rv)) return rv; - rv = GetImapConnectionAndLoadUrl(queue, aImapUrl, aDisplayConsumer, aURL); + rv = GetImapConnectionAndLoadUrl(NS_GetCurrentThread(), aImapUrl, + aDisplayConsumer, aURL); } } } @@ -858,16 +849,8 @@ NS_IMETHODIMP nsImapService::Search(nsIMsgSearchSession *aSearchSession, nsIMsgW rv = mailNewsUrl->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) { - nsCOMPtr queue; - // get the Event Queue for this thread... - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - - if (NS_FAILED(rv)) return rv; - - rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - if (NS_FAILED(rv)) return rv; - rv = GetImapConnectionAndLoadUrl(queue, imapUrl, nsnull, nsnull); + rv = GetImapConnectionAndLoadUrl(NS_GetCurrentThread(), imapUrl, + nsnull, nsnull); } } return rv; @@ -1101,16 +1084,8 @@ nsImapService::FetchMessage(nsIImapUrl * aImapUrl, #if defined(DEBUG_mscott) || defined(DEBUG_bienvenu) NS_ASSERTION(0, "oops...someone still is reaching this part of the code"); #endif - nsCOMPtr queue; - // get the Event Queue for this thread... - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - - if (NS_FAILED(rv)) return rv; - - rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - if (NS_FAILED(rv)) return rv; - rv = GetImapConnectionAndLoadUrl(queue, aImapUrl, aDisplayConsumer, aURL); + rv = GetImapConnectionAndLoadUrl(NS_GetCurrentThread(), aImapUrl, + aDisplayConsumer, aURL); } } return rv; @@ -1254,7 +1229,7 @@ nsImapService::CreateStartOfImapUrl(const char * aImapURI, nsIImapUrl ** imapUrl /* 'x' is the message UID or sequence number list */ /* will not affect the 'SEEN' flag */ NS_IMETHODIMP -nsImapService::GetHeaders(nsIEventQueue * aClientEventQueue, +nsImapService::GetHeaders(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL, @@ -1264,9 +1239,9 @@ nsImapService::GetHeaders(nsIEventQueue * aClientEventQueue, // create a protocol instance to handle the request. // NOTE: once we start working with multiple connections, this step will be much more complicated...but for now // just create a connection and process the request. - NS_ASSERTION (aImapMailFolder && aClientEventQueue, + NS_ASSERTION (aImapMailFolder && aClientEventTarget, "Oops ... null pointer"); - if (!aImapMailFolder || !aClientEventQueue) + if (!aImapMailFolder || !aClientEventTarget) return NS_ERROR_NULL_POINTER; nsCOMPtr imapUrl; @@ -1298,7 +1273,7 @@ nsImapService::GetHeaders(nsIEventQueue * aClientEventQueue, rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); } @@ -1313,7 +1288,7 @@ nsImapService::GetHeaders(nsIEventQueue * aClientEventQueue, /* 'n' is the number of bytes to fetch */ /* will not affect the 'SEEN' flag */ NS_IMETHODIMP -nsImapService::GetBodyStart(nsIEventQueue * aClientEventQueue, +nsImapService::GetBodyStart(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, const char *messageIdentifierList, @@ -1321,9 +1296,9 @@ nsImapService::GetBodyStart(nsIEventQueue * aClientEventQueue, nsIURI ** aURL) { nsresult rv; - NS_ASSERTION (aImapMailFolder && aClientEventQueue, + NS_ASSERTION (aImapMailFolder && aClientEventTarget, "Oops ... null pointer"); - if (!aImapMailFolder || !aClientEventQueue) + if (!aImapMailFolder || !aClientEventTarget) return NS_ERROR_NULL_POINTER; nsCOMPtr imapUrl; @@ -1357,23 +1332,23 @@ nsImapService::GetBodyStart(nsIEventQueue * aClientEventQueue, urlSpec.AppendInt(numBytes); rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); } } return rv; } -nsresult nsImapService::FolderCommand(nsIEventQueue * clientEventQueue, +nsresult nsImapService::FolderCommand(nsIEventTarget * clientEventTarget, nsIMsgFolder * imapMailFolder, nsIUrlListener * urlListener, const char *command, nsImapAction imapAction, nsIURI ** url) { - NS_ASSERTION (imapMailFolder && clientEventQueue, + NS_ASSERTION (imapMailFolder && clientEventTarget, "Oops ... null pointer"); - if (!imapMailFolder || !clientEventQueue) + if (!imapMailFolder || !clientEventTarget) return NS_ERROR_NULL_POINTER; nsCOMPtr imapUrl; @@ -1401,7 +1376,7 @@ nsresult nsImapService::FolderCommand(nsIEventQueue * clientEventQueue, urlSpec.Append((const char *) folderName); rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(clientEventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(clientEventTarget, imapUrl, nsnull, url); } } @@ -1410,40 +1385,40 @@ nsresult nsImapService::FolderCommand(nsIEventQueue * clientEventQueue, // Noop, used to update a folder (causes server to send changes). NS_IMETHODIMP -nsImapService::Noop(nsIEventQueue * aClientEventQueue, +nsImapService::Noop(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL) { - return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener, + return FolderCommand(aClientEventTarget, aImapMailFolder, aUrlListener, "/selectnoop>", nsIImapUrl::nsImapSelectNoopFolder, aURL); } // FolderStatus, used to update message counts NS_IMETHODIMP -nsImapService::UpdateFolderStatus(nsIEventQueue * aClientEventQueue, +nsImapService::UpdateFolderStatus(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL) { - return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener, + return FolderCommand(aClientEventTarget, aImapMailFolder, aUrlListener, "/folderstatus>", nsIImapUrl::nsImapFolderStatus, aURL); } // Expunge, used to "compress" an imap folder,removes deleted messages. NS_IMETHODIMP -nsImapService::Expunge(nsIEventQueue * aClientEventQueue, +nsImapService::Expunge(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL) { - return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener, + return FolderCommand(aClientEventTarget, aImapMailFolder, aUrlListener, "/Expunge>", nsIImapUrl::nsImapExpungeFolder, aURL); } /* old-stle biff that doesn't download headers */ NS_IMETHODIMP -nsImapService::Biff(nsIEventQueue * aClientEventQueue, +nsImapService::Biff(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL, @@ -1451,9 +1426,9 @@ nsImapService::Biff(nsIEventQueue * aClientEventQueue, { // static const char *formatString = "biff>%c%s>%ld"; - NS_ASSERTION (aImapMailFolder && aClientEventQueue, + NS_ASSERTION (aImapMailFolder && aClientEventTarget, "Oops ... null pointer"); - if (!aImapMailFolder || !aClientEventQueue) + if (!aImapMailFolder || !aClientEventTarget) return NS_ERROR_NULL_POINTER; nsCOMPtr imapUrl; @@ -1483,7 +1458,7 @@ nsImapService::Biff(nsIEventQueue * aClientEventQueue, urlSpec.AppendInt(uidHighWater); rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); } } @@ -1491,7 +1466,7 @@ nsImapService::Biff(nsIEventQueue * aClientEventQueue, } NS_IMETHODIMP -nsImapService::DeleteFolder(nsIEventQueue* aClientEventQueue, +nsImapService::DeleteFolder(nsIEventTarget* aClientEventTarget, nsIMsgFolder* aImapMailFolder, nsIUrlListener* aUrlListener, nsIURI** aURL) @@ -1508,14 +1483,14 @@ nsImapService::DeleteFolder(nsIEventQueue* aClientEventQueue, imapServer->GetIsAOLServer(&removeFolderAndMsgs); } - return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener, + return FolderCommand(aClientEventTarget, aImapMailFolder, aUrlListener, removeFolderAndMsgs ? "/deletefolder>": "/delete>", nsIImapUrl::nsImapDeleteFolder, aURL); } NS_IMETHODIMP -nsImapService::DeleteMessages(nsIEventQueue * aClientEventQueue, +nsImapService::DeleteMessages(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL, @@ -1526,9 +1501,9 @@ nsImapService::DeleteMessages(nsIEventQueue * aClientEventQueue, // create a protocol instance to handle the request. // NOTE: once we start working with multiple connections, this step will be much more complicated...but for now // just create a connection and process the request. - NS_ASSERTION (aImapMailFolder && aClientEventQueue, + NS_ASSERTION (aImapMailFolder && aClientEventTarget, "Oops ... null pointer"); - if (!aImapMailFolder || !aClientEventQueue) + if (!aImapMailFolder || !aClientEventTarget) return NS_ERROR_NULL_POINTER; nsCOMPtr imapUrl; @@ -1560,7 +1535,7 @@ nsImapService::DeleteMessages(nsIEventQueue * aClientEventQueue, urlSpec.Append(messageIdentifierList); rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); } @@ -1570,17 +1545,17 @@ nsImapService::DeleteMessages(nsIEventQueue * aClientEventQueue, // Delete all messages in a folder, used to empty trash NS_IMETHODIMP -nsImapService::DeleteAllMessages(nsIEventQueue * aClientEventQueue, +nsImapService::DeleteAllMessages(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL) { - return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener, + return FolderCommand(aClientEventTarget, aImapMailFolder, aUrlListener, "/deleteallmsgs>", nsIImapUrl::nsImapSelectNoopFolder, aURL); } NS_IMETHODIMP -nsImapService::AddMessageFlags(nsIEventQueue * aClientEventQueue, +nsImapService::AddMessageFlags(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL, @@ -1588,12 +1563,12 @@ nsImapService::AddMessageFlags(nsIEventQueue * aClientEventQueue, imapMessageFlagsType flags, PRBool messageIdsAreUID) { - return DiddleFlags(aClientEventQueue, aImapMailFolder, aUrlListener, aURL, messageIdentifierList, + return DiddleFlags(aClientEventTarget, aImapMailFolder, aUrlListener, aURL, messageIdentifierList, "addmsgflags", flags, messageIdsAreUID); } NS_IMETHODIMP -nsImapService::SubtractMessageFlags(nsIEventQueue * aClientEventQueue, +nsImapService::SubtractMessageFlags(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL, @@ -1601,12 +1576,12 @@ nsImapService::SubtractMessageFlags(nsIEventQueue * aClientEventQueue, imapMessageFlagsType flags, PRBool messageIdsAreUID) { - return DiddleFlags(aClientEventQueue, aImapMailFolder, aUrlListener, aURL, messageIdentifierList, + return DiddleFlags(aClientEventTarget, aImapMailFolder, aUrlListener, aURL, messageIdentifierList, "subtractmsgflags", flags, messageIdsAreUID); } NS_IMETHODIMP -nsImapService::SetMessageFlags(nsIEventQueue * aClientEventQueue, +nsImapService::SetMessageFlags(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL, @@ -1618,11 +1593,11 @@ nsImapService::SetMessageFlags(nsIEventQueue * aClientEventQueue, // NOTE: once we start working with multiple connections, this step will be much more complicated...but for now // just create a connection and process the request. - return DiddleFlags(aClientEventQueue, aImapMailFolder, aUrlListener, aURL, messageIdentifierList, + return DiddleFlags(aClientEventTarget, aImapMailFolder, aUrlListener, aURL, messageIdentifierList, "setmsgflags", flags, messageIdsAreUID); } -nsresult nsImapService::DiddleFlags(nsIEventQueue * aClientEventQueue, +nsresult nsImapService::DiddleFlags(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL, @@ -1634,9 +1609,9 @@ nsresult nsImapService::DiddleFlags(nsIEventQueue * aClientEventQueue, // create a protocol instance to handle the request. // NOTE: once we start working with multiple connections, this step will be much more complicated...but for now // just create a connection and process the request. - NS_ASSERTION (aImapMailFolder && aClientEventQueue, + NS_ASSERTION (aImapMailFolder && aClientEventTarget, "Oops ... null pointer"); - if (!aImapMailFolder || !aClientEventQueue) + if (!aImapMailFolder || !aClientEventTarget) return NS_ERROR_NULL_POINTER; nsCOMPtr imapUrl; @@ -1671,7 +1646,7 @@ nsresult nsImapService::DiddleFlags(nsIEventQueue * aClientEventQueue, urlSpec.AppendInt(flags); rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); } } @@ -1720,15 +1695,15 @@ nsImapService::SetImapUrlSink(nsIMsgFolder* aMsgFolder, } NS_IMETHODIMP -nsImapService::DiscoverAllFolders(nsIEventQueue* aClientEventQueue, +nsImapService::DiscoverAllFolders(nsIEventTarget* aClientEventTarget, nsIMsgFolder* aImapMailFolder, nsIUrlListener* aUrlListener, nsIMsgWindow * aMsgWindow, nsIURI** aURL) { - NS_ASSERTION (aImapMailFolder && aClientEventQueue, - "Oops ... null aClientEventQueue or aImapMailFolder"); - if (!aImapMailFolder || ! aClientEventQueue) + NS_ASSERTION (aImapMailFolder && aClientEventTarget, + "Oops ... null aClientEventTarget or aImapMailFolder"); + if (!aImapMailFolder || ! aClientEventTarget) return NS_ERROR_NULL_POINTER; nsCOMPtr imapUrl; @@ -1752,7 +1727,7 @@ nsImapService::DiscoverAllFolders(nsIEventQueue* aClientEventQueue, nsCOMPtr url = do_QueryInterface(imapUrl, &rv); rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); } } @@ -1760,14 +1735,14 @@ nsImapService::DiscoverAllFolders(nsIEventQueue* aClientEventQueue, } NS_IMETHODIMP -nsImapService::DiscoverAllAndSubscribedFolders(nsIEventQueue* aClientEventQueue, +nsImapService::DiscoverAllAndSubscribedFolders(nsIEventTarget* aClientEventTarget, nsIMsgFolder* aImapMailFolder, nsIUrlListener* aUrlListener, nsIURI** aURL) { - NS_ASSERTION (aImapMailFolder && aClientEventQueue, - "Oops ... null aClientEventQueue or aImapMailFolder"); - if (!aImapMailFolder || ! aClientEventQueue) + NS_ASSERTION (aImapMailFolder && aClientEventTarget, + "Oops ... null aClientEventTarget or aImapMailFolder"); + if (!aImapMailFolder || ! aClientEventTarget) return NS_ERROR_NULL_POINTER; nsCOMPtr aImapUrl; @@ -1788,7 +1763,7 @@ nsImapService::DiscoverAllAndSubscribedFolders(nsIEventQueue* aClientEventQueue, urlSpec.Append("/discoverallandsubscribedboxes"); rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, aImapUrl, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, aImapUrl, nsnull, aURL); } } @@ -1796,15 +1771,15 @@ nsImapService::DiscoverAllAndSubscribedFolders(nsIEventQueue* aClientEventQueue, } NS_IMETHODIMP -nsImapService::DiscoverChildren(nsIEventQueue* aClientEventQueue, +nsImapService::DiscoverChildren(nsIEventTarget* aClientEventTarget, nsIMsgFolder* aImapMailFolder, nsIUrlListener* aUrlListener, const char *folderPath, nsIURI** aURL) { - NS_ASSERTION (aImapMailFolder && aClientEventQueue, - "Oops ... null aClientEventQueue or aImapMailFolder"); - if (!aImapMailFolder || ! aClientEventQueue) + NS_ASSERTION (aImapMailFolder && aClientEventTarget, + "Oops ... null aClientEventTarget or aImapMailFolder"); + if (!aImapMailFolder || ! aClientEventTarget) return NS_ERROR_NULL_POINTER; nsCOMPtr aImapUrl; @@ -1842,7 +1817,7 @@ nsImapService::DiscoverChildren(nsIEventQueue* aClientEventQueue, if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, aImapUrl, nsnull, aURL); } @@ -1857,7 +1832,7 @@ nsImapService::DiscoverChildren(nsIEventQueue* aClientEventQueue, NS_IMETHODIMP -nsImapService::OnlineMessageCopy(nsIEventQueue* aClientEventQueue, +nsImapService::OnlineMessageCopy(nsIEventTarget* aClientEventTarget, nsIMsgFolder* aSrcFolder, const char* messageIds, nsIMsgFolder* aDstFolder, @@ -1868,9 +1843,9 @@ nsImapService::OnlineMessageCopy(nsIEventQueue* aClientEventQueue, nsISupports* copyState, nsIMsgWindow *aMsgWindow) { - NS_ASSERTION(aSrcFolder && aDstFolder && messageIds && aClientEventQueue, + NS_ASSERTION(aSrcFolder && aDstFolder && messageIds && aClientEventTarget, "Fatal ... missing key parameters"); - if (!aClientEventQueue || !aSrcFolder || !aDstFolder || !messageIds || + if (!aClientEventTarget || !aSrcFolder || !aDstFolder || !messageIds || *messageIds == 0) return NS_ERROR_NULL_POINTER; @@ -1936,7 +1911,7 @@ nsImapService::OnlineMessageCopy(nsIEventQueue* aClientEventQueue, rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); } return rv; @@ -2056,7 +2031,7 @@ nsresult nsImapService::OfflineAppendFromFile(nsIFileSpec* aFileSpec, /* imap://HOST>appendmsgfromfile>DESTINATIONMAILBOXPATH */ /* imap://HOST>appenddraftfromfile>DESTINATIONMAILBOXPATH>UID>messageId */ NS_IMETHODIMP -nsImapService::AppendMessageFromFile(nsIEventQueue* aClientEventQueue, +nsImapService::AppendMessageFromFile(nsIEventTarget* aClientEventTarget, nsIFileSpec* aFileSpec, nsIMsgFolder* aDstFolder, const char* messageId, // te be replaced @@ -2068,7 +2043,7 @@ nsImapService::AppendMessageFromFile(nsIEventQueue* aClientEventQueue, nsIMsgWindow *aMsgWindow) { nsresult rv = NS_ERROR_NULL_POINTER; - if (!aClientEventQueue || !aFileSpec || !aDstFolder) + if (!aClientEventTarget || !aFileSpec || !aDstFolder) return rv; nsCOMPtr imapUrl; @@ -2122,14 +2097,14 @@ nsImapService::AppendMessageFromFile(nsIEventQueue* aClientEventQueue, // handle offline append to drafts or templates folder here. } if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); } return rv; } nsresult -nsImapService::GetImapConnectionAndLoadUrl(nsIEventQueue* aClientEventQueue, +nsImapService::GetImapConnectionAndLoadUrl(nsIEventTarget* aClientEventTarget, nsIImapUrl* aImapUrl, nsISupports* aConsumer, nsIURI** aURL) @@ -2160,20 +2135,20 @@ nsImapService::GetImapConnectionAndLoadUrl(nsIEventQueue* aClientEventQueue, { nsCOMPtr aImapServer(do_QueryInterface(aMsgIncomingServer, &rv)); if (NS_SUCCEEDED(rv) && aImapServer) - rv = aImapServer->GetImapConnectionAndLoadUrl(aClientEventQueue, + rv = aImapServer->GetImapConnectionAndLoadUrl(aClientEventTarget, aImapUrl, aConsumer); } return rv; } NS_IMETHODIMP -nsImapService::MoveFolder(nsIEventQueue* eventQueue, nsIMsgFolder* srcFolder, +nsImapService::MoveFolder(nsIEventTarget* eventTarget, nsIMsgFolder* srcFolder, nsIMsgFolder* dstFolder, nsIUrlListener* urlListener, nsIMsgWindow *msgWindow, nsIURI** url) { - NS_ASSERTION(eventQueue && srcFolder && dstFolder, + NS_ASSERTION(eventTarget && srcFolder && dstFolder, "Oops ... null pointer"); - if (!eventQueue || !srcFolder || !dstFolder) + if (!eventTarget || !srcFolder || !dstFolder) return NS_ERROR_NULL_POINTER; nsCOMPtr imapUrl; @@ -2210,7 +2185,7 @@ nsImapService::MoveFolder(nsIEventQueue* eventQueue, nsIMsgFolder* srcFolder, if (NS_SUCCEEDED(rv)) { GetFolderName(srcFolder, getter_Copies(folderName)); - rv = GetImapConnectionAndLoadUrl(eventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(eventTarget, imapUrl, nsnull, url); } @@ -2220,13 +2195,13 @@ nsImapService::MoveFolder(nsIEventQueue* eventQueue, nsIMsgFolder* srcFolder, } NS_IMETHODIMP -nsImapService::RenameLeaf(nsIEventQueue* eventQueue, nsIMsgFolder* srcFolder, +nsImapService::RenameLeaf(nsIEventTarget* eventTarget, nsIMsgFolder* srcFolder, const PRUnichar* newLeafName, nsIUrlListener* urlListener, nsIMsgWindow *msgWindow, nsIURI** url) { - NS_ASSERTION(eventQueue && srcFolder && newLeafName && *newLeafName, + NS_ASSERTION(eventTarget && srcFolder && newLeafName && *newLeafName, "Oops ... [RenameLeaf] null pointers"); - if (!eventQueue || !srcFolder || !newLeafName || !*newLeafName) + if (!eventTarget || !srcFolder || !newLeafName || !*newLeafName) return NS_ERROR_NULL_POINTER; nsCOMPtr imapUrl; @@ -2277,7 +2252,7 @@ nsImapService::RenameLeaf(nsIEventQueue* eventQueue, nsIMsgFolder* srcFolder, rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) { - rv = GetImapConnectionAndLoadUrl(eventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(eventTarget, imapUrl, nsnull, url); } } // if (NS_SUCCEEDED(rv)) @@ -2286,13 +2261,13 @@ nsImapService::RenameLeaf(nsIEventQueue* eventQueue, nsIMsgFolder* srcFolder, } NS_IMETHODIMP -nsImapService::CreateFolder(nsIEventQueue* eventQueue, nsIMsgFolder* parent, +nsImapService::CreateFolder(nsIEventTarget* eventTarget, nsIMsgFolder* parent, const PRUnichar* newFolderName, nsIUrlListener* urlListener, nsIURI** url) { - NS_ASSERTION(eventQueue && parent && newFolderName && *newFolderName, + NS_ASSERTION(eventTarget && parent && newFolderName && *newFolderName, "Oops ... [CreateFolder] null pointers"); - if (!eventQueue || !parent || !newFolderName || !*newFolderName) + if (!eventTarget || !parent || !newFolderName || !*newFolderName) return NS_ERROR_NULL_POINTER; nsCOMPtr imapUrl; @@ -2330,7 +2305,7 @@ nsImapService::CreateFolder(nsIEventQueue* eventQueue, nsIMsgFolder* parent, rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(eventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(eventTarget, imapUrl, nsnull, url); } // if (NS_SUCCEEDED(rv)) @@ -2339,13 +2314,13 @@ nsImapService::CreateFolder(nsIEventQueue* eventQueue, nsIMsgFolder* parent, } NS_IMETHODIMP -nsImapService::EnsureFolderExists(nsIEventQueue* eventQueue, nsIMsgFolder* parent, +nsImapService::EnsureFolderExists(nsIEventTarget* eventTarget, nsIMsgFolder* parent, const PRUnichar* newFolderName, nsIUrlListener* urlListener, nsIURI** url) { - NS_ASSERTION(eventQueue && parent && newFolderName && *newFolderName, + NS_ASSERTION(eventTarget && parent && newFolderName && *newFolderName, "Oops ... [EnsureExists] null pointers"); - if (!eventQueue || !parent || !newFolderName || !*newFolderName) + if (!eventTarget || !parent || !newFolderName || !*newFolderName) return NS_ERROR_NULL_POINTER; nsCOMPtr imapUrl; @@ -2378,7 +2353,7 @@ nsImapService::EnsureFolderExists(nsIEventQueue* eventQueue, nsIMsgFolder* paren rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(eventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(eventTarget, imapUrl, nsnull, url); } // if (NS_SUCCEEDED(rv)) @@ -2388,12 +2363,12 @@ nsImapService::EnsureFolderExists(nsIEventQueue* eventQueue, nsIMsgFolder* paren NS_IMETHODIMP -nsImapService::ListFolder(nsIEventQueue* aClientEventQueue, +nsImapService::ListFolder(nsIEventTarget* aClientEventTarget, nsIMsgFolder* aImapMailFolder, nsIUrlListener* aUrlListener, nsIURI** aURL) { - return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener, + return FolderCommand(aClientEventTarget, aImapMailFolder, aUrlListener, "/listfolder>", nsIImapUrl::nsImapListFolder, aURL); } @@ -2944,15 +2919,6 @@ nsImapService::GetListOfFoldersWithPath(nsIImapIncomingServer *aServer, nsIMsgWi if (NS_FAILED(rv)) return rv; if (!listener) return NS_ERROR_FAILURE; - nsCOMPtr queue; - // get the Event Queue for this thread... - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - if (NS_FAILED(rv)) return rv; - // Locate the folder so that the correct hierarchical delimiter is used in the folder // pathnames, otherwise root's (ie, '^') is used and this is wrong. nsCOMPtr msgFolder; @@ -2983,7 +2949,7 @@ nsImapService::GetListOfFoldersWithPath(nsIImapIncomingServer *aServer, nsIMsgWi rv = rootMsgFolder->FindSubFolder(changedStr, getter_AddRefs(msgFolder)); } - rv = DiscoverChildren(queue, msgFolder, listener, folderPath, nsnull); + rv = DiscoverChildren(NS_GetCurrentThread(), msgFolder, listener, folderPath, nsnull); if (NS_FAILED(rv)) return rv; return NS_OK; @@ -3007,38 +2973,30 @@ nsImapService::GetListOfFoldersOnServer(nsIImapIncomingServer *aServer, nsIMsgWi if (NS_FAILED(rv)) return rv; if (!listener) return NS_ERROR_FAILURE; - nsCOMPtr queue; - // get the Event Queue for this thread... - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - if (NS_FAILED(rv)) return rv; - - rv = DiscoverAllAndSubscribedFolders(queue, rootMsgFolder, listener, nsnull); + rv = DiscoverAllAndSubscribedFolders(NS_GetCurrentThread(), rootMsgFolder, + listener, nsnull); if (NS_FAILED(rv)) return rv; return NS_OK; } NS_IMETHODIMP -nsImapService::SubscribeFolder(nsIEventQueue* eventQueue, +nsImapService::SubscribeFolder(nsIEventTarget* eventTarget, nsIMsgFolder* aFolder, const PRUnichar* aFolderName, nsIUrlListener* urlListener, nsIURI** url) { - return ChangeFolderSubscription(eventQueue, aFolder, aFolderName, + return ChangeFolderSubscription(eventTarget, aFolder, aFolderName, "/subscribe>", urlListener, url); } -nsresult nsImapService::ChangeFolderSubscription(nsIEventQueue* eventQueue, +nsresult nsImapService::ChangeFolderSubscription(nsIEventTarget* eventTarget, nsIMsgFolder* folder, const PRUnichar* folderName, const char *command, nsIUrlListener* urlListener, nsIURI** url) { - NS_ENSURE_ARG_POINTER(eventQueue); + NS_ENSURE_ARG_POINTER(eventTarget); NS_ENSURE_ARG_POINTER(folder); NS_ENSURE_ARG_POINTER(folderName); @@ -3064,7 +3022,7 @@ nsresult nsImapService::ChangeFolderSubscription(nsIEventQueue* eventQueue, nsCRT::free(escapedFolderName); rv = uri->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(eventQueue, imapUrl, + rv = GetImapConnectionAndLoadUrl(eventTarget, imapUrl, nsnull, url); } } @@ -3072,35 +3030,35 @@ nsresult nsImapService::ChangeFolderSubscription(nsIEventQueue* eventQueue, } NS_IMETHODIMP -nsImapService::UnsubscribeFolder(nsIEventQueue* aEventQueue, +nsImapService::UnsubscribeFolder(nsIEventTarget* aEventTarget, nsIMsgFolder* aFolder, const PRUnichar* aFolderName, nsIUrlListener* aUrlListener, nsIURI** aUrl) { - return ChangeFolderSubscription(aEventQueue, aFolder, aFolderName, + return ChangeFolderSubscription(aEventTarget, aFolder, aFolderName, "/unsubscribe>", aUrlListener, aUrl); } NS_IMETHODIMP -nsImapService::GetFolderAdminUrl(nsIEventQueue *aClientEventQueue, +nsImapService::GetFolderAdminUrl(nsIEventTarget *aClientEventTarget, nsIMsgFolder *aImapMailFolder, nsIMsgWindow *aMsgWindow, nsIUrlListener *aUrlListener, nsIURI** aURL) { - return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener, + return FolderCommand(aClientEventTarget, aImapMailFolder, aUrlListener, "/refreshfolderurls>", nsIImapUrl::nsImapRefreshFolderUrls, aURL); } NS_IMETHODIMP -nsImapService::IssueCommandOnMsgs(nsIEventQueue *aClientEventQueue, +nsImapService::IssueCommandOnMsgs(nsIEventTarget *aClientEventTarget, nsIMsgFolder *anImapFolder, nsIMsgWindow *aMsgWindow, const char *aCommand, const char *uids, nsIURI** aURL) { - NS_ENSURE_ARG_POINTER(aClientEventQueue); + NS_ENSURE_ARG_POINTER(aClientEventTarget); NS_ENSURE_ARG_POINTER(anImapFolder); NS_ENSURE_ARG_POINTER(aMsgWindow); nsCOMPtr imapUrl; @@ -3135,7 +3093,7 @@ nsImapService::IssueCommandOnMsgs(nsIEventQueue *aClientEventQueue, urlSpec.Append(uids); rv = mailNewsUrl->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); @@ -3146,14 +3104,14 @@ nsImapService::IssueCommandOnMsgs(nsIEventQueue *aClientEventQueue, } NS_IMETHODIMP -nsImapService::FetchCustomMsgAttribute(nsIEventQueue *aClientEventQueue, +nsImapService::FetchCustomMsgAttribute(nsIEventTarget *aClientEventTarget, nsIMsgFolder *anImapFolder, nsIMsgWindow *aMsgWindow, const char *aAttribute, const char *uids, nsIURI** aURL) { - NS_ENSURE_ARG_POINTER(aClientEventQueue); + NS_ENSURE_ARG_POINTER(aClientEventTarget); NS_ENSURE_ARG_POINTER(anImapFolder); NS_ENSURE_ARG_POINTER(aMsgWindow); nsCOMPtr imapUrl; @@ -3186,7 +3144,7 @@ nsImapService::FetchCustomMsgAttribute(nsIEventQueue *aClientEventQueue, urlSpec.Append(aAttribute); rv = mailNewsUrl->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); @@ -3197,7 +3155,7 @@ nsImapService::FetchCustomMsgAttribute(nsIEventQueue *aClientEventQueue, } NS_IMETHODIMP -nsImapService::StoreCustomKeywords(nsIEventQueue *aClientEventQueue, +nsImapService::StoreCustomKeywords(nsIEventTarget *aClientEventTarget, nsIMsgFolder *anImapFolder, nsIMsgWindow *aMsgWindow, const char *flagsToAdd, @@ -3205,7 +3163,7 @@ nsImapService::StoreCustomKeywords(nsIEventQueue *aClientEventQueue, const char *uids, nsIURI** aURL) { - NS_ENSURE_ARG_POINTER(aClientEventQueue); + NS_ENSURE_ARG_POINTER(aClientEventTarget); NS_ENSURE_ARG_POINTER(anImapFolder); nsCOMPtr imapUrl; nsCAutoString urlSpec; @@ -3239,7 +3197,7 @@ nsImapService::StoreCustomKeywords(nsIEventQueue *aClientEventQueue, urlSpec.Append(flagsToSubtract); rv = mailNewsUrl->SetSpec(urlSpec); if (NS_SUCCEEDED(rv)) - rv = GetImapConnectionAndLoadUrl(aClientEventQueue, + rv = GetImapConnectionAndLoadUrl(aClientEventTarget, imapUrl, nsnull, aURL); diff --git a/mozilla/mailnews/imap/src/nsImapService.h b/mozilla/mailnews/imap/src/nsImapService.h index c15c62dd700..5a93d8e9c29 100644 --- a/mozilla/mailnews/imap/src/nsImapService.h +++ b/mozilla/mailnews/imap/src/nsImapService.h @@ -98,7 +98,7 @@ protected: nsIUrlListener * aUrlListener, nsCString & urlSpec, PRUnichar &hierarchyDelimiter); - nsresult GetImapConnectionAndLoadUrl(nsIEventQueue* aClientEventQueue, + nsresult GetImapConnectionAndLoadUrl(nsIEventTarget* aClientEventTarget, nsIImapUrl* aImapUrl, nsISupports* aConsumer, nsIURI** aURL); @@ -114,20 +114,20 @@ protected: const char *messageIdentifierList, const char *mimePart); - nsresult FolderCommand(nsIEventQueue * clientEventQueue, + nsresult FolderCommand(nsIEventTarget * clientEventTarget, nsIMsgFolder * imapMailFolder, nsIUrlListener * urlListener, const char *command, nsImapAction imapAction, nsIURI ** url); - nsresult ChangeFolderSubscription(nsIEventQueue* eventQueue, + nsresult ChangeFolderSubscription(nsIEventTarget* eventTarget, nsIMsgFolder* folder, const PRUnichar* folderName, const char *command, nsIUrlListener* urlListener, nsIURI** url); - nsresult DiddleFlags(nsIEventQueue * aClientEventQueue, + nsresult DiddleFlags(nsIEventTarget * aClientEventTarget, nsIMsgFolder * aImapMailFolder, nsIUrlListener * aUrlListener, nsIURI ** aURL, diff --git a/mozilla/mailnews/imap/src/nsImapUndoTxn.cpp b/mozilla/mailnews/imap/src/nsImapUndoTxn.cpp index 42ea58a9b58..fa06b483a6e 100644 --- a/mozilla/mailnews/imap/src/nsImapUndoTxn.cpp +++ b/mozilla/mailnews/imap/src/nsImapUndoTxn.cpp @@ -54,11 +54,11 @@ nsImapMoveCopyMsgTxn::nsImapMoveCopyMsgTxn( nsIMsgFolder* srcFolder, nsMsgKeyArray* srcKeyArray, const char* srcMsgIdString, nsIMsgFolder* dstFolder, PRBool idsAreUids, PRBool isMove, - nsIEventQueue* eventQueue, nsIUrlListener* urlListener) : + nsIEventTarget* eventTarget, nsIUrlListener* urlListener) : m_idsAreUids(PR_FALSE), m_isMove(PR_FALSE), m_srcIsPop3(PR_FALSE) { Init(srcFolder, srcKeyArray, srcMsgIdString, dstFolder, idsAreUids, - isMove, eventQueue, urlListener); + isMove, eventTarget, urlListener); } nsresult @@ -66,7 +66,7 @@ nsImapMoveCopyMsgTxn::Init( nsIMsgFolder* srcFolder, nsMsgKeyArray* srcKeyArray, const char* srcMsgIdString, nsIMsgFolder* dstFolder, PRBool idsAreUids, PRBool isMove, - nsIEventQueue* eventQueue, nsIUrlListener* urlListener) + nsIEventTarget* eventTarget, nsIUrlListener* urlListener) { nsresult rv; NS_NewISupportsArray(getter_AddRefs(m_srcHdrs)); @@ -75,7 +75,7 @@ nsImapMoveCopyMsgTxn::Init( m_isMove = isMove; m_srcFolder = do_GetWeakReference(srcFolder); m_dstFolder = do_GetWeakReference(dstFolder); - m_eventQueue = do_QueryInterface(eventQueue, &rv); + m_eventTarget = eventTarget; if (urlListener) m_urlListener = do_QueryInterface(urlListener, &rv); m_srcKeyArray.CopyArray(srcKeyArray); @@ -179,7 +179,7 @@ nsImapMoveCopyMsgTxn::UndoTransaction(void) return rv; // ** make sure we are in the selected state; use lite select // folder so we won't hit performance hard - rv = imapService->LiteSelectFolder(m_eventQueue, srcFolder, + rv = imapService->LiteSelectFolder(m_eventTarget, srcFolder, srcListener, nsnull); if (NS_FAILED(rv)) return rv; @@ -198,11 +198,11 @@ nsImapMoveCopyMsgTxn::UndoTransaction(void) if (deletedMsgs) rv = imapService->SubtractMessageFlags( - m_eventQueue, srcFolder, srcListener, nsnull, + m_eventTarget, srcFolder, srcListener, nsnull, m_srcMsgIdString.get(), kImapMsgDeletedFlag, m_idsAreUids); else - rv = imapService->AddMessageFlags(m_eventQueue, srcFolder, + rv = imapService->AddMessageFlags(m_eventTarget, srcFolder, srcListener, nsnull, m_srcMsgIdString.get(), kImapMsgDeletedFlag, @@ -211,7 +211,7 @@ nsImapMoveCopyMsgTxn::UndoTransaction(void) return rv; if (deleteModel != nsMsgImapDeleteModels::IMAPDelete) - rv = imapService->GetHeaders(m_eventQueue, srcFolder, + rv = imapService->GetHeaders(m_eventTarget, srcFolder, srcListener, nsnull, m_srcMsgIdString.get(), PR_TRUE); @@ -228,10 +228,10 @@ nsImapMoveCopyMsgTxn::UndoTransaction(void) if (NS_FAILED(rv)) return rv; // ** make sure we are in the selected state; use lite select folder // so we won't potentially download a bunch of headers. - rv = imapService->LiteSelectFolder(m_eventQueue, dstFolder, + rv = imapService->LiteSelectFolder(m_eventTarget, dstFolder, dstListener, nsnull); if (NS_FAILED(rv)) return rv; - rv = imapService->AddMessageFlags(m_eventQueue, dstFolder, + rv = imapService->AddMessageFlags(m_eventTarget, dstFolder, dstListener, nsnull, m_dstMsgIdString.get(), kImapMsgDeletedFlag, @@ -279,17 +279,17 @@ nsImapMoveCopyMsgTxn::RedoTransaction(void) // ** make sire we are in the selected state; use lite select // folder so we won't hit preformace hard - rv = imapService->LiteSelectFolder(m_eventQueue, srcFolder, + rv = imapService->LiteSelectFolder(m_eventTarget, srcFolder, srcListener, nsnull); if (NS_FAILED(rv)) return rv; if (deletedMsgs) - rv = imapService->SubtractMessageFlags(m_eventQueue, srcFolder, + rv = imapService->SubtractMessageFlags(m_eventTarget, srcFolder, srcListener, nsnull, m_srcMsgIdString.get(), kImapMsgDeletedFlag, m_idsAreUids); else - rv = imapService->AddMessageFlags(m_eventQueue, srcFolder, + rv = imapService->AddMessageFlags(m_eventTarget, srcFolder, srcListener, nsnull, m_srcMsgIdString.get(), kImapMsgDeletedFlag, m_idsAreUids); } @@ -306,11 +306,11 @@ nsImapMoveCopyMsgTxn::RedoTransaction(void) return rv; // ** make sure we are in the selected state; use lite select // folder so we won't hit preformace hard - rv = imapService->LiteSelectFolder(m_eventQueue, dstFolder, + rv = imapService->LiteSelectFolder(m_eventTarget, dstFolder, dstListener, nsnull); if (NS_FAILED(rv)) return rv; - rv = imapService->SubtractMessageFlags(m_eventQueue, dstFolder, + rv = imapService->SubtractMessageFlags(m_eventTarget, dstFolder, dstListener, nsnull, m_dstMsgIdString.get(), kImapMsgDeletedFlag, @@ -320,7 +320,7 @@ nsImapMoveCopyMsgTxn::RedoTransaction(void) nsMsgImapDeleteModel deleteModel; rv = GetImapDeleteModel(dstFolder, &deleteModel); if (NS_FAILED(rv) || deleteModel == nsMsgImapDeleteModels::MoveToTrash) - rv = imapService->GetHeaders(m_eventQueue, dstFolder, + rv = imapService->GetHeaders(m_eventTarget, dstFolder, dstListener, nsnull, m_dstMsgIdString.get(), PR_TRUE); @@ -451,10 +451,10 @@ nsresult nsImapMoveCopyMsgTxn::GetImapDeleteModel(nsIMsgFolder *aFolder, nsMsgIm nsImapOfflineTxn::nsImapOfflineTxn(nsIMsgFolder* srcFolder, nsMsgKeyArray* srcKeyArray, nsIMsgFolder* dstFolder, PRBool isMove, nsOfflineImapOperationType opType, nsIMsgDBHdr *srcHdr, - nsIEventQueue* eventQueue, nsIUrlListener* urlListener) + nsIEventTarget* eventTarget, nsIUrlListener* urlListener) { Init(srcFolder, srcKeyArray, nsnull, dstFolder, PR_TRUE, - isMove, eventQueue, urlListener); + isMove, eventTarget, urlListener); m_opType = opType; m_flags = 0; diff --git a/mozilla/mailnews/imap/src/nsImapUndoTxn.h b/mozilla/mailnews/imap/src/nsImapUndoTxn.h index f55b2435318..a80d73b3cfd 100644 --- a/mozilla/mailnews/imap/src/nsImapUndoTxn.h +++ b/mozilla/mailnews/imap/src/nsImapUndoTxn.h @@ -43,7 +43,7 @@ #include "nsIImapService.h" #include "nsIImapIncomingServer.h" #include "nsIUrlListener.h" -#include "nsIEventQueue.h" +#include "nsIEventTarget.h" #include "nsMsgTxn.h" #include "nsMsgKeyArray.h" #include "nsIMsgOfflineImapOperation.h" @@ -64,7 +64,7 @@ public: nsImapMoveCopyMsgTxn(nsIMsgFolder* srcFolder, nsMsgKeyArray* srcKeyArray, const char* srcMsgIdString, nsIMsgFolder* dstFolder, PRBool idsAreUids, PRBool isMove, - nsIEventQueue *eventQueue, + nsIEventTarget *eventTarget, nsIUrlListener *urlListener); virtual ~nsImapMoveCopyMsgTxn(); @@ -82,7 +82,7 @@ public: nsresult Init(nsIMsgFolder* srcFolder, nsMsgKeyArray* srcKeyArray, const char* srcMsgIdString, nsIMsgFolder* dstFolder, PRBool idsAreUids, PRBool isMove, - nsIEventQueue *eventQueue, + nsIEventTarget *eventTarget, nsIUrlListener *urlListener); protected: @@ -94,7 +94,7 @@ protected: nsCString m_srcMsgIdString; nsWeakPtr m_dstFolder; nsCString m_dstMsgIdString; - nsCOMPtr m_eventQueue; + nsCOMPtr m_eventTarget; nsCOMPtr m_urlListener; PRBool m_idsAreUids; PRBool m_isMove; @@ -114,7 +114,7 @@ public: PRBool isMove, nsOfflineImapOperationType opType, nsIMsgDBHdr *srcHdr, - nsIEventQueue *eventQueue, + nsIEventTarget *eventTarget, nsIUrlListener *urlListener); virtual ~nsImapOfflineTxn(); diff --git a/mozilla/mailnews/imap/src/nsImapUrl.cpp b/mozilla/mailnews/imap/src/nsImapUrl.cpp index 7243040204b..7fe006ae3f7 100644 --- a/mozilla/mailnews/imap/src/nsImapUrl.cpp +++ b/mozilla/mailnews/imap/src/nsImapUrl.cpp @@ -39,8 +39,6 @@ #include "msgCore.h" // precompiled header... #include "nsMsgImapCID.h" -#include "nsIEventQueueService.h" - #include "nsIURL.h" #include "nsImapUrl.h" #include "nsIMsgMailSession.h" diff --git a/mozilla/mailnews/import/comm4x/src/nsComm4xMailImport.cpp b/mozilla/mailnews/import/comm4x/src/nsComm4xMailImport.cpp index 17507e0aa49..95759127efa 100644 --- a/mozilla/mailnews/import/comm4x/src/nsComm4xMailImport.cpp +++ b/mozilla/mailnews/import/comm4x/src/nsComm4xMailImport.cpp @@ -74,8 +74,6 @@ #include "nsIProxyObjectManager.h" #include "nsProxiedService.h" -static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); - #define COMM4XMAIL_MSGS_URL "chrome://messenger/locale/comm4xMailImportMsgs.properties" PRLogModuleInfo *COMM4XLOGMODULE = nsnull; @@ -172,7 +170,7 @@ NS_IMETHODIMP nsComm4xMailImport::GetImportInterface(const char *pImportType, ns NS_ENSURE_SUCCESS(rv,rv); nameString->SetData(name); pGeneric->SetData("name", nameString); - rv = pGeneric->QueryInterface(kISupportsIID, (void **)ppInterface); + rv = CallQueryInterface(pGeneric, ppInterface); } } } @@ -196,13 +194,14 @@ nsresult ImportComm4xMailImpl::Initialize() nsCOMPtr pBundle; pBundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv) && (pBundleService)) + if (NS_SUCCEEDED(rv) && (pBundleService)) { pBundleService->CreateBundle(COMM4XMAIL_MSGS_URL, getter_AddRefs(pBundle)); - nsCOMPtr proxyMgr(do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv)); - if (NS_SUCCEEDED(rv)) { - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIStringBundle), - pBundle, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs(m_pBundleProxy)); + rv = NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIStringBundle), + pBundle, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs(m_pBundleProxy)); } return rv; } diff --git a/mozilla/mailnews/import/eudora/src/nsEudoraCompose.cpp b/mozilla/mailnews/import/eudora/src/nsEudoraCompose.cpp index b677e902847..ebf2878f4b9 100644 --- a/mozilla/mailnews/import/eudora/src/nsEudoraCompose.cpp +++ b/mozilla/mailnews/import/eudora/src/nsEudoraCompose.cpp @@ -74,7 +74,6 @@ static NS_DEFINE_CID( kMsgSendCID, NS_MSGSEND_CID); static NS_DEFINE_CID( kMsgCompFieldsCID, NS_MSGCOMPFIELDS_CID); static NS_DEFINE_CID( kIOServiceCID, NS_IOSERVICE_CID); -static NS_DEFINE_CID( kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); // We need to do some calculations to set these numbers to something reasonable! @@ -219,7 +218,7 @@ nsEudoraCompose::~nsEudoraCompose() NS_ASSERTION(NS_SUCCEEDED(rv),"failed to clear values"); if (NS_FAILED(rv)) return; - NS_WITH_PROXIED_SERVICE(nsIMsgAccountManager, accMgr, NS_MSGACCOUNTMANAGER_CONTRACTID, NS_UI_THREAD_EVENTQ, &rv); + NS_WITH_PROXIED_SERVICE(nsIMsgAccountManager, accMgr, NS_MSGACCOUNTMANAGER_CONTRACTID, NS_PROXY_TO_MAIN_THREAD, &rv); NS_ASSERTION(NS_SUCCEEDED(rv) && accMgr,"failed to get account manager"); if (NS_FAILED(rv) || !accMgr) return; @@ -238,7 +237,7 @@ nsresult nsEudoraCompose::CreateIdentity( void) return( NS_OK); nsresult rv; - NS_WITH_PROXIED_SERVICE(nsIMsgAccountManager, accMgr, NS_MSGACCOUNTMANAGER_CONTRACTID, NS_UI_THREAD_EVENTQ, &rv); + NS_WITH_PROXIED_SERVICE(nsIMsgAccountManager, accMgr, NS_MSGACCOUNTMANAGER_CONTRACTID, NS_PROXY_TO_MAIN_THREAD, &rv); if (NS_FAILED(rv)) return( rv); rv = accMgr->CreateIdentity( &m_pIdentity); nsString name(NS_LITERAL_STRING("Import Identity")); @@ -258,7 +257,7 @@ nsresult nsEudoraCompose::CreateComponents( void) if (!m_pIOService) { IMPORT_LOG0( "Creating nsIOService\n"); - NS_WITH_PROXIED_SERVICE(nsIIOService, service, kIOServiceCID, NS_UI_THREAD_EVENTQ, &rv); + NS_WITH_PROXIED_SERVICE(nsIIOService, service, kIOServiceCID, NS_PROXY_TO_MAIN_THREAD, &rv); if (NS_FAILED(rv)) return( rv); m_pIOService = service; @@ -269,16 +268,10 @@ nsresult nsEudoraCompose::CreateComponents( void) if (!m_pMsgSend) { rv = CallCreateInstance( kMsgSendCID, &m_pMsgSend); if (NS_SUCCEEDED( rv) && m_pMsgSend) { - nsCOMPtr proxyMgr = - do_GetService(kProxyObjectManagerCID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIMsgSend), - m_pMsgSend, PROXY_SYNC, (void**)&m_pSendProxy); - if (NS_FAILED( rv)) { - m_pSendProxy = nsnull; - } - } - if (NS_FAILED( rv)) { + rv = NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIMsgSend), + m_pMsgSend, NS_PROXY_SYNC, (void**)&m_pSendProxy); + if (NS_FAILED( rv)) { + m_pSendProxy = nsnull; NS_RELEASE( m_pMsgSend); m_pMsgSend = nsnull; } diff --git a/mozilla/mailnews/import/eudora/src/nsEudoraStringBundle.cpp b/mozilla/mailnews/import/eudora/src/nsEudoraStringBundle.cpp index 04d8db8f5ea..578ebd53f49 100644 --- a/mozilla/mailnews/import/eudora/src/nsEudoraStringBundle.cpp +++ b/mozilla/mailnews/import/eudora/src/nsEudoraStringBundle.cpp @@ -46,8 +46,6 @@ #include "nsIProxyObjectManager.h" #include "nsIURI.h" -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); - #define EUDORA_MSGS_URL "chrome://messenger/locale/eudoraImportMsgs.properties" nsIStringBundle * nsEudoraStringBundle::m_pBundle = nsnull; @@ -78,14 +76,10 @@ nsIStringBundle *nsEudoraStringBundle::GetStringBundleProxy( void) return( nsnull); nsIStringBundle *strProxy = nsnull; - nsresult rv; // create a proxy object if we aren't on the same thread? - nsCOMPtr proxyMgr = - do_GetService(kProxyObjectManagerCID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIStringBundle), - m_pBundle, PROXY_SYNC | PROXY_ALWAYS, (void **) &strProxy); - } + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIStringBundle), + m_pBundle, NS_PROXY_SYNC | NS_PROXY_ALWAYS, + (void **) &strProxy); return( strProxy); } diff --git a/mozilla/mailnews/import/oexpress/nsOEStringBundle.cpp b/mozilla/mailnews/import/oexpress/nsOEStringBundle.cpp index 7439c415d8f..a6fd86764f9 100644 --- a/mozilla/mailnews/import/oexpress/nsOEStringBundle.cpp +++ b/mozilla/mailnews/import/oexpress/nsOEStringBundle.cpp @@ -44,8 +44,6 @@ #include "nsIProxyObjectManager.h" #include "nsIURI.h" -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); - #define OE_MSGS_URL "chrome://messenger/locale/oeImportMsgs.properties" nsIStringBundle * nsOEStringBundle::m_pBundle = nsnull; @@ -77,14 +75,10 @@ nsIStringBundle *nsOEStringBundle::GetStringBundleProxy( void) return( nsnull); nsIStringBundle *strProxy = nsnull; - nsresult rv; // create a proxy object if we aren't on the same thread? - nsCOMPtr proxyMgr = - do_GetService(kProxyObjectManagerCID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIStringBundle), - m_pBundle, PROXY_SYNC | PROXY_ALWAYS, (void **) &strProxy); - } + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIStringBundle), + m_pBundle, NS_PROXY_SYNC | NS_PROXY_ALWAYS, + (void **) &strProxy); return( strProxy); } diff --git a/mozilla/mailnews/import/outlook/src/nsOutlookCompose.cpp b/mozilla/mailnews/import/outlook/src/nsOutlookCompose.cpp index a54dd4753cf..28bd565098b 100644 --- a/mozilla/mailnews/import/outlook/src/nsOutlookCompose.cpp +++ b/mozilla/mailnews/import/outlook/src/nsOutlookCompose.cpp @@ -75,7 +75,6 @@ static NS_DEFINE_CID( kMsgSendCID, NS_MSGSEND_CID); static NS_DEFINE_CID( kMsgCompFieldsCID, NS_MSGCOMPFIELDS_CID); static NS_DEFINE_CID( kIOServiceCID, NS_IOSERVICE_CID); -static NS_DEFINE_CID( kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); // We need to do some calculations to set these numbers to something reasonable! @@ -213,7 +212,7 @@ nsOutlookCompose::~nsOutlookCompose() NS_ASSERTION(NS_SUCCEEDED(rv),"failed to clear values"); if (NS_FAILED(rv)) return; - NS_WITH_PROXIED_SERVICE(nsIMsgAccountManager, accMgr, NS_MSGACCOUNTMANAGER_CONTRACTID, NS_UI_THREAD_EVENTQ, &rv); + NS_WITH_PROXIED_SERVICE(nsIMsgAccountManager, accMgr, NS_MSGACCOUNTMANAGER_CONTRACTID, NS_PROXY_TO_MAIN_THREAD, &rv); NS_ASSERTION(NS_SUCCEEDED(rv) && accMgr,"failed to get account manager"); if (NS_FAILED(rv) || !accMgr) return; @@ -231,7 +230,7 @@ nsresult nsOutlookCompose::CreateIdentity( void) return( NS_OK); nsresult rv; - NS_WITH_PROXIED_SERVICE(nsIMsgAccountManager, accMgr, NS_MSGACCOUNTMANAGER_CONTRACTID, NS_UI_THREAD_EVENTQ, &rv); + NS_WITH_PROXIED_SERVICE(nsIMsgAccountManager, accMgr, NS_MSGACCOUNTMANAGER_CONTRACTID, NS_PROXY_TO_MAIN_THREAD, &rv); if (NS_FAILED(rv)) return( rv); rv = accMgr->CreateIdentity( &m_pIdentity); nsString name; @@ -252,7 +251,7 @@ nsresult nsOutlookCompose::CreateComponents( void) if (!m_pIOService) { IMPORT_LOG0( "Creating nsIOService\n"); - NS_WITH_PROXIED_SERVICE(nsIIOService, service, kIOServiceCID, NS_UI_THREAD_EVENTQ, &rv); + NS_WITH_PROXIED_SERVICE(nsIIOService, service, kIOServiceCID, NS_PROXY_TO_MAIN_THREAD, &rv); if (NS_FAILED(rv)) return( rv); m_pIOService = service; @@ -263,18 +262,11 @@ nsresult nsOutlookCompose::CreateComponents( void) if (!m_pMsgSend) { rv = CallCreateInstance( kMsgSendCID, &m_pMsgSend); if (NS_SUCCEEDED( rv) && m_pMsgSend) { - nsCOMPtr proxyMgr = - do_GetService(kProxyObjectManagerCID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIMsgSend), - m_pMsgSend, PROXY_SYNC, (void **)&m_pSendProxy); - if (NS_FAILED( rv)) { - m_pSendProxy = nsnull; - } - } - if (NS_FAILED( rv)) { + rv = NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIMsgSend), + m_pMsgSend, NS_PROXY_SYNC, (void **)&m_pSendProxy); + if (NS_FAILED( rv)) { + m_pSendProxy = nsnull; NS_RELEASE( m_pMsgSend); - m_pMsgSend = nsnull; } } } diff --git a/mozilla/mailnews/import/outlook/src/nsOutlookStringBundle.cpp b/mozilla/mailnews/import/outlook/src/nsOutlookStringBundle.cpp index 720afa6a434..805faf399e1 100644 --- a/mozilla/mailnews/import/outlook/src/nsOutlookStringBundle.cpp +++ b/mozilla/mailnews/import/outlook/src/nsOutlookStringBundle.cpp @@ -44,8 +44,6 @@ #include "nsIProxyObjectManager.h" #include "nsIURI.h" -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); - #define OUTLOOK_MSGS_URL "chrome://messenger/locale/outlookImportMsgs.properties" nsIStringBundle * nsOutlookStringBundle::m_pBundle = nsnull; @@ -77,14 +75,9 @@ nsIStringBundle *nsOutlookStringBundle::GetStringBundleProxy( void) return( nsnull); nsIStringBundle *strProxy = nsnull; - nsresult rv; // create a proxy object if we aren't on the same thread? - nsCOMPtr proxyMgr = - do_GetService(kProxyObjectManagerCID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIStringBundle), - m_pBundle, PROXY_SYNC | PROXY_ALWAYS, (void **) &strProxy); - } + NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIStringBundle), + m_pBundle, NS_PROXY_SYNC | NS_PROXY_ALWAYS, (void **) &strProxy); return( strProxy); } diff --git a/mozilla/mailnews/import/src/nsImportAddressBooks.cpp b/mozilla/mailnews/import/src/nsImportAddressBooks.cpp index 84e97d5ced0..6346c9ee275 100644 --- a/mozilla/mailnews/import/src/nsImportAddressBooks.cpp +++ b/mozilla/mailnews/import/src/nsImportAddressBooks.cpp @@ -73,7 +73,6 @@ static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); static NS_DEFINE_CID(kSupportsWStringCID, NS_SUPPORTS_STRING_CID); -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); //////////////////////////////////////////////////////////////////////// @@ -756,7 +755,9 @@ nsIAddrDatabase *GetAddressBookFromUri( const char *pUri) nsIAddrDatabase * pDatabase = nsnull; if (pUri) { nsresult rv = NS_OK; - NS_WITH_PROXIED_SERVICE(nsIAddressBook, addressBook, NS_ADDRESSBOOK_CONTRACTID, NS_UI_THREAD_EVENTQ, &rv); + NS_WITH_PROXIED_SERVICE(nsIAddressBook, addressBook, + NS_ADDRESSBOOK_CONTRACTID, + NS_PROXY_TO_MAIN_THREAD, &rv); if (addressBook) rv = addressBook->GetAbDatabaseFromURI(pUri, &pDatabase); } @@ -776,19 +777,14 @@ nsIAddrDatabase *GetAddressBook( const PRUnichar *name, PRBool makeNew) IMPORT_LOG0( "In GetAddressBook\n"); - nsCOMPtr proxyMgr = - do_GetService(kProxyObjectManagerCID, &rv); - if (NS_FAILED( rv)) { - IMPORT_LOG0( "*** Error: Unable to get proxy manager\n"); - return( nsnull); - } - nsIAddrDatabase * pDatabase = nsnull; /* Get the profile directory */ nsCOMPtr dbPath; - NS_WITH_PROXIED_SERVICE(nsIAddrBookSession, abSession, NS_ADDRBOOKSESSION_CONTRACTID, NS_UI_THREAD_EVENTQ, &rv); + NS_WITH_PROXIED_SERVICE(nsIAddrBookSession, abSession, + NS_ADDRBOOKSESSION_CONTRACTID, + NS_PROXY_TO_MAIN_THREAD, &rv); if (NS_SUCCEEDED(rv)) rv = abSession->GetUserProfileDirectory(getter_AddRefs(dbPath)); @@ -802,7 +798,9 @@ nsIAddrDatabase *GetAddressBook( const PRUnichar *name, PRBool makeNew) if (NS_SUCCEEDED(rv)) { IMPORT_LOG0( "Getting the address database factory\n"); - NS_WITH_PROXIED_SERVICE(nsIAddrDatabase, addrDBFactory, NS_ADDRDATABASE_CONTRACTID, NS_UI_THREAD_EVENTQ, &rv); + NS_WITH_PROXIED_SERVICE(nsIAddrDatabase, addrDBFactory, + NS_ADDRDATABASE_CONTRACTID, + NS_PROXY_TO_MAIN_THREAD, &rv); if (NS_SUCCEEDED(rv) && addrDBFactory) { IMPORT_LOG0( "Opening the new address book\n"); rv = addrDBFactory->Open( dbPath, PR_TRUE, PR_TRUE, &pDatabase); @@ -820,7 +818,8 @@ nsIAddrDatabase *GetAddressBook( const PRUnichar *name, PRBool makeNew) // This is major bogosity again! Why doesn't the address book // just handle this properly for me? Uggggg... - NS_WITH_PROXIED_SERVICE(nsIRDFService, rdfService, kRDFServiceCID, NS_UI_THREAD_EVENTQ, &rv); + NS_WITH_PROXIED_SERVICE(nsIRDFService, rdfService, kRDFServiceCID, + NS_PROXY_TO_MAIN_THREAD, &rv); if (NS_SUCCEEDED(rv)) { nsCOMPtr parentResource; rv = rdfService->GetResource(NS_LITERAL_CSTRING(kAllDirectoryRoot), @@ -837,8 +836,11 @@ nsIAddrDatabase *GetAddressBook( const PRUnichar *name, PRBool makeNew) * a thread other than the UI thread. * */ - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID( nsIAbDirectory), - parentResource, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs( parentDir)); + rv = NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID( nsIAbDirectory), + parentResource, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs( parentDir)); if (parentDir) { nsCAutoString URI("moz-abmdbdirectory://"); @@ -924,10 +926,10 @@ PR_STATIC_CALLBACK( void) ImportAddressThread( void *stuff) } nsCOMPtr proxyAddrDatabase; - rv = NS_GetProxyForObject(NS_UI_THREAD_EVENTQ, + rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIAddrDatabase), pDestDB, - PROXY_SYNC | PROXY_ALWAYS, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(proxyAddrDatabase)); if (NS_FAILED(rv)) return; diff --git a/mozilla/mailnews/import/src/nsImportMail.cpp b/mozilla/mailnews/import/src/nsImportMail.cpp index 36c20cf701a..3a0c8a1e009 100644 --- a/mozilla/mailnews/import/src/nsImportMail.cpp +++ b/mozilla/mailnews/import/src/nsImportMail.cpp @@ -78,7 +78,6 @@ #define IMPORT_MSGS_URL "chrome://messenger/locale/importMsgs.properties" -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); static NS_DEFINE_CID(kSupportsWStringCID, NS_SUPPORTS_STRING_CID); //////////////////////////////////////////////////////////////////////// @@ -786,23 +785,18 @@ ImportMailThread( void *stuff) } // Initialize the curFolder proxy object - nsCOMPtr proxyMgr = - do_GetService(kProxyObjectManagerCID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIMsgFolder), - curFolder, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs( curProxy)); + rv = NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIMsgFolder), + curFolder, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs( curProxy)); - if (NS_SUCCEEDED(rv)) - // GetSubfolders() will initialize folders if they are not already initialized. - curProxy->GetSubFolders(getter_AddRefs(enumerator)); - else - IMPORT_LOG1( "*** ImportMailThread: Can't get the destination root folder proxy. rv=(0x%lx)", (long) rv); - } - else { - IMPORT_LOG0("*** ImportMailThread: Unable to obtain proxy service to do the import."); - nsImportStringBundle::GetStringByID( IMPORT_ERROR_MB_NOPROXY, error, pBundle); - pData->abort = PR_TRUE; - } + if (NS_SUCCEEDED(rv)) { + // GetSubfolders() will initialize folders if they are not already initialized. + curProxy->GetSubFolders(getter_AddRefs(enumerator)); + } else { + IMPORT_LOG1( "*** ImportMailThread: Can't get the destination root folder proxy. rv=(0x%lx)", (long) rv); + } IMPORT_LOG1("ImportMailThread: Total number of folders to import = %d.", count); @@ -834,8 +828,11 @@ ImportMailThread( void *stuff) break; } - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIMsgFolder), - subFolder, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs( curProxy)); + rv = NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIMsgFolder), + subFolder, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs( curProxy)); if (NS_FAILED( rv)) { IMPORT_LOG1("*** ImportMailThread: Failed to get the proxy interface for child folder '%s'.", NS_ConvertUTF16toUTF8(lastName).get()); nsImportStringBundle::GetStringByID( IMPORT_ERROR_MB_NOPROXY, error, pBundle); @@ -858,8 +855,11 @@ ImportMailThread( void *stuff) break; } - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIMsgFolder), - parFolder, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs( curProxy)); + rv = NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIMsgFolder), + parFolder, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs( curProxy)); depth--; } if (NS_FAILED( rv)) { diff --git a/mozilla/mailnews/import/src/nsImportStringBundle.cpp b/mozilla/mailnews/import/src/nsImportStringBundle.cpp index 1ebb640f606..d09abed1f83 100644 --- a/mozilla/mailnews/import/src/nsImportStringBundle.cpp +++ b/mozilla/mailnews/import/src/nsImportStringBundle.cpp @@ -44,8 +44,6 @@ #include "nsIProxyObjectManager.h" #include "nsIURI.h" -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); - nsresult nsImportStringBundle::GetStringBundle(const char* aPropertyURL, nsIStringBundle** aBundle) { nsresult rv; @@ -61,15 +59,12 @@ nsresult nsImportStringBundle::GetStringBundle(const char* aPropertyURL, nsIStri nsresult nsImportStringBundle::GetStringBundleProxy(nsIStringBundle* aOriginalBundle, nsIStringBundle **aProxy) { - nsresult rv; // create a proxy object if we aren't on the same thread? - nsCOMPtr proxyMgr = - do_GetService(kProxyObjectManagerCID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIStringBundle), - aOriginalBundle, PROXY_SYNC | PROXY_ALWAYS, (void **) aProxy); - } - return rv; + return NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIStringBundle), + aOriginalBundle, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + (void **) aProxy); } void nsImportStringBundle::GetStringByID(PRInt32 stringID, nsString& result, nsIStringBundle *aBundle) diff --git a/mozilla/mailnews/import/text/src/nsTextStringBundle.cpp b/mozilla/mailnews/import/text/src/nsTextStringBundle.cpp index 2bdeec051ce..9c6c281c040 100644 --- a/mozilla/mailnews/import/text/src/nsTextStringBundle.cpp +++ b/mozilla/mailnews/import/text/src/nsTextStringBundle.cpp @@ -46,8 +46,6 @@ #include "nsIProxyObjectManager.h" #include "nsIURI.h" -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); - nsIStringBundle * nsTextStringBundle::m_pBundle = nsnull; #define TEXT_MSGS_URL "chrome://messenger/locale/textImportMsgs.properties" @@ -79,14 +77,12 @@ nsIStringBundle *nsTextStringBundle::GetStringBundleProxy( void) return( nsnull); nsIStringBundle *strProxy = nsnull; - nsresult rv; // create a proxy object if we aren't on the same thread? - nsCOMPtr proxyMgr = - do_GetService(kProxyObjectManagerCID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIStringBundle), - m_pBundle, PROXY_SYNC | PROXY_ALWAYS, (void **) &strProxy); - } + NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIStringBundle), + m_pBundle, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + (void **) &strProxy); return( strProxy); } diff --git a/mozilla/mailnews/local/src/nsLocalUndoTxn.cpp b/mozilla/mailnews/local/src/nsLocalUndoTxn.cpp index 0928e8d423e..275a41fa7e2 100644 --- a/mozilla/mailnews/local/src/nsLocalUndoTxn.cpp +++ b/mozilla/mailnews/local/src/nsLocalUndoTxn.cpp @@ -44,10 +44,8 @@ #include "nsIImapService.h" #include "nsIUrlListener.h" #include "nsIMsgLocalMailFolder.h" -#include "nsIEventQueueService.h" #include "nsIMsgMailSession.h" - -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); +#include "nsThreadUtils.h" nsLocalMoveCopyMsgTxn::nsLocalMoveCopyMsgTxn() : m_isMove(PR_FALSE), m_srcIsImap4(PR_FALSE) @@ -190,36 +188,29 @@ nsLocalMoveCopyMsgTxn::UndoImapDeleteFlag(nsIMsgFolder* folder, msgIds.Append(','); msgIds.AppendInt((PRInt32) keyArray.GetAt(i)); } - nsCOMPtr eventQueue; - nsCOMPtr pEventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_SUCCEEDED(rv) && pEventQService) + nsIThread *thread = NS_GetCurrentThread(); + if (thread) { - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(eventQueue)); - if (eventQueue) - { - // This is to make sure that we are in the selected state - // when executing the imap url; we don't want to load the - // folder so use lite select to do the trick - rv = imapService->LiteSelectFolder(eventQueue, folder, - urlListener, nsnull); - if (!deleteFlag) - rv =imapService->AddMessageFlags(eventQueue, folder, - urlListener, nsnull, - msgIds.get(), - kImapMsgDeletedFlag, - PR_TRUE); - else - rv = imapService->SubtractMessageFlags(eventQueue, - folder, - urlListener, nsnull, - msgIds.get(), - kImapMsgDeletedFlag, - PR_TRUE); - if (NS_SUCCEEDED(rv) && m_msgWindow) - folder->UpdateFolder(m_msgWindow); - } + // This is to make sure that we are in the selected state + // when executing the imap url; we don't want to load the + // folder so use lite select to do the trick + rv = imapService->LiteSelectFolder(thread, folder, + urlListener, nsnull); + if (!deleteFlag) + rv =imapService->AddMessageFlags(thread, folder, + urlListener, nsnull, + msgIds.get(), + kImapMsgDeletedFlag, + PR_TRUE); + else + rv = imapService->SubtractMessageFlags(thread, + folder, + urlListener, nsnull, + msgIds.get(), + kImapMsgDeletedFlag, + PR_TRUE); + if (NS_SUCCEEDED(rv) && m_msgWindow) + folder->UpdateFolder(m_msgWindow); } } rv = NS_OK; // always return NS_OK to indicate that the src is imap diff --git a/mozilla/mailnews/mapi/mapihook/src/msgMapiHook.cpp b/mozilla/mailnews/mapi/mapihook/src/msgMapiHook.cpp index 4e3c1270205..a587c6eadb7 100644 --- a/mozilla/mailnews/mapi/mapihook/src/msgMapiHook.cpp +++ b/mozilla/mailnews/mapi/mapihook/src/msgMapiHook.cpp @@ -83,6 +83,7 @@ #include "msgMapiHook.h" #include "msgMapiSupport.h" #include "msgMapiMain.h" +#include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsEmbedCID.h" @@ -413,15 +414,13 @@ nsresult nsMapiHook::BlindSendMail (unsigned long aSession, nsIMsgCompFields * a // we need to wait here to make sure that we return only after send is completed // so we will have a event loop here which will process the events till the Send IsDone. - nsCOMPtr pEventQService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - nsCOMPtr eventQueue; - pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,getter_AddRefs(eventQueue)); + nsIThread *thread = NS_GetCurrentThread(); while ( !((nsMAPISendListener *) pSendListener)->IsDone() ) { PR_CEnterMonitor(pSendListener); PR_CWait(pSendListener, PR_MicrosecondsToInterval(1000UL)); PR_CExitMonitor(pSendListener); - eventQueue->ProcessPendingEvents(); + NS_ProcessPendingEvents(thread); } return rv ; diff --git a/mozilla/mailnews/mime/src/mimecms.cpp b/mozilla/mailnews/mime/src/mimecms.cpp index 97a6a1ff1bd..bcec5617596 100644 --- a/mozilla/mailnews/mime/src/mimecms.cpp +++ b/mozilla/mailnews/mime/src/mimecms.cpp @@ -53,6 +53,7 @@ #include "nsIMimeMiscStatus.h" #include "nsIMsgSMIMEHeaderSink.h" #include "nsCOMPtr.h" +#include "nsAutoPtr.h" #include "nsIX509Cert.h" #include "nsIMsgHeaderParser.h" #include "nsIProxyObjectManager.h" @@ -326,16 +327,11 @@ NS_IMETHODIMP nsSMimeVerificationListener::Notify(nsICMSMessage2 *aVerifiedMessa signature_status = nsICMSMessageErrors::SUCCESS; } - - nsCOMPtr proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID)); - if (proxyman) - { - nsCOMPtr proxySink; - proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIMsgSMIMEHeaderSink), - mHeaderSink, PROXY_SYNC, getter_AddRefs(proxySink)); - if (proxySink) - proxySink->SignedStatus(mMimeNestingLevel, signature_status, signerCert); - } + nsCOMPtr proxySink; + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIMsgSMIMEHeaderSink), + mHeaderSink, NS_PROXY_SYNC, getter_AddRefs(proxySink)); + if (proxySink) + proxySink->SignedStatus(mMimeNestingLevel, signature_status, signerCert); return NS_OK; } diff --git a/mozilla/modules/libpr0n/src/imgLoader.cpp b/mozilla/modules/libpr0n/src/imgLoader.cpp index 310483b4086..e22d45cf614 100644 --- a/mozilla/modules/libpr0n/src/imgLoader.cpp +++ b/mozilla/modules/libpr0n/src/imgLoader.cpp @@ -46,6 +46,7 @@ #include "nsICachingChannel.h" #include "nsIProxyObjectManager.h" #include "nsIServiceManager.h" +#include "nsThreadUtils.h" #include "nsXPIDLString.h" #include "nsCRT.h" @@ -356,26 +357,10 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, } // - // Get the current EventQueue... This is used as a cacheId to prevent - // sharing requests which are being loaded across multiple event queues... + // Get the current thread... This is used as a cacheId to prevent + // sharing requests which are being loaded across multiple threads... // - nsCOMPtr eventQService; - nsCOMPtr activeQ; - - eventQService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) { - NS_IF_RELEASE(request); - return rv; - } - - rv = eventQService->ResolveEventQueue(NS_CURRENT_EVENTQ, - getter_AddRefs(activeQ)); - if (NS_FAILED(rv)) { - NS_IF_RELEASE(request); - return rv; - } - - void *cacheId = activeQ.get(); + void *cacheId = NS_GetCurrentThread(); if (request && !request->IsReusable(cacheId)) { // // The current request is still being loaded and lives on a different @@ -633,19 +618,10 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb *listener = nsnull; // give them back a null nsIStreamListener } else { // - // Get the current EventQueue... This is used as a cacheId to prevent - // sharing requests which are being loaded across multiple event queues... + // Get the current Thread... This is used as a cacheId to prevent + // sharing requests which are being loaded across multiple threads... // - nsCOMPtr eventQService; - nsCOMPtr activeQ; - - eventQService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return rv; - - rv = eventQService->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(activeQ)); - if (NS_FAILED(rv)) - return rv; + nsIThread *thread = NS_GetCurrentThread(); NS_NEWXPCOM(request, imgRequest); if (!request) return NS_ERROR_OUT_OF_MEMORY; @@ -659,7 +635,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb // the cache should use the original URI? See bug 89419. nsCOMPtr originalURI; channel->GetOriginalURI(getter_AddRefs(originalURI)); - request->Init(originalURI, channel, entry, activeQ.get(), aCX); + request->Init(originalURI, channel, entry, thread, aCX); ProxyListener *pl = new ProxyListener(NS_STATIC_CAST(nsIStreamListener *, request)); if (!pl) { @@ -977,14 +953,6 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport mRequest->mValidator = nsnull; NS_RELEASE(mRequest); // assigns null - nsresult rv; - nsCOMPtr eventQService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr activeQ; - rv = eventQService->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(activeQ)); - if (NS_FAILED(rv)) return rv; - imgRequest *request; NS_NEWXPCOM(request, imgRequest); if (!request) return NS_ERROR_OUT_OF_MEMORY; @@ -997,7 +965,7 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport // the cache should use the original URI? See bug 89419. nsCOMPtr originalURI; channel->GetOriginalURI(getter_AddRefs(originalURI)); - request->Init(originalURI, channel, entry, activeQ.get(), mContext); + request->Init(originalURI, channel, entry, NS_GetCurrentThread(), mContext); ProxyListener *pl = new ProxyListener(NS_STATIC_CAST(nsIStreamListener *, request)); if (!pl) { diff --git a/mozilla/modules/oji/public/Makefile.in b/mozilla/modules/oji/public/Makefile.in index d8971cbfe7e..1b7f7e38661 100644 --- a/mozilla/modules/oji/public/Makefile.in +++ b/mozilla/modules/oji/public/Makefile.in @@ -64,7 +64,7 @@ EXPORTS = \ nsISymantecDebugger.h \ nsISecureEnv.h \ ProxyJNI.h \ - nsIThreadManager.h \ + nsIJVMThreadManager.h \ nsILiveConnectManager.h \ $(NULL) diff --git a/mozilla/modules/oji/public/nsIThreadManager.h b/mozilla/modules/oji/public/nsIJVMThreadManager.h similarity index 87% rename from mozilla/modules/oji/public/nsIThreadManager.h rename to mozilla/modules/oji/public/nsIJVMThreadManager.h index ec8a8e2aa3b..87408e698bb 100644 --- a/mozilla/modules/oji/public/nsIThreadManager.h +++ b/mozilla/modules/oji/public/nsIJVMThreadManager.h @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 sts=4 ci et: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -35,8 +36,8 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef nsIThreadManager_h___ -#define nsIThreadManager_h___ +#ifndef nsIJVMThreadManager_h___ +#define nsIJVMThreadManager_h___ #include "nsISupports.h" #include "nsIRunnable.h" @@ -48,7 +49,7 @@ // Thread Manager // This interface provides thread primitives. -#define NS_ITHREADMANAGER_IID \ +#define NS_IJVMTHREADMANAGER_IID \ { /* 97bb54c0-6846-11d2-801f-00805f71101c */ \ 0x97bb54c0, \ 0x6846, \ @@ -58,9 +59,9 @@ class nsIRunnable; -class nsIThreadManager : public nsISupports { +class nsIJVMThreadManager : public nsISupports { public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITHREADMANAGER_IID) + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJVMTHREADMANAGER_IID) /** * Returns a unique identifier for the "current" system thread. @@ -124,6 +125,12 @@ public: PostEvent(PRThread* thread, nsIRunnable* runnable, PRBool async) = 0; }; -NS_DEFINE_STATIC_IID_ACCESSOR(nsIThreadManager, NS_ITHREADMANAGER_IID) +NS_DEFINE_STATIC_IID_ACCESSOR(nsIJVMThreadManager, NS_IJVMTHREADMANAGER_IID) -#endif /* nsIThreadManager_h___ */ +#ifndef NS_OJI_IMPL +// For backwards compatibility: +typedef nsIJVMThreadManager nsIThreadManager; +#define NS_ITHREADMANAGER_IID NS_IJVMTHREADMANAGER_IID +#endif + +#endif /* nsIJVMThreadManager_h___ */ diff --git a/mozilla/modules/oji/public/nsjvm.h b/mozilla/modules/oji/public/nsjvm.h index 623bbaf4b39..768e9470e82 100644 --- a/mozilla/modules/oji/public/nsjvm.h +++ b/mozilla/modules/oji/public/nsjvm.h @@ -58,7 +58,7 @@ #include "nsISymantecDebugManager.h" #include "nsISymantecDebugger.h" #include "nsILiveconnect.h" -#include "nsIThreadManager.h" +#include "nsIJVMThreadManager.h" //////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/modules/oji/src/Makefile.in b/mozilla/modules/oji/src/Makefile.in index 02e69776902..73e099404e5 100644 --- a/mozilla/modules/oji/src/Makefile.in +++ b/mozilla/modules/oji/src/Makefile.in @@ -101,13 +101,14 @@ CPPSRCS += \ $(NULL) endif +DEFINES += -DNS_OJI_IMPL=1 + EXPORTS = \ jvmmgr.h \ nsJVMManager.h \ nsJVMPluginTagInfo.h \ $(NULL) - EXTRA_DSO_LDOPTS = \ $(LIBS_DIR) \ $(EXTRA_DSO_LIBS) \ diff --git a/mozilla/modules/oji/src/lcglue.h b/mozilla/modules/oji/src/lcglue.h index 1b8135bea44..3300e859608 100644 --- a/mozilla/modules/oji/src/lcglue.h +++ b/mozilla/modules/oji/src/lcglue.h @@ -43,7 +43,7 @@ #include "jsdbgapi.h" #include "nsError.h" -#include "nsIThreadManager.h" +#include "nsIJVMThreadManager.h" #include "nsISecurityContext.h" /** diff --git a/mozilla/modules/oji/src/nsJVMManager.cpp b/mozilla/modules/oji/src/nsJVMManager.cpp index 75926128e84..4eabb4706e0 100644 --- a/mozilla/modules/oji/src/nsJVMManager.cpp +++ b/mozilla/modules/oji/src/nsJVMManager.cpp @@ -1,5 +1,6 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 sts=4 ci et: */ +/* * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -60,7 +61,9 @@ #include "ProxyJNI.h" #include "nsIPluginHost.h" #include "nsIServiceManager.h" -#include "nsIEventQueueService.h" +#include "nsIThreadManager.h" +#include "nsIThread.h" +#include "nsXPCOMCIDInternal.h" // All these interfaces are necessary just to get the damn // nsIWebBrowserChrome to send the "Starting Java" message to the status @@ -104,8 +107,6 @@ static NS_DEFINE_CID(kJVMManagerCID, NS_JVMMANAGER_CID); static NS_DEFINE_CID(kPluginManagerCID, NS_PLUGINMANAGER_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - // FIXME -- need prototypes for these functions!!! XXX #ifdef XP_MAC extern "C" { @@ -117,7 +118,7 @@ void stopAsyncCursors(void); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIJVMManagerIID, NS_IJVMMANAGER_IID); -static NS_DEFINE_IID(kIThreadManagerIID, NS_ITHREADMANAGER_IID); +static NS_DEFINE_IID(kIJVMThreadManagerIID, NS_IJVMTHREADMANAGER_IID); static NS_DEFINE_IID(kILiveConnectManagerIID, NS_ILIVECONNECTMANAGER_IID); static NS_DEFINE_IID(kIJVMPluginIID, NS_IJVMPLUGIN_IID); @@ -291,57 +292,22 @@ nsJVMManager::CreateThread(PRThread **outThread, nsIRunnable* runnable) return (thread != NULL ? NS_OK : NS_ERROR_FAILURE); } -struct JVMRunnableEvent : PLEvent { - JVMRunnableEvent(nsIRunnable* runnable); - ~JVMRunnableEvent(); - - nsIRunnable* mRunnable; -}; - -static void PR_CALLBACK -handleRunnableEvent(JVMRunnableEvent* aEvent) -{ - aEvent->mRunnable->Run(); -} - -static void PR_CALLBACK -destroyRunnableEvent(JVMRunnableEvent* aEvent) -{ - delete aEvent; -} - -JVMRunnableEvent::JVMRunnableEvent(nsIRunnable* runnable) - : mRunnable(runnable) -{ - NS_ADDREF(mRunnable); - PL_InitEvent(this, nsnull, PLHandleEventProc(handleRunnableEvent), PLDestroyEventProc(&destroyRunnableEvent)); -} - -JVMRunnableEvent::~JVMRunnableEvent() -{ - NS_RELEASE(mRunnable); -} - NS_METHOD -nsJVMManager::PostEvent(PRThread* thread, nsIRunnable* runnable, PRBool async) +nsJVMManager::PostEvent(PRThread* prthread, nsIRunnable* runnable, PRBool async) { nsresult rv; - nsCOMPtr eventService = - do_GetService(kEventQueueServiceCID, &rv); + nsCOMPtr mgr = + do_GetService(NS_THREADMANAGER_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; - nsCOMPtr eventQueue = NULL; - rv = eventService->GetThreadEventQueue(thread, getter_AddRefs(eventQueue)); + nsCOMPtr thread; + rv = mgr->GetThreadFromPRThread(prthread, getter_AddRefs(thread)); if (NS_FAILED(rv)) return rv; - JVMRunnableEvent* runnableEvent = new JVMRunnableEvent(runnable); - if (runnableEvent == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - if (async) - eventQueue->PostEvent(runnableEvent); - else - eventQueue->PostSynchronousEvent(runnableEvent, nsnull); - return rv; + NS_ENSURE_STATE(thread); + + return thread->Dispatch(runnable, async ? NS_DISPATCH_NORMAL + : NS_DISPATCH_SYNC); } nsJVMManager::nsJVMManager(nsISupports* outer) @@ -386,8 +352,8 @@ nsJVMManager::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr) NS_ADDREF_THIS(); return NS_OK; } - if (aIID.Equals(kIThreadManagerIID)) { - *aInstancePtr = (void*) NS_STATIC_CAST(nsIThreadManager*, this); + if (aIID.Equals(kIJVMThreadManagerIID)) { + *aInstancePtr = (void*) NS_STATIC_CAST(nsIJVMThreadManager*, this); NS_ADDREF_THIS(); return NS_OK; } diff --git a/mozilla/modules/oji/src/nsJVMManager.h b/mozilla/modules/oji/src/nsJVMManager.h index 56619840399..679cbed5bbe 100644 --- a/mozilla/modules/oji/src/nsJVMManager.h +++ b/mozilla/modules/oji/src/nsJVMManager.h @@ -62,7 +62,8 @@ class nsIWebBrowserChrome; * nsIJVMManager is the more limited interface what the JVM plugin sees. ******************************************************************************/ -struct nsJVMManager : public nsIJVMManager, public nsIThreadManager, public nsILiveConnectManager, public nsIObserver { +struct nsJVMManager : public nsIJVMManager, public nsIJVMThreadManager, + public nsILiveConnectManager, public nsIObserver { public: NS_DECL_AGGREGATED @@ -71,7 +72,7 @@ public: NS_DECL_NSIOBSERVER - /* from nsIThreadManager: */ + /* from nsIJVMThreadManager: */ /** * Returns a unique identifier for the "current" system thread. diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp index 1ab9d85c563..0555c418287 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -122,9 +122,7 @@ #include "nsIDOMMimeType.h" #include "nsMimeTypes.h" #include "prprf.h" -#include "plevent.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" +#include "nsThreadUtils.h" #include "nsIInputStreamTee.h" #include "nsIInterfaceInfoManager.h" #include "xptinfo.h" @@ -222,7 +220,6 @@ static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID); static const char kDirectoryServiceContractID[] = "@mozilla.org/file/directory_service;1"; // for the dialog static NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kCPluginManagerCID, NS_PLUGINMANAGER_CID); // needed for NS_TRY_SAFE_CALL //////////////////////////////////////////////////////////////////////// @@ -302,13 +299,14 @@ PRBool ReadSectionHeader(nsPluginManifestLineReader& reader, const char *token) // Little helper struct to asynchronously reframe any presentations (embedded) // or reload any documents (full-page), that contained plugins // which were shutdown as a result of a plugins.refresh(1) -struct nsPluginDocReframeEvent: public PLEvent { - nsPluginDocReframeEvent (nsISupportsArray* aDocs) { mDocs = aDocs; } - nsresult HandlePluginDocReframeEvent(); +class nsPluginDocReframeEvent: public nsRunnable { +public: + nsPluginDocReframeEvent(nsISupportsArray* aDocs) { mDocs = aDocs; } + NS_IMETHOD Run(); nsCOMPtr mDocs; }; -nsresult nsPluginDocReframeEvent::HandlePluginDocReframeEvent() { +NS_IMETHODIMP nsPluginDocReframeEvent::Run() { NS_ENSURE_TRUE(mDocs, NS_ERROR_FAILURE); PRUint32 c; @@ -345,25 +343,6 @@ nsresult nsPluginDocReframeEvent::HandlePluginDocReframeEvent() { return mDocs->Clear(); } - - - -//---------------------------------------------------------------------- -static void* PR_CALLBACK HandlePluginDocReframePLEvent(PLEvent* aEvent) -{ - nsPluginDocReframeEvent* event = - NS_STATIC_CAST(nsPluginDocReframeEvent*, aEvent); - event->HandlePluginDocReframeEvent(); - return nsnull; -} -static void PR_CALLBACK DestroyPluginDocReframePLEvent(PLEvent* aEvent) -{ - nsPluginDocReframeEvent* event = - NS_STATIC_CAST(nsPluginDocReframeEvent*, aEvent); - delete event; -} - - //////////////////////////////////////////////////////////////////////// nsActivePlugin::nsActivePlugin(nsPluginTag* aPluginTag, nsIPluginInstance* aInstance, @@ -976,55 +955,31 @@ void nsPluginTag::SetHost(nsPluginHostImpl * aHost) //---------------------------------------------------------------------- // helper struct for asynchronous handeling of plugin unloading -struct nsPluginUnloadEvent: public PLEvent { - nsPluginUnloadEvent (PRLibrary* aLibrary); +class nsPluginUnloadEvent : public nsRunnable { +public: + nsPluginUnloadEvent(PRLibrary* aLibrary) + : mLibrary(aLibrary) + {} - void HandleEvent() { - if (mLibrary) - NS_TRY_SAFE_CALL_VOID(PR_UnloadLibrary(mLibrary), nsnull, nsnull); // put our unload call in a saftey wrapper - else + NS_IMETHOD Run() { + if (mLibrary) { + // put our unload call in a saftey wrapper + NS_TRY_SAFE_CALL_VOID(PR_UnloadLibrary(mLibrary), nsnull, nsnull); + } else { NS_WARNING("missing library from nsPluginUnloadEvent"); + } + return NS_OK; } PRLibrary* mLibrary; }; -nsPluginUnloadEvent::nsPluginUnloadEvent (PRLibrary* aLibrary) -{ - mLibrary = aLibrary; -} -//---------------------------------------------------------------------- -// helper static callback functions for plugin unloading PLEvents -static void* PR_CALLBACK HandlePluginUnloadPLEvent(PLEvent* aEvent) -{ - nsPluginUnloadEvent *event = NS_STATIC_CAST(nsPluginUnloadEvent*, aEvent); - event->HandleEvent(); - return nsnull; -} -static void PR_CALLBACK DestroyPluginUnloadPLEvent(PLEvent* aEvent) -{ - nsPluginUnloadEvent *event = NS_STATIC_CAST(nsPluginUnloadEvent*, aEvent); - delete event; -} // unload plugin asynchronously if possible, otherwise just unload now -nsresult PostPluginUnloadEvent (PRLibrary* aLibrary) +nsresult PostPluginUnloadEvent(PRLibrary* aLibrary) { - nsCOMPtr eventService(do_GetService(kEventQueueServiceCID)); - if (eventService) { - nsCOMPtr eventQueue; - eventService->GetThreadEventQueue(PR_GetCurrentThread(), getter_AddRefs(eventQueue)); - if (eventQueue) { - nsPluginUnloadEvent * ev = new nsPluginUnloadEvent(aLibrary); - if (ev) { - - PL_InitEvent(ev, nsnull, ::HandlePluginUnloadPLEvent, ::DestroyPluginUnloadPLEvent); - if (NS_SUCCEEDED(eventQueue->PostEvent(ev))) - return NS_OK; - else NS_WARNING("failed to post event onto queue"); - - } else NS_WARNING("not able to create plugin unload event"); - } else NS_WARNING("couldn't get event queue"); - } else NS_WARNING("couldn't get event queue service"); + nsCOMPtr ev = new nsPluginUnloadEvent(aLibrary); + if (ev && NS_SUCCEEDED(NS_DispatchToCurrentThread(ev))) + return NS_OK; // failure case NS_TRY_SAFE_CALL_VOID(PR_UnloadLibrary(aLibrary), nsnull, nsnull); @@ -2753,19 +2708,9 @@ nsresult nsPluginHostImpl::ReloadPlugins(PRBool reloadPages) instsToReload && NS_SUCCEEDED(instsToReload->Count(&c)) && c > 0) { - nsCOMPtr eventService(do_GetService(kEventQueueServiceCID)); - if (eventService) { - nsCOMPtr eventQueue; - eventService->GetThreadEventQueue(PR_GetCurrentThread(), getter_AddRefs(eventQueue)); - if (eventQueue) { - nsPluginDocReframeEvent * ev = new nsPluginDocReframeEvent(instsToReload); - if (ev) { - PL_InitEvent(ev, nsnull, HandlePluginDocReframePLEvent, DestroyPluginDocReframePLEvent); - eventQueue->PostEvent(ev); - } - } - } - + nsCOMPtr ev = new nsPluginDocReframeEvent(instsToReload); + if (ev) + NS_DispatchToCurrentThread(ev); } PLUGIN_LOG(PLUGIN_LOG_NORMAL, diff --git a/mozilla/modules/plugin/base/src/nsPluginNativeWindowWin.cpp b/mozilla/modules/plugin/base/src/nsPluginNativeWindowWin.cpp index 5a8e888fd1a..1108cb3000c 100644 --- a/mozilla/modules/plugin/base/src/nsPluginNativeWindowWin.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginNativeWindowWin.cpp @@ -50,37 +50,41 @@ #include "nsDebug.h" -#include "plevent.h" -#include "nsIEventQueueService.h" #include "nsGUIEvent.h" #include "nsIPluginInstancePeer.h" #include "nsIPluginInstanceInternal.h" #include "nsPluginSafety.h" #include "nsPluginNativeWindow.h" +#include "nsThreadUtils.h" +#include "nsAutoPtr.h" +#include "nsTWeakRef.h" -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kCPluginManagerCID, NS_PLUGINMANAGER_CID); // needed for NS_TRY_SAFE_CALL #define NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION "MozillaPluginWindowPropertyAssociation" +typedef nsTWeakRef PluginWindowWeakRef; + /** * PLEvent handling code */ -class PluginWindowEvent : public PLEvent { +class PluginWindowEvent : public nsRunnable { public: PluginWindowEvent(); - void Init(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + void Init(const PluginWindowWeakRef &ref, HWND hWnd, UINT msg, WPARAM wParam, + LPARAM lParam); void Clear(); HWND GetWnd() { return mWnd; }; UINT GetMsg() { return mMsg; }; WPARAM GetWParam() { return mWParam; }; LPARAM GetLParam() { return mLParam; }; - PRBool GetIsAlloced() { return mIsAlloced; }; - void SetIsAlloced(PRBool aIsAlloced) { mIsAlloced = aIsAlloced; }; - PRBool InUse() { return (mWnd!=NULL || mMsg!=0); }; + PRBool InUse() { return (mWnd!=NULL || mMsg!=0); }; + + NS_IMETHOD Run(); protected: + PluginWindowWeakRef mPluginWindowRef; HWND mWnd; UINT mMsg; WPARAM mWParam; @@ -101,10 +105,12 @@ void PluginWindowEvent::Clear() mLParam = 0; } -void PluginWindowEvent::Init(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam) +void PluginWindowEvent::Init(const PluginWindowWeakRef &ref, HWND aWnd, + UINT aMsg, WPARAM aWParam, LPARAM aLParam) { NS_ASSERTION(aWnd!=NULL && aMsg!=0, "invalid plugin event value"); NS_ASSERTION(mWnd==NULL && mMsg==0 && mWParam==0 && mLParam==0,"event already in use"); + mPluginWindowRef = ref; mWnd = aWnd; mMsg = aMsg; mWParam = aWParam; @@ -139,14 +145,13 @@ public: // locals WNDPROC GetPrevWindowProc(); WNDPROC GetWindowProc(); - nsIEventQueueService *GetEventService(); PluginWindowEvent * GetPluginWindowEvent(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam); private: WNDPROC mPrevWinProc; WNDPROC mPluginWinProc; - nsCOMPtr mEventService; - PluginWindowEvent mPluginWindowEvent; + PluginWindowWeakRef mWeakRef; + nsRefPtr mCachedPluginWindowEvent; public: nsPluginType mPluginType; @@ -164,43 +169,27 @@ static PRBool ProcessFlashMessageDelayed(nsPluginNativeWindowWin * aWin, return PR_FALSE; // no need to delay // do stuff - nsIEventQueueService *eventService = aWin->GetEventService(); - if (eventService) { - nsCOMPtr eventQueue; - eventService->GetThreadEventQueue(PR_GetCurrentThread(), - getter_AddRefs(eventQueue)); - if (eventQueue) { - PluginWindowEvent *pwe = aWin->GetPluginWindowEvent(hWnd, msg, wParam, lParam); - if (pwe) { - eventQueue->PostEvent(pwe); - return PR_TRUE; - } - } + nsCOMPtr pwe = aWin->GetPluginWindowEvent(hWnd, msg, wParam, lParam); + if (pwe) { + NS_DispatchToCurrentThread(pwe); + return PR_TRUE; } return PR_FALSE; } -PR_STATIC_CALLBACK(void*) -DelayedPopupsEnabledEvent_Handle(PLEvent *event) +class nsDelayedPopupsEnabledEvent : public nsRunnable { - nsIPluginInstanceInternal *instInternal = - (nsIPluginInstanceInternal *)event->owner; - - instInternal->PushPopupsEnabledState(PR_FALSE); - - return nsnull; -} - -PR_STATIC_CALLBACK(void) -DelayedPopupsEnabledEvent_Destroy(PLEvent *event) -{ - nsIPluginInstanceInternal *instInternal = - (nsIPluginInstanceInternal *)event->owner; - - NS_RELEASE(instInternal); - - delete event; -} +public: + nsDelayedPopupsEnabledEvent(nsIPluginInstanceInternal *inst) + : mInst(inst) + {} + NS_IMETHOD Run() { + mInst->PushPopupsEnabledState(PR_FALSE); + return NS_OK; + } +private: + nsCOMPtr mInst; +}; /** * New plugin window procedure @@ -375,26 +364,10 @@ static LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM // code will pop any popup state pushed by this plugin on // destruction. - nsIEventQueueService *eventService = win->GetEventService(); - if (eventService) { - nsCOMPtr eventQueue; - eventService->GetThreadEventQueue(PR_GetCurrentThread(), - getter_AddRefs(eventQueue)); - if (eventQueue) { - PLEvent *event = new PLEvent; - - if (event) { - nsIPluginInstanceInternal *eventInst = instInternal; - - // Make the event own the plugin instance. - NS_ADDREF(eventInst); - - PL_InitEvent(event, eventInst, DelayedPopupsEnabledEvent_Handle, - DelayedPopupsEnabledEvent_Destroy); - - eventQueue->PostEvent(event); - } - } + nsCOMPtr event = + new nsDelayedPopupsEnabledEvent(instInternal); + if (event) { + NS_DispatchToCurrentThread(event); } } @@ -415,21 +388,14 @@ nsPluginNativeWindowWin::nsPluginNativeWindowWin() : nsPluginNativeWindow() mPrevWinProc = NULL; mPluginWinProc = NULL; - mPluginWindowEvent.SetIsAlloced(PR_FALSE); mPluginType = nsPluginType_Unknown; } nsPluginNativeWindowWin::~nsPluginNativeWindowWin() { - // clear any pending events to avoid dangling pointers - nsCOMPtr eventService(do_GetService(kEventQueueServiceCID)); - if (eventService) { - nsCOMPtr eventQueue; - eventService->GetThreadEventQueue(PR_GetCurrentThread(), getter_AddRefs(eventQueue)); - if (eventQueue) { - eventQueue->RevokeEvents(this); - } - } + // clear weak reference to self to prevent any pending events from + // dereferencing this. + mWeakRef.forget(); } WNDPROC nsPluginNativeWindowWin::GetPrevWindowProc() @@ -442,61 +408,39 @@ WNDPROC nsPluginNativeWindowWin::GetWindowProc() return mPluginWinProc; } -PR_STATIC_CALLBACK(void*) -PluginWindowEvent_Handle(PLEvent* self) +NS_IMETHODIMP PluginWindowEvent::Run() { - if (!self) - return nsnull; + nsPluginNativeWindowWin *win = mPluginWindowRef.get(); + if (!win) + return NS_OK; - PluginWindowEvent *event = NS_STATIC_CAST(PluginWindowEvent*, self); - - HWND hWnd = event->GetWnd(); + HWND hWnd = GetWnd(); if (!hWnd) - return nsnull; + return NS_OK; - nsPluginNativeWindowWin * win = (nsPluginNativeWindowWin *)::GetProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION); - if (win) { - nsCOMPtr inst; - win->GetPluginInstance(inst); - NS_TRY_SAFE_CALL_VOID(::CallWindowProc(win->GetWindowProc(), - hWnd, - event->GetMsg(), - event->GetWParam(), - event->GetLParam()), - nsnull, inst); - } - - return nsnull; -} - -PR_STATIC_CALLBACK(void) -PluginWindowEvent_Destroy(PLEvent* self) -{ - if (!self) - return; - - PluginWindowEvent *event = NS_STATIC_CAST(PluginWindowEvent*, self); - if (event->GetIsAlloced()) { - delete event; - } - else - event->Clear(); -} - -nsIEventQueueService *nsPluginNativeWindowWin::GetEventService() -{ - if (!mEventService) { - mEventService = do_GetService(kEventQueueServiceCID); - } - - return mEventService; + nsCOMPtr inst; + win->GetPluginInstance(inst); + NS_TRY_SAFE_CALL_VOID(::CallWindowProc(win->GetWindowProc(), + hWnd, + GetMsg(), + GetWParam(), + GetLParam()), + nsnull, inst); + Clear(); + return NS_OK; } PluginWindowEvent* nsPluginNativeWindowWin::GetPluginWindowEvent(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam) { + if (!mWeakRef) { + mWeakRef = this; + if (!mWeakRef) + return nsnull; + } + PluginWindowEvent *event; - if (mPluginWindowEvent.InUse()) { + if (!mCachedPluginWindowEvent || mCachedPluginWindowEvent->InUse()) { // We have the ability to alloc if needed in case in the future some plugin // should post multiple PostMessages. However, this could lead to many // alloc's per second which could become a performance issue. If/when this @@ -505,15 +449,13 @@ nsPluginNativeWindowWin::GetPluginWindowEvent(HWND aWnd, UINT aMsg, WPARAM aWPar event = new PluginWindowEvent(); if (!event) return nsnull; - - event->SetIsAlloced(PR_TRUE); } else { - event = &mPluginWindowEvent; + event = mCachedPluginWindowEvent; } + NS_ADDREF(event); - event->Init(aWnd, aMsg, aWParam, aLParam); - PL_InitEvent(event, (void *)this, &PluginWindowEvent_Handle, PluginWindowEvent_Destroy); + event->Init(mWeakRef, aWnd, aMsg, aWParam, aLParam); return event; } diff --git a/mozilla/netwerk/base/public/Makefile.in b/mozilla/netwerk/base/public/Makefile.in index 8ffcb10416b..1bfefbc2236 100644 --- a/mozilla/netwerk/base/public/Makefile.in +++ b/mozilla/netwerk/base/public/Makefile.in @@ -94,7 +94,6 @@ XPIDLSRCS = \ nsIServerSocket.idl \ nsIResumableChannel.idl \ nsIRequestObserverProxy.idl \ - nsIStreamListenerProxy.idl \ nsIStreamListenerTee.idl \ nsISimpleStreamListener.idl \ nsIStreamTransportService.idl \ diff --git a/mozilla/netwerk/base/public/nsIAsyncStreamCopier.idl b/mozilla/netwerk/base/public/nsIAsyncStreamCopier.idl index cc8a7cdb401..febfcef8cc7 100644 --- a/mozilla/netwerk/base/public/nsIAsyncStreamCopier.idl +++ b/mozilla/netwerk/base/public/nsIAsyncStreamCopier.idl @@ -42,7 +42,7 @@ interface nsIOutputStream; interface nsIRequestObserver; interface nsIEventTarget; -[scriptable, uuid(eaa49141-c21c-4fe8-a79b-77860a3910aa)] +[scriptable, uuid(72e515de-a91e-4154-bb78-e5244cbaae74)] interface nsIAsyncStreamCopier : nsIRequest { /** @@ -67,12 +67,12 @@ interface nsIAsyncStreamCopier : nsIRequest * * NOTE: at least one of the streams must be buffered. */ - void init(in nsIInputStream aSource, - in nsIOutputStream aSink, - in nsIEventTarget aTarget, - in boolean aSourceBuffered, - in boolean aSinkBuffered, - in unsigned long aChunkSize); + void init(in nsIInputStream aSource, + in nsIOutputStream aSink, + in nsIEventTarget aTarget, + in boolean aSourceBuffered, + in boolean aSinkBuffered, + in unsigned long aChunkSize); /** * asyncCopy triggers the start of the copy. The observer will be notified diff --git a/mozilla/netwerk/base/public/nsIInputStreamPump.idl b/mozilla/netwerk/base/public/nsIInputStreamPump.idl index 026429ca720..5505e389821 100644 --- a/mozilla/netwerk/base/public/nsIInputStreamPump.idl +++ b/mozilla/netwerk/base/public/nsIInputStreamPump.idl @@ -46,7 +46,7 @@ interface nsIStreamListener; * * This interface provides a means to configure and use a input stream pump * instance. The input stream pump will asynchronously read from a input - * stream, and push data to a nsIStreamListener instance. It utilizes the + * stream, and push data to a nsIStreamListener instance. It utilizes the * current thread's nsIEventTarget in order to make reading from the stream * asynchronous. * diff --git a/mozilla/netwerk/base/public/nsIRequestObserverProxy.idl b/mozilla/netwerk/base/public/nsIRequestObserverProxy.idl index a819e1c830c..81033885630 100644 --- a/mozilla/netwerk/base/public/nsIRequestObserverProxy.idl +++ b/mozilla/netwerk/base/public/nsIRequestObserverProxy.idl @@ -38,25 +38,25 @@ #include "nsIRequestObserver.idl" -interface nsIEventQueue; +interface nsIEventTarget; /** - * A request observer proxy is used to ship data over to another thread specified - * by the thread's event queue. The "true" request observer's methods are - * invoked on the other thread. + * A request observer proxy is used to ship data over to another thread + * specified by the thread's dispatch target. The "true" request observer's + * methods are invoked on the other thread. * - * This interface only provides the initialization needed after construction. Otherwise, - * these objects are used simply as nsIRequestObserver's. + * This interface only provides the initialization needed after construction. + * Otherwise, these objects are used simply as nsIRequestObserver's. */ -[scriptable, uuid(3c9b532e-db84-4ecf-aa6a-4d38a9c4c5f0)] +[scriptable, uuid(7df8845f-938a-4437-9ea4-b11b850048f1)] interface nsIRequestObserverProxy : nsIRequestObserver { /** * Initializes an nsIRequestObserverProxy. * * @param observer - receives observer notifications on the other thread - * @param eventQ - may be NULL indicating the calling thread's event queue + * @param target - may be NULL indicating the calling thread's event target */ void init(in nsIRequestObserver observer, - in nsIEventQueue eventQ); + in nsIEventTarget target); }; diff --git a/mozilla/netwerk/base/public/nsIStreamListenerProxy.idl b/mozilla/netwerk/base/public/nsIStreamListenerProxy.idl deleted file mode 100644 index 705af532dde..00000000000 --- a/mozilla/netwerk/base/public/nsIStreamListenerProxy.idl +++ /dev/null @@ -1,88 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Darin Fisher (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsIStreamListener.idl" - -interface nsIEventQueue; - -/** - * A stream listener proxy is used to ship data over to another thread specified - * by the thread's event queue. The "true" stream listener's methods are - * invoked on the other thread. - * - * This interface only provides the initialization needed after construction. - * Otherwise, these objects are used as nsIStreamListener. - */ -[scriptable, uuid(e400e688-6b54-4a84-8c4e-56b40281981a)] -interface nsIStreamListenerProxy : nsIStreamListener -{ - /** - * Initializes an nsIStreamListenerProxy. - * - * @param aListener receives listener notifications on the other thread - * @param aEventQ may be NULL indicating the calling thread's event queue - * @param aBufferSegmentSize passing zero indicates the default - * @param aBufferMaxSize passing zero indicates the default - */ - void init(in nsIStreamListener aListener, - in nsIEventQueue aEventQ, - in unsigned long aBufferSegmentSize, - in unsigned long aBufferMaxSize); -}; - -/** - * THIS INTERFACE IS DEPRECATED - * - * An asynchronous stream listener is used to ship data over to another thread specified - * by the thread's event queue. The receiver stream listener is then used to receive - * the notifications on the other thread. - * - * This interface only provides the initialization needed after construction. Otherwise, - * these objects are used simply as nsIStreamListener. - */ -[scriptable, uuid(1b012ade-91bf-11d3-8cd9-0060b0fc14a3)] -interface nsIAsyncStreamListener : nsIStreamListener -{ - /** - * Initializes an nsIAsyncStreamListener. - * - * @param aReceiver receives listener notifications on the other thread - * @param aEventQ may be null indicating the calling thread's event queue - */ - void init(in nsIStreamListener aReceiver, - in nsIEventQueue aEventQ); -}; diff --git a/mozilla/netwerk/base/public/nsITransport.idl b/mozilla/netwerk/base/public/nsITransport.idl index c38ef247611..40f1c3267ad 100644 --- a/mozilla/netwerk/base/public/nsITransport.idl +++ b/mozilla/netwerk/base/public/nsITransport.idl @@ -57,7 +57,7 @@ interface nsIEventTarget; * socket transport, these events can include status about the connection. * See nsISocketTransport for more info about socket transport specifics. */ -[scriptable, uuid(cbb0baeb-5fcb-408b-a2be-9f8fc98d0af1)] +[scriptable, uuid(d8786c64-eb49-4a0b-b42c-0936a745fbe8)] interface nsITransport : nsISupports { /** diff --git a/mozilla/netwerk/base/public/nsNetUtil.h b/mozilla/netwerk/base/public/nsNetUtil.h index dd2456ca910..d33079dbc89 100644 --- a/mozilla/netwerk/base/public/nsNetUtil.h +++ b/mozilla/netwerk/base/public/nsNetUtil.h @@ -54,7 +54,6 @@ #include "nsISafeOutputStream.h" #include "nsIStreamListener.h" #include "nsIRequestObserverProxy.h" -#include "nsIStreamListenerProxy.h" // XXX for nsIAsyncStreamListener #include "nsISimpleStreamListener.h" #include "nsILoadGroup.h" #include "nsIInterfaceRequestor.h" @@ -535,13 +534,13 @@ NS_ImplementChannelOpen(nsIChannel *channel, inline nsresult NS_NewRequestObserverProxy(nsIRequestObserver **result, nsIRequestObserver *observer, - nsIEventQueue *eventQ = nsnull) + nsIEventTarget *target = nsnull) { nsresult rv; nsCOMPtr proxy = do_CreateInstance(NS_REQUESTOBSERVERPROXY_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { - rv = proxy->Init(observer, eventQ); + rv = proxy->Init(observer, target); if (NS_SUCCEEDED(rv)) NS_ADDREF(*result = proxy); // cannot use nsCOMPtr::swap } @@ -564,22 +563,6 @@ NS_NewSimpleStreamListener(nsIStreamListener **result, return rv; } -inline nsresult -NS_NewAsyncStreamListener(nsIStreamListener **result, - nsIStreamListener *receiver, - nsIEventQueue *eventQ) -{ - nsresult rv; - nsCOMPtr lsnr = - do_CreateInstance(NS_ASYNCSTREAMLISTENER_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = lsnr->Init(receiver, eventQ); - if (NS_SUCCEEDED(rv)) - NS_ADDREF(*result = lsnr); // cannot use nsCOMPtr::swap - } - return rv; -} - inline nsresult NS_CheckPortSafety(PRInt32 port, const char *scheme, diff --git a/mozilla/netwerk/base/src/Makefile.in b/mozilla/netwerk/base/src/Makefile.in index 3856b308dc6..b5657ff9b42 100644 --- a/mozilla/netwerk/base/src/Makefile.in +++ b/mozilla/netwerk/base/src/Makefile.in @@ -56,10 +56,8 @@ REQUIRES = xpcom \ $(NULL) CPPSRCS = \ - nsIOThreadPool.cpp \ nsTransportUtils.cpp \ nsAsyncStreamCopier.cpp \ - nsAsyncStreamListener.cpp \ nsBaseChannel.cpp \ nsBaseContentStream.cpp \ nsBufferedStreams.cpp \ diff --git a/mozilla/netwerk/base/src/nsAsyncStreamCopier.cpp b/mozilla/netwerk/base/src/nsAsyncStreamCopier.cpp index 7e060938167..5430d15187b 100644 --- a/mozilla/netwerk/base/src/nsAsyncStreamCopier.cpp +++ b/mozilla/netwerk/base/src/nsAsyncStreamCopier.cpp @@ -36,6 +36,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsAsyncStreamCopier.h" +#include "nsIEventTarget.h" #include "nsStreamUtils.h" #include "nsNetSegmentUtils.h" #include "nsNetUtil.h" @@ -245,7 +246,7 @@ nsAsyncStreamCopier::Init(nsIInputStream *source, mTarget = target; else { nsresult rv; - mTarget = do_GetService(NS_IOTHREADPOOL_CONTRACTID, &rv); + mTarget = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; } return NS_OK; diff --git a/mozilla/netwerk/base/src/nsAsyncStreamListener.cpp b/mozilla/netwerk/base/src/nsAsyncStreamListener.cpp index 4e41b922bda..e69de29bb2d 100644 --- a/mozilla/netwerk/base/src/nsAsyncStreamListener.cpp +++ b/mozilla/netwerk/base/src/nsAsyncStreamListener.cpp @@ -1,497 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsAsyncStreamListener.h" -#include "nsIInputStream.h" -#include "nsString.h" -#include "nsCRT.h" -#include "nsIEventQueueService.h" -#include "nsIIOService.h" -#include "nsIServiceManager.h" -#include "nsIChannel.h" -#include "prlog.h" - -static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID); - -#if defined(PR_LOGGING) -static PRLogModuleInfo* gStreamEventLog = 0; -#endif - -// prevent name conflicts -#define nsStreamListenerEvent nsStreamListenerEvent0 -#define nsOnStartRequestEvent nsOnStartRequestEvent0 -#define nsOnStopRequestEvent nsOnStopRequestEvent0 -#define nsOnDataAvailableEvent nsOnDataAvailableEvent0 - -//////////////////////////////////////////////////////////////////////////////// - -class nsStreamListenerEvent -{ -public: - nsStreamListenerEvent(nsAsyncStreamObserver* listener, - nsIRequest* request, nsISupports* context); - virtual ~nsStreamListenerEvent(); - - nsresult Fire(nsIEventQueue* aEventQ); - - NS_IMETHOD HandleEvent() = 0; - -protected: - static void* PR_CALLBACK HandlePLEvent(PLEvent* aEvent); - static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent); - - nsAsyncStreamObserver* mListener; - nsIRequest* mRequest; - nsISupports* mContext; - PLEvent mEvent; -}; - -#define GET_STREAM_LISTENER_EVENT(_this) \ - ((nsStreamListenerEvent*)((char*)(_this) - offsetof(nsStreamListenerEvent, mEvent))) - -//////////////////////////////////////////////////////////////////////////////// - -nsStreamListenerEvent::nsStreamListenerEvent(nsAsyncStreamObserver* listener, - nsIRequest* request, nsISupports* context) - : mListener(listener), mRequest(request), mContext(context) -{ - MOZ_COUNT_CTOR(nsStreamListenerEvent); - - NS_IF_ADDREF(mListener); - NS_IF_ADDREF(mRequest); - NS_IF_ADDREF(mContext); -} - -nsStreamListenerEvent::~nsStreamListenerEvent() -{ - MOZ_COUNT_DTOR(nsStreamListenerEvent); - - NS_IF_RELEASE(mListener); - NS_IF_RELEASE(mRequest); - NS_IF_RELEASE(mContext); -} - -void* PR_CALLBACK nsStreamListenerEvent::HandlePLEvent(PLEvent* aEvent) -{ - nsStreamListenerEvent* ev = GET_STREAM_LISTENER_EVENT(aEvent); - NS_ASSERTION(nsnull != ev,"null event."); - - nsresult rv = ev->HandleEvent(); - // - // If the consumer fails, then cancel the transport. This is necessary - // in case where the socket transport is blocked waiting for room in the - // pipe, but the consumer fails without consuming all the data. - // - // Unless the transport is cancelled, it will block forever, waiting for - // the pipe to empty... - // - if (NS_FAILED(rv)) { - nsresult cancelRv = ev->mRequest->Cancel(rv); - NS_ASSERTION(NS_SUCCEEDED(cancelRv), "Cancel failed"); - } - - return nsnull; -} - -void PR_CALLBACK nsStreamListenerEvent::DestroyPLEvent(PLEvent* aEvent) -{ - nsStreamListenerEvent* ev = GET_STREAM_LISTENER_EVENT(aEvent); - NS_ASSERTION(nsnull != ev, "null event."); - delete ev; -} - -nsresult -nsStreamListenerEvent::Fire(nsIEventQueue* aEventQueue) -{ - NS_PRECONDITION(nsnull != aEventQueue, "nsIEventQueue for thread is null"); - - PL_InitEvent(&mEvent, - nsnull, - nsStreamListenerEvent::HandlePLEvent, - nsStreamListenerEvent::DestroyPLEvent); - - return aEventQueue->PostEvent(&mEvent); -} - -//////////////////////////////////////////////////////////////////////////////// - -NS_IMPL_THREADSAFE_ISUPPORTS1(nsAsyncStreamObserver, - nsIRequestObserver) - -NS_IMPL_ADDREF_INHERITED(nsAsyncStreamListener, nsAsyncStreamObserver) -NS_IMPL_RELEASE_INHERITED(nsAsyncStreamListener, nsAsyncStreamObserver) - -NS_IMETHODIMP -nsAsyncStreamListener::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - if (!aInstancePtr) return NS_ERROR_NULL_POINTER; - if (aIID.Equals(NS_GET_IID(nsIAsyncStreamListener))) { - *aInstancePtr = NS_STATIC_CAST(nsIAsyncStreamListener*, this); - NS_ADDREF_THIS(); - return NS_OK; - } - if (aIID.Equals(NS_GET_IID(nsIStreamListener))) { - *aInstancePtr = NS_STATIC_CAST(nsIStreamListener*, this); - NS_ADDREF_THIS(); - return NS_OK; - } - return nsAsyncStreamObserver::QueryInterface(aIID, aInstancePtr); -} - -NS_IMETHODIMP -nsAsyncStreamObserver::Init(nsIRequestObserver* aObserver, nsIEventQueue* aEventQ) -{ - nsresult rv = NS_OK; - NS_ASSERTION(aObserver, "null observer"); - mReceiver = aObserver; - - nsCOMPtr eventQService = - do_GetService(kEventQueueService, &rv); - if (NS_FAILED(rv)) - return rv; - - rv = eventQService->ResolveEventQueue(aEventQ, getter_AddRefs(mEventQueue)); - return rv; -} - -//////////////////////////////////////////////////////////////////////////////// -// -// OnStartRequest... -// -//////////////////////////////////////////////////////////////////////////////// - -class nsOnStartRequestEvent : public nsStreamListenerEvent -{ -public: - nsOnStartRequestEvent(nsAsyncStreamObserver* listener, - nsIRequest* request, nsISupports* context) - : nsStreamListenerEvent(listener, request, context) {} - virtual ~nsOnStartRequestEvent() {} - - NS_IMETHOD HandleEvent(); -}; - -NS_IMETHODIMP -nsOnStartRequestEvent::HandleEvent() -{ -#if defined(PR_LOGGING) - if (!gStreamEventLog) - gStreamEventLog = PR_NewLogModule("netlibStreamEvent"); - PR_LOG(gStreamEventLog, PR_LOG_DEBUG, - ("netlibEvent: Handle Start [event=%x]", this)); -#endif - nsIRequestObserver* receiver = (nsIRequestObserver*)mListener->GetReceiver(); - if (receiver == nsnull) { - // must have already called OnStopRequest (it clears the receiver) - return NS_ERROR_FAILURE; - } - - nsresult status; - nsresult rv = mRequest->GetStatus(&status); - NS_ASSERTION(NS_SUCCEEDED(rv), "GetStatus failed"); - rv = receiver->OnStartRequest(mRequest, mContext); - - return rv; -} - -NS_IMETHODIMP -nsAsyncStreamObserver::OnStartRequest(nsIRequest *request, nsISupports* context) -{ - nsresult rv; - nsOnStartRequestEvent* event = - new nsOnStartRequestEvent(this, request, context); - if (event == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - -#if defined(PR_LOGGING) - PLEventQueue *equeue; - mEventQueue->GetPLEventQueue(&equeue); - char ts[80]; - sprintf(ts, "nsAsyncStreamObserver: Start [this=%lx queue=%lx", - (long)this, (long)equeue); - if (!gStreamEventLog) - gStreamEventLog = PR_NewLogModule("netlibStreamEvent"); - PR_LOG(gStreamEventLog, PR_LOG_DEBUG, - ("nsAsyncStreamObserver: Start [this=%x queue=%x event=%x]", - this, equeue, event)); -#endif - rv = event->Fire(mEventQueue); - if (NS_FAILED(rv)) goto failed; - return rv; - - failed: - delete event; - return rv; -} - -//////////////////////////////////////////////////////////////////////////////// -// -// OnStopRequest -// -//////////////////////////////////////////////////////////////////////////////// - -class nsOnStopRequestEvent : public nsStreamListenerEvent -{ -public: - nsOnStopRequestEvent(nsAsyncStreamObserver* listener, - nsISupports* context, nsIRequest* request) - : nsStreamListenerEvent(listener, request, context), - mStatus(NS_OK) {} - virtual ~nsOnStopRequestEvent(); - - nsresult Init(nsresult aStatus); - NS_IMETHOD HandleEvent(); - -protected: - nsresult mStatus; -}; - -nsOnStopRequestEvent::~nsOnStopRequestEvent() -{ -} - -nsresult -nsOnStopRequestEvent::Init(nsresult aStatus) -{ - mStatus = aStatus; - return NS_OK; -} - -NS_IMETHODIMP -nsOnStopRequestEvent::HandleEvent() -{ -#if defined(PR_LOGGING) - if (!gStreamEventLog) - gStreamEventLog = PR_NewLogModule("netlibStreamEvent"); - PR_LOG(gStreamEventLog, PR_LOG_DEBUG, - ("netlibEvent: Handle Stop [event=%x]", this)); -#endif - nsIRequestObserver* receiver = (nsIRequestObserver*)mListener->GetReceiver(); - if (receiver == nsnull) { - // must have already called OnStopRequest (it clears the receiver) - return NS_ERROR_FAILURE; - } - - nsresult status = NS_OK; - nsresult rv = mRequest->GetStatus(&status); - NS_ASSERTION(NS_SUCCEEDED(rv), "GetStatus failed"); - - // - // If the consumer returned a failure code, then pass it out in the - // OnStopRequest(...) notification... - // - if (NS_SUCCEEDED(rv) && NS_FAILED(status)) { - mStatus = status; - } - rv = receiver->OnStopRequest(mRequest, mContext, mStatus); - // Call clear on the listener to make sure it's cleanup is done on the correct thread - mListener->Clear(); - return rv; -} - -NS_IMETHODIMP -nsAsyncStreamObserver::OnStopRequest(nsIRequest* request, nsISupports* context, - nsresult aStatus) -{ - nsresult rv; - - // - // Fire the OnStopRequest(...) regardless of what the current - // Status is... - // - nsOnStopRequestEvent* event = - new nsOnStopRequestEvent(this, context, request); - if (event == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - - rv = event->Init(aStatus); - if (NS_FAILED(rv)) goto failed; -#if defined(PR_LOGGING) - PLEventQueue *equeue; - mEventQueue->GetPLEventQueue(&equeue); - if (!gStreamEventLog) - gStreamEventLog = PR_NewLogModule("netlibStreamEvent"); - PR_LOG(gStreamEventLog, PR_LOG_DEBUG, - ("nsAsyncStreamObserver: Stop [this=%x queue=%x event=%x]", - this, equeue, event)); -#endif - rv = event->Fire(mEventQueue); - if (NS_FAILED(rv)) goto failed; - return rv; - - failed: - delete event; - return rv; -} - -//////////////////////////////////////////////////////////////////////////////// -// -// OnDataAvailable -// -//////////////////////////////////////////////////////////////////////////////// - -class nsOnDataAvailableEvent : public nsStreamListenerEvent -{ -public: - nsOnDataAvailableEvent(nsAsyncStreamObserver* listener, - nsIRequest* request, nsISupports* context) - : nsStreamListenerEvent(listener, request, context), - mIStream(nsnull), mLength(0) {} - virtual ~nsOnDataAvailableEvent(); - - nsresult Init(nsIInputStream* aIStream, PRUint32 aSourceOffset, - PRUint32 aLength); - NS_IMETHOD HandleEvent(); - -protected: - nsIInputStream* mIStream; - PRUint32 mSourceOffset; - PRUint32 mLength; -}; - -nsOnDataAvailableEvent::~nsOnDataAvailableEvent() -{ - NS_RELEASE(mIStream); -} - -nsresult -nsOnDataAvailableEvent::Init(nsIInputStream* aIStream, PRUint32 aSourceOffset, - PRUint32 aLength) -{ - mSourceOffset = aSourceOffset; - mLength = aLength; - mIStream = aIStream; - NS_ADDREF(mIStream); - return NS_OK; -} - -NS_IMETHODIMP -nsOnDataAvailableEvent::HandleEvent() -{ -#if defined(PR_LOGGING) - if (!gStreamEventLog) - gStreamEventLog = PR_NewLogModule("netlibStreamEvent"); - PR_LOG(gStreamEventLog, PR_LOG_DEBUG, - ("netlibEvent: Handle Data [event=%x]", this)); -#endif - nsIStreamListener* receiver = (nsIStreamListener*)mListener->GetReceiver(); - if (receiver == nsnull) { - // must have already called OnStopRequest (it clears the receiver) - return NS_ERROR_FAILURE; - } - - nsresult status; - nsresult rv = mRequest->GetStatus(&status); - NS_ASSERTION(NS_SUCCEEDED(rv), "GetStatus failed"); - - // - // Only send OnDataAvailable(... ) notifications if all previous calls - // have succeeded... - // - if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) { - rv = receiver->OnDataAvailable(mRequest, mContext, - mIStream, mSourceOffset, mLength); - } - else { - NS_WARNING("not calling OnDataAvailable"); - } - return rv; -} - -NS_IMETHODIMP -nsAsyncStreamListener::OnDataAvailable(nsIRequest* request, nsISupports* context, - nsIInputStream *aIStream, - PRUint32 aSourceOffset, - PRUint32 aLength) -{ - nsresult rv; - nsOnDataAvailableEvent* event = - new nsOnDataAvailableEvent(this, request, context); - if (event == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - - rv = event->Init(aIStream, aSourceOffset, aLength); - if (NS_FAILED(rv)) goto failed; -#if defined(PR_LOGGING) - PLEventQueue *equeue; - mEventQueue->GetPLEventQueue(&equeue); - if (!gStreamEventLog) - gStreamEventLog = PR_NewLogModule("netlibStreamEvent"); - PR_LOG(gStreamEventLog, PR_LOG_DEBUG, - ("nsAsyncStreamObserver: Data [this=%x queue=%x event=%x]", - this, equeue, event)); -#endif - rv = event->Fire(mEventQueue); - if (NS_FAILED(rv)) goto failed; - return rv; - - failed: - delete event; - return rv; -} - -//////////////////////////////////////////////////////////////////////////////// - -NS_METHOD -nsAsyncStreamObserver::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) -{ - if (aOuter) - return NS_ERROR_NO_AGGREGATION; - nsAsyncStreamObserver* l = new nsAsyncStreamObserver(); - if (l == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(l); - nsresult rv = l->QueryInterface(aIID, aResult); - NS_RELEASE(l); - return rv; -} - -NS_METHOD -nsAsyncStreamListener::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) -{ - if (aOuter) - return NS_ERROR_NO_AGGREGATION; - nsAsyncStreamListener* l = new nsAsyncStreamListener(); - if (l == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(l); - nsresult rv = l->QueryInterface(aIID, aResult); - NS_RELEASE(l); - return rv; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/netwerk/base/src/nsAsyncStreamListener.h b/mozilla/netwerk/base/src/nsAsyncStreamListener.h index c5f7055fc95..e69de29bb2d 100644 --- a/mozilla/netwerk/base/src/nsAsyncStreamListener.h +++ b/mozilla/netwerk/base/src/nsAsyncStreamListener.h @@ -1,124 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsAsyncStreamListener_h__ -#define nsAsyncStreamListener_h__ - -#include "nsIStreamListenerProxy.h" -#include "nsCOMPtr.h" -#include "nsIEventQueue.h" -#include "nsIRequestObserver.h" -#include "nsIStreamListener.h" -#include "nsIRequest.h" - -//////////////////////////////////////////////////////////////////////////////// - -class nsAsyncStreamObserver : public nsIRequestObserver -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIREQUESTOBSERVER - - // nsAsyncStreamObserver methods: - nsAsyncStreamObserver() - { - } - - virtual ~nsAsyncStreamObserver() {} - - static NS_METHOD - Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); - - NS_METHOD Init(nsIRequestObserver *, nsIEventQueue *); - - nsISupports* GetReceiver() { return mReceiver.get(); } - void Clear() { mReceiver = nsnull; } - -protected: - nsCOMPtr mEventQueue; - nsCOMPtr mReceiver; -}; - -//////////////////////////////////////////////////////////////////////////////// - -class nsAsyncStreamListener : public nsAsyncStreamObserver, - public nsIAsyncStreamListener -{ -public: - NS_DECL_ISUPPORTS_INHERITED - - // nsIStreamListener methods: - NS_IMETHOD OnStartRequest(nsIRequest* request, - nsISupports* context) - { - return nsAsyncStreamObserver::OnStartRequest(request, context); - } - - NS_IMETHOD OnStopRequest(nsIRequest* request, - nsISupports* context, - nsresult aStatus) - { - return nsAsyncStreamObserver::OnStopRequest(request, context, aStatus); - } - - NS_IMETHOD OnDataAvailable(nsIRequest* request, nsISupports* context, - nsIInputStream *aIStream, - PRUint32 aSourceOffset, - PRUint32 aLength); - - // nsIAsyncStreamListener methods: - NS_IMETHOD Init(nsIStreamListener* aListener, nsIEventQueue* aEventQ) { - return nsAsyncStreamObserver::Init(aListener, aEventQ); - } - - // nsAsyncStreamListener methods: - nsAsyncStreamListener() { - MOZ_COUNT_CTOR(nsAsyncStreamListener); - } - - virtual ~nsAsyncStreamListener() { - MOZ_COUNT_DTOR(nsAsyncStreamListener); - } - - static NS_METHOD - Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); - -}; - -//////////////////////////////////////////////////////////////////////////////// - -#endif // nsAsyncStreamListener_h__ diff --git a/mozilla/netwerk/base/src/nsBaseContentStream.cpp b/mozilla/netwerk/base/src/nsBaseContentStream.cpp index 900c26bf0d5..3e6ab49e8f8 100644 --- a/mozilla/netwerk/base/src/nsBaseContentStream.cpp +++ b/mozilla/netwerk/base/src/nsBaseContentStream.cpp @@ -138,8 +138,9 @@ nsBaseContentStream::CloseWithStatus(nsresult status) } NS_IMETHODIMP -nsBaseContentStream::AsyncWait(nsIInputStreamCallback *callback, PRUint32 flags, - PRUint32 requestedCount, nsIEventTarget *target) +nsBaseContentStream::AsyncWait(nsIInputStreamCallback *callback, + PRUint32 flags, PRUint32 requestedCount, + nsIEventTarget *target) { // Our _only_ consumer is nsInputStreamPump, so we simplify things here by // making assumptions about how we will be called. diff --git a/mozilla/netwerk/base/src/nsBaseContentStream.h b/mozilla/netwerk/base/src/nsBaseContentStream.h index 1660a7e9f35..bca954ebf48 100644 --- a/mozilla/netwerk/base/src/nsBaseContentStream.h +++ b/mozilla/netwerk/base/src/nsBaseContentStream.h @@ -84,7 +84,7 @@ public: // Called to test if the stream has a pending callback. PRBool HasPendingCallback() { return mCallback != nsnull; } - // The current event target (may be null) for the pending callback if any. + // The current dispatch target (may be null) for the pending callback if any. nsIEventTarget *CallbackTarget() { return mCallbackTarget; } // Called to dispatch a pending callback. If there is no pending callback, diff --git a/mozilla/netwerk/base/src/nsIOService.cpp b/mozilla/netwerk/base/src/nsIOService.cpp index 8cba0a1b89a..5eda5925b0a 100644 --- a/mozilla/netwerk/base/src/nsIOService.cpp +++ b/mozilla/netwerk/base/src/nsIOService.cpp @@ -41,7 +41,6 @@ #include "nsIFileProtocolHandler.h" #include "nscore.h" #include "nsIServiceManager.h" -#include "nsIEventQueueService.h" #include "nsIURI.h" #include "nsIStreamListener.h" #include "prprf.h" @@ -183,13 +182,6 @@ nsIOService::Init() { nsresult rv; - // Hold onto the eventQueue service. We do not want any eventqueues to go away - // when we shutdown until we process all remaining transports - - mEventQueueService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) - NS_WARNING("failed to get event queue service"); - // We need to get references to these services so that we can shut them // down later. If we wait until the nsIOService is being shut down, // GetService will fail at that point. diff --git a/mozilla/netwerk/base/src/nsIOService.h b/mozilla/netwerk/base/src/nsIOService.h index f73c897558d..c8ccf1acf65 100644 --- a/mozilla/netwerk/base/src/nsIOService.h +++ b/mozilla/netwerk/base/src/nsIOService.h @@ -49,7 +49,6 @@ #include "nsCOMPtr.h" #include "nsURLHelper.h" #include "nsWeakPtr.h" -#include "nsIEventQueueService.h" #include "nsIURLParser.h" #include "nsSupportsArray.h" #include "nsIObserver.h" @@ -135,7 +134,6 @@ private: nsCOMPtr mSocketTransportService; nsCOMPtr mDNSService; nsCOMPtr mProxyService; - nsCOMPtr mEventQueueService; nsCOMPtr mNetworkLinkService; // Cached protocol handlers diff --git a/mozilla/netwerk/base/src/nsInputStreamPump.cpp b/mozilla/netwerk/base/src/nsInputStreamPump.cpp index 200f8d5f069..8ae697330e8 100644 --- a/mozilla/netwerk/base/src/nsInputStreamPump.cpp +++ b/mozilla/netwerk/base/src/nsInputStreamPump.cpp @@ -42,7 +42,7 @@ #include "nsISeekableStream.h" #include "nsITransport.h" #include "nsNetUtil.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsNetSegmentUtils.h" #include "nsCOMPtr.h" #include "prlog.h" @@ -142,7 +142,7 @@ nsInputStreamPump::EnsureWaiting() // on only one thread. if (!mWaiting) { - nsresult rv = mAsyncStream->AsyncWait(this, 0, 0, mEventQ); + nsresult rv = mAsyncStream->AsyncWait(this, 0, 0, mTargetThread); if (NS_FAILED(rv)) { NS_ERROR("AsyncWait failed"); return rv; @@ -346,8 +346,8 @@ nsInputStreamPump::AsyncRead(nsIStreamListener *listener, nsISupports *ctxt) // grab event queue (we must do this here by contract, since all notifications // must go to the thread which called AsyncRead) - rv = NS_GetCurrentEventQ(getter_AddRefs(mEventQ)); - if (NS_FAILED(rv)) return rv; + mTargetThread = do_GetCurrentThread(); + NS_ENSURE_STATE(mTargetThread); rv = EnsureWaiting(); if (NS_FAILED(rv)) return rv; @@ -560,7 +560,7 @@ nsInputStreamPump::OnStateStop() mAsyncStream->Close(); mAsyncStream = 0; - mEventQ = 0; + mTargetThread = 0; mIsPending = PR_FALSE; mListener->OnStopRequest(this, mListenerContext, mStatus); diff --git a/mozilla/netwerk/base/src/nsInputStreamPump.h b/mozilla/netwerk/base/src/nsInputStreamPump.h index 4cce57730dc..28a9f04b96a 100644 --- a/mozilla/netwerk/base/src/nsInputStreamPump.h +++ b/mozilla/netwerk/base/src/nsInputStreamPump.h @@ -46,7 +46,7 @@ #include "nsIInterfaceRequestor.h" #include "nsIProgressEventSink.h" #include "nsIAsyncInputStream.h" -#include "nsIEventQueue.h" +#include "nsIThread.h" #include "nsCOMPtr.h" class nsInputStreamPump : public nsIInputStreamPump @@ -102,7 +102,7 @@ protected: nsCOMPtr mLoadGroup; nsCOMPtr mListener; nsCOMPtr mListenerContext; - nsCOMPtr mEventQ; + nsCOMPtr mTargetThread; nsCOMPtr mStream; nsCOMPtr mAsyncStream; PRUint64 mStreamOffset; diff --git a/mozilla/netwerk/base/src/nsLoadGroup.cpp b/mozilla/netwerk/base/src/nsLoadGroup.cpp index 9425799e6ea..49c17601df4 100644 --- a/mozilla/netwerk/base/src/nsLoadGroup.cpp +++ b/mozilla/netwerk/base/src/nsLoadGroup.cpp @@ -41,7 +41,6 @@ #include "nsISupportsArray.h" #include "nsEnumeratorUtils.h" #include "nsIServiceManager.h" -#include "nsIEventQueueService.h" #include "nsCOMPtr.h" #include "nsIURI.h" #include "prlog.h" diff --git a/mozilla/netwerk/base/src/nsPACMan.cpp b/mozilla/netwerk/base/src/nsPACMan.cpp index 1ebdc2f7d8d..f5b7227db18 100644 --- a/mozilla/netwerk/base/src/nsPACMan.cpp +++ b/mozilla/netwerk/base/src/nsPACMan.cpp @@ -37,10 +37,10 @@ * ***** END LICENSE BLOCK ***** */ #include "nsPACMan.h" +#include "nsThreadUtils.h" #include "nsIDNSService.h" #include "nsIDNSListener.h" #include "nsICancelable.h" -#include "nsEventQueueUtils.h" #include "nsNetUtil.h" #include "nsAutoLock.h" #include "nsAutoPtr.h" @@ -97,12 +97,8 @@ PendingPACQuery::Start() if (NS_FAILED(rv)) return rv; - nsCOMPtr eventQ; - rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - if (NS_FAILED(rv)) - return rv; - - rv = dns->AsyncResolve(host, 0, this, eventQ, getter_AddRefs(mDNSRequest)); + rv = dns->AsyncResolve(host, 0, this, NS_GetCurrentThread(), + getter_AddRefs(mDNSRequest)); if (NS_FAILED(rv)) NS_WARNING("DNS AsyncResolve failed"); @@ -152,7 +148,7 @@ PendingPACQuery::OnLookupComplete(nsICancelable *request, //----------------------------------------------------------------------------- nsPACMan::nsPACMan() - : mLoadEvent(nsnull) + : mLoadPending(PR_FALSE) , mShutdown(PR_FALSE) { PR_INIT_CLIST(&mPendingQ); @@ -226,22 +222,6 @@ nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback) return rv; } -void *PR_CALLBACK -nsPACMan::LoadEvent_Handle(PLEvent *ev) -{ - NS_REINTERPRET_CAST(nsPACMan *, PL_GetEventOwner(ev))->StartLoading(); - return nsnull; -} - -void PR_CALLBACK -nsPACMan::LoadEvent_Destroy(PLEvent *ev) -{ - nsPACMan *self = NS_REINTERPRET_CAST(nsPACMan *, PL_GetEventOwner(ev)); - self->mLoadEvent = nsnull; - self->Release(); - delete ev; -} - nsresult nsPACMan::LoadPACFromURI(nsIURI *pacURI) { @@ -257,20 +237,13 @@ nsPACMan::LoadPACFromURI(nsIURI *pacURI) // But, we need to flag ourselves as loading, so that we queue up any PAC // queries the enter between now and when we actually load the PAC file. - if (!mLoadEvent) { - mLoadEvent = new PLEvent; - if (!mLoadEvent) - return NS_ERROR_OUT_OF_MEMORY; - - NS_ADDREF_THIS(); - PL_InitEvent(mLoadEvent, this, LoadEvent_Handle, LoadEvent_Destroy); - - nsCOMPtr eventQ; - nsresult rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - if (NS_FAILED(rv) || NS_FAILED(rv = eventQ->PostEvent(mLoadEvent))) { - PL_DestroyEvent(mLoadEvent); + if (!mLoadPending) { + nsCOMPtr event = + NS_NewRunnableMethod(this, &nsPACMan::StartLoading); + nsresult rv; + if (NS_FAILED(rv = NS_DispatchToCurrentThread(event))) return rv; - } + mLoadPending = PR_TRUE; } CancelExistingLoad(); @@ -281,13 +254,15 @@ nsPACMan::LoadPACFromURI(nsIURI *pacURI) return NS_OK; } -nsresult +void nsPACMan::StartLoading() { + mLoadPending = PR_FALSE; + // CancelExistingLoad was called... if (!mLoader) { ProcessPendingQ(NS_ERROR_ABORT); - return NS_OK; + return; } // Always hit the origin server when loading PAC. @@ -302,13 +277,12 @@ nsPACMan::StartLoading() channel->SetLoadFlags(nsIRequest::LOAD_BYPASS_CACHE); channel->SetNotificationCallbacks(this); if (NS_SUCCEEDED(mLoader->Init(channel, this, nsnull))) - return NS_OK; + return; } } CancelExistingLoad(); ProcessPendingQ(NS_ERROR_UNEXPECTED); - return NS_OK; } void diff --git a/mozilla/netwerk/base/src/nsPACMan.h b/mozilla/netwerk/base/src/nsPACMan.h index 00dfcc6c4b2..0df01211a0c 100644 --- a/mozilla/netwerk/base/src/nsPACMan.h +++ b/mozilla/netwerk/base/src/nsPACMan.h @@ -47,7 +47,6 @@ #include "nsCOMPtr.h" #include "nsString.h" #include "prclist.h" -#include "plevent.h" /** * This class defines a callback interface used by AsyncGetProxyForURI. @@ -150,7 +149,7 @@ private: /** * Start loading the PAC file. */ - nsresult StartLoading(); + void StartLoading(); /** * Returns true if the given URI matches the URI of our PAC file. @@ -160,19 +159,13 @@ private: return mPACURI && NS_SUCCEEDED(mPACURI->Equals(uri, &result)) && result; } - /** - * Event fu for calling StartLoading asynchronously. - */ - PR_STATIC_CALLBACK(void *) LoadEvent_Handle(PLEvent *); - PR_STATIC_CALLBACK(void) LoadEvent_Destroy(PLEvent *); - private: nsCOMPtr mPAC; nsCOMPtr mPACURI; PRCList mPendingQ; nsCOMPtr mLoader; - PLEvent *mLoadEvent; - PRBool mShutdown; + PRPackedBool mLoadPending; + PRPackedBool mShutdown; }; #endif // nsPACMan_h__ diff --git a/mozilla/netwerk/base/src/nsProtocolProxyService.cpp b/mozilla/netwerk/base/src/nsProtocolProxyService.cpp index ae9e5b14561..ba977dfcf33 100644 --- a/mozilla/netwerk/base/src/nsProtocolProxyService.cpp +++ b/mozilla/netwerk/base/src/nsProtocolProxyService.cpp @@ -44,7 +44,6 @@ #include "nsXPIDLString.h" #include "nsIProxyAutoConfig.h" #include "nsAutoLock.h" -#include "nsEventQueueUtils.h" #include "nsIIOService.h" #include "nsIObserverService.h" #include "nsIProtocolHandler.h" @@ -54,11 +53,11 @@ #include "nsIPrefService.h" #include "nsIPrefBranch2.h" #include "nsReadableUtils.h" +#include "nsThreadUtils.h" #include "nsString.h" #include "nsNetUtil.h" #include "nsCRT.h" #include "prnetdb.h" -#include "nsEventQueueUtils.h" #include "nsPACMan.h" //---------------------------------------------------------------------------- @@ -87,7 +86,7 @@ struct nsProtocolInfo { //---------------------------------------------------------------------------- -class nsAsyncResolveRequest : public PLEvent +class nsAsyncResolveRequest : public nsIRunnable , public nsPACManCallback , public nsICancelable { @@ -103,7 +102,6 @@ public: , mCallback(callback) { NS_ASSERTION(mCallback, "null callback"); - PL_InitEvent(this, nsnull, HandleEvent, CleanupEvent); } void SetResult(nsresult status, nsIProxyInfo *pi) @@ -112,6 +110,13 @@ public: mProxyInfo = pi; } + NS_IMETHOD Run() + { + if (mCallback) + DoCallback(); + return NS_OK; + } + NS_IMETHOD Cancel(nsresult reason) { NS_ENSURE_ARG(NS_FAILED(reason)); @@ -129,21 +134,12 @@ public: if (mDispatched) // Only need to dispatch once return NS_OK; - nsCOMPtr eventQ; - nsresult rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ)); + nsresult rv = NS_DispatchToCurrentThread(this); if (NS_FAILED(rv)) - NS_WARNING("could not get current event queue"); + NS_WARNING("unable to dispatch callback event"); else { - NS_ADDREF_THIS(); - rv = eventQ->PostEvent(this); - if (NS_FAILED(rv)) { - NS_WARNING("unable to dispatch callback event"); - PL_DestroyEvent(this); - } - else { - mDispatched = PR_TRUE; - return NS_OK; - } + mDispatched = PR_TRUE; + return NS_OK; } mCallback = nsnull; // break possible reference cycle @@ -192,22 +188,6 @@ private: mCallback = nsnull; // in case the callback holds an owning ref to us } - PR_STATIC_CALLBACK(void *) HandleEvent(PLEvent *ev) - { - nsAsyncResolveRequest *self = - NS_STATIC_CAST(nsAsyncResolveRequest *, ev); - if (self->mCallback) - self->DoCallback(); - return nsnull; - } - - PR_STATIC_CALLBACK(void) CleanupEvent(PLEvent *ev) - { - nsAsyncResolveRequest *self = - NS_STATIC_CAST(nsAsyncResolveRequest *, ev); - NS_RELEASE(self); // balance AddRef in DispatchCallback - } - private: nsresult mStatus; diff --git a/mozilla/netwerk/base/src/nsProtocolProxyService.h b/mozilla/netwerk/base/src/nsProtocolProxyService.h index 0a49c57cc75..25de13a4f28 100644 --- a/mozilla/netwerk/base/src/nsProtocolProxyService.h +++ b/mozilla/netwerk/base/src/nsProtocolProxyService.h @@ -39,7 +39,6 @@ #ifndef nsProtocolProxyService_h__ #define nsProtocolProxyService_h__ -#include "plevent.h" #include "nsString.h" #include "nsCOMPtr.h" #include "nsAutoPtr.h" @@ -291,8 +290,6 @@ protected: NS_HIDDEN_(PRBool) CanUseProxy(nsIURI *uri, PRInt32 defaultPort); static PRBool PR_CALLBACK CleanupFilterArray(void *aElement, void *aData); - static void* PR_CALLBACK HandlePACLoadEvent(PLEvent* aEvent); - static void PR_CALLBACK DestroyPACLoadEvent(PLEvent* aEvent); public: // The Sun Forte compiler and others implement older versions of the diff --git a/mozilla/netwerk/base/src/nsRequestObserverProxy.cpp b/mozilla/netwerk/base/src/nsRequestObserverProxy.cpp index 47dfe325a00..2fd6536cf39 100644 --- a/mozilla/netwerk/base/src/nsRequestObserverProxy.cpp +++ b/mozilla/netwerk/base/src/nsRequestObserverProxy.cpp @@ -39,8 +39,9 @@ #include "nscore.h" #include "nsRequestObserverProxy.h" #include "nsIRequest.h" -#include "nsIEventQueueService.h" #include "nsIServiceManager.h" +#include "nsProxyRelease.h" +#include "nsAutoPtr.h" #include "nsString.h" #include "prlog.h" @@ -50,44 +51,6 @@ static PRLogModuleInfo *gRequestObserverProxyLog; #define LOG(args) PR_LOG(gRequestObserverProxyLog, PR_LOG_DEBUG, args) -static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID); - -//----------------------------------------------------------------------------- -// ProxyRelease -//----------------------------------------------------------------------------- - -static void *PR_CALLBACK -ProxyRelease_EventHandlerFunc(PLEvent *ev) -{ - nsIRequestObserver *obs = - NS_STATIC_CAST(nsIRequestObserver *, PL_GetEventOwner(ev)); - NS_RELEASE(obs); - return nsnull; -} - -static void PR_CALLBACK -ProxyRelease_EventCleanupFunc(PLEvent *ev) -{ - delete ev; -} - -static void -ProxyRelease(nsIEventQueue *eventQ, nsIRequestObserver *obs) -{ - PLEvent *ev = new PLEvent; - if (!ev) { - NS_ERROR("failed to allocate PLEvent"); - return; - } - - PL_InitEvent(ev, (void *) obs, - ProxyRelease_EventHandlerFunc, - ProxyRelease_EventCleanupFunc); - - nsresult rv = eventQ->PostEvent(ev); - NS_ASSERTION(NS_SUCCEEDED(rv), "PostEvent failed"); -} - //----------------------------------------------------------------------------- // nsARequestObserverEvent internal class... //----------------------------------------------------------------------------- @@ -98,31 +61,6 @@ nsARequestObserverEvent::nsARequestObserverEvent(nsIRequest *request, , mContext(context) { NS_PRECONDITION(mRequest, "null pointer"); - - PL_InitEvent(&mEvent, nsnull, - nsARequestObserverEvent::HandlePLEvent, - nsARequestObserverEvent::DestroyPLEvent); -} - -void* PR_CALLBACK -nsARequestObserverEvent::HandlePLEvent(PLEvent *plev) -{ - nsARequestObserverEvent *ev = FromPLEvent(plev); - NS_ASSERTION(ev, "null event"); - - // Pass control to the real event handler - if (ev) - ev->HandleEvent(); - - return nsnull; -} - -void PR_CALLBACK -nsARequestObserverEvent::DestroyPLEvent(PLEvent *plev) -{ - nsARequestObserverEvent *ev = FromPLEvent(plev); - NS_ASSERTION(ev, "null event"); - delete ev; } //----------------------------------------------------------------------------- @@ -131,7 +69,7 @@ nsARequestObserverEvent::DestroyPLEvent(PLEvent *plev) class nsOnStartRequestEvent : public nsARequestObserverEvent { - nsRequestObserverProxy *mProxy; + nsRefPtr mProxy; public: nsOnStartRequestEvent(nsRequestObserverProxy *proxy, nsIRequest *request, @@ -140,23 +78,17 @@ public: , mProxy(proxy) { NS_PRECONDITION(mProxy, "null pointer"); - MOZ_COUNT_CTOR(nsOnStartRequestEvent); - NS_ADDREF(mProxy); } - ~nsOnStartRequestEvent() - { - MOZ_COUNT_DTOR(nsOnStartRequestEvent); - NS_RELEASE(mProxy); - } + virtual ~nsOnStartRequestEvent() {} - void HandleEvent() + NS_IMETHOD Run() { LOG(("nsOnStartRequestEvent::HandleEvent [req=%x]\n", mRequest.get())); if (!mProxy->mObserver) { NS_NOTREACHED("already handled onStopRequest event (observer is null)"); - return; + return NS_OK; } LOG(("handle startevent=%8lX\n",(long)this)); @@ -166,6 +98,8 @@ public: rv = mRequest->Cancel(rv); NS_ASSERTION(NS_SUCCEEDED(rv), "Cancel failed for request!"); } + + return NS_OK; } }; @@ -175,7 +109,7 @@ public: class nsOnStopRequestEvent : public nsARequestObserverEvent { - nsRequestObserverProxy *mProxy; + nsRefPtr mProxy; public: nsOnStopRequestEvent(nsRequestObserverProxy *proxy, nsIRequest *request, nsISupports *context) @@ -183,17 +117,11 @@ public: , mProxy(proxy) { NS_PRECONDITION(mProxy, "null pointer"); - MOZ_COUNT_CTOR(nsOnStopRequestEvent); - NS_ADDREF(mProxy); } - ~nsOnStopRequestEvent() - { - MOZ_COUNT_DTOR(nsOnStopRequestEvent); - NS_RELEASE(mProxy); - } + virtual ~nsOnStopRequestEvent() {} - void HandleEvent() + NS_IMETHOD Run() { nsresult rv, status = NS_OK; @@ -202,7 +130,7 @@ public: nsCOMPtr observer = mProxy->mObserver; if (!observer) { NS_NOTREACHED("already handled onStopRequest event (observer is null)"); - return; + return NS_OK; } // Do not allow any more events to be handled after OnStopRequest mProxy->mObserver = 0; @@ -212,6 +140,8 @@ public: LOG(("handle stopevent=%8lX\n",(long)this)); (void) observer->OnStopRequest(mRequest, mContext, status); + + return NS_OK; } }; @@ -225,10 +155,9 @@ nsRequestObserverProxy::~nsRequestObserverProxy() // order is crucial here... we must be careful to clear mObserver // before posting the proxy release event. otherwise, we'd risk // releasing the object on this thread. - nsIRequestObserver *obs = mObserver; - NS_ADDREF(obs); - mObserver = 0; - ProxyRelease(mEventQ, obs); + nsIRequestObserver *obs = nsnull; + mObserver.swap(obs); + NS_ProxyRelease(mTarget, obs); } } @@ -255,7 +184,7 @@ nsRequestObserverProxy::OnStartRequest(nsIRequest *request, if (!ev) return NS_ERROR_OUT_OF_MEMORY; - LOG(("post startevent=%8lX queue=%8lX\n",(long)ev,(long)mEventQ.get())); + LOG(("post startevent=%p queue=%p\n", ev, mTarget.get())); nsresult rv = FireEvent(ev); if (NS_FAILED(rv)) delete ev; @@ -280,7 +209,7 @@ nsRequestObserverProxy::OnStopRequest(nsIRequest *request, if (!ev) return NS_ERROR_OUT_OF_MEMORY; - LOG(("post stopevent=%8lX queue=%8lX\n",(long)ev,(long)mEventQ.get())); + LOG(("post stopevent=%p queue=%p\n", ev, mTarget.get())); nsresult rv = FireEvent(ev); if (NS_FAILED(rv)) delete ev; @@ -293,7 +222,7 @@ nsRequestObserverProxy::OnStopRequest(nsIRequest *request, NS_IMETHODIMP nsRequestObserverProxy::Init(nsIRequestObserver *observer, - nsIEventQueue *eventQ) + nsIEventTarget *target) { NS_ENSURE_ARG_POINTER(observer); @@ -304,7 +233,10 @@ nsRequestObserverProxy::Init(nsIRequestObserver *observer, mObserver = observer; - return SetEventQueue(eventQ); + SetTarget(target ? target : NS_GetCurrentThread()); + NS_ENSURE_STATE(mTarget); + + return NS_OK; } //----------------------------------------------------------------------------- @@ -314,21 +246,6 @@ nsRequestObserverProxy::Init(nsIRequestObserver *observer, nsresult nsRequestObserverProxy::FireEvent(nsARequestObserverEvent *event) { - NS_ENSURE_TRUE(mEventQ, NS_ERROR_NOT_INITIALIZED); - - return mEventQ->PostEvent(event->GetPLEvent()); -} - -nsresult -nsRequestObserverProxy::SetEventQueue(nsIEventQueue *eq) -{ - nsresult rv = NS_OK; - if ((eq == NS_CURRENT_EVENTQ) || (eq == NS_UI_THREAD_EVENTQ)) { - nsCOMPtr serv = do_GetService(kEventQueueService, &rv); - if (NS_FAILED(rv)) return rv; - rv = serv->GetSpecialEventQueue(NS_PTR_TO_INT32(eq), getter_AddRefs(mEventQ)); - } - else - mEventQ = eq; - return rv; + NS_ENSURE_TRUE(mTarget, NS_ERROR_NOT_INITIALIZED); + return mTarget->Dispatch(event, NS_DISPATCH_NORMAL); } diff --git a/mozilla/netwerk/base/src/nsRequestObserverProxy.h b/mozilla/netwerk/base/src/nsRequestObserverProxy.h index 294c54df1de..83a2f054f18 100644 --- a/mozilla/netwerk/base/src/nsRequestObserverProxy.h +++ b/mozilla/netwerk/base/src/nsRequestObserverProxy.h @@ -41,8 +41,8 @@ #include "nsIRequestObserver.h" #include "nsIRequestObserverProxy.h" -#include "nsIEventQueue.h" #include "nsIRequest.h" +#include "nsThreadUtils.h" #include "nsCOMPtr.h" class nsARequestObserverEvent; @@ -54,44 +54,31 @@ public: NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSIREQUESTOBSERVERPROXY - nsRequestObserverProxy() { } - virtual ~nsRequestObserverProxy(); + nsRequestObserverProxy() {} nsIRequestObserver *Observer() { return mObserver; } nsresult FireEvent(nsARequestObserverEvent *); - nsIEventQueue *EventQueue() { return mEventQ.get(); } // debugging aid - nsresult SetEventQueue(nsIEventQueue *); + nsIEventTarget *Target() { return mTarget; } // debugging aid + void SetTarget(nsIEventTarget *target) { mTarget = target; } protected: + virtual ~nsRequestObserverProxy(); + nsCOMPtr mObserver; - nsCOMPtr mEventQ; + nsCOMPtr mTarget; friend class nsOnStartRequestEvent; friend class nsOnStopRequestEvent; }; -class nsARequestObserverEvent +class nsARequestObserverEvent : public nsRunnable { public: nsARequestObserverEvent(nsIRequest *, nsISupports *); - virtual ~nsARequestObserverEvent() {} - - static nsARequestObserverEvent *FromPLEvent(PLEvent *p) - { return (nsARequestObserverEvent *) - ( (char *) p - offsetof(nsARequestObserverEvent, mEvent) ); } - PLEvent *GetPLEvent() { return &mEvent; } - - /** - * Implement this method to add code to handle the event - */ - virtual void HandleEvent() = 0; protected: - static void* PR_CALLBACK HandlePLEvent(PLEvent *); - static void PR_CALLBACK DestroyPLEvent(PLEvent *); - - PLEvent mEvent; // this _must_ be the first data member + virtual ~nsARequestObserverEvent() {} nsCOMPtr mRequest; nsCOMPtr mContext; diff --git a/mozilla/netwerk/base/src/nsServerSocket.cpp b/mozilla/netwerk/base/src/nsServerSocket.cpp index c56cd721a8d..a29bc7f827d 100644 --- a/mozilla/netwerk/base/src/nsServerSocket.cpp +++ b/mozilla/netwerk/base/src/nsServerSocket.cpp @@ -52,47 +52,32 @@ static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID); typedef void (nsServerSocket:: *nsServerSocketFunc)(void); -struct nsServerSocketEvent : PLEvent +class nsServerSocketEvent : public nsRunnable { +public: nsServerSocketEvent(nsServerSocket *s, nsServerSocketFunc f) - : func(f) - { - NS_ADDREF(s); - PL_InitEvent(this, s, EventHandler, EventCleanup); - } + : mServerSocket(s) + , mFunc(f) + {} - PR_STATIC_CALLBACK(void *) - EventHandler(PLEvent *ev) + NS_IMETHOD Run() { - nsServerSocket *s = (nsServerSocket *) ev->owner; - nsServerSocketEvent *event = (nsServerSocketEvent *) ev; - nsServerSocketFunc func = event->func; - (s->*func)(); + (mServerSocket->*mFunc)(); return nsnull; } - PR_STATIC_CALLBACK(void) - EventCleanup(PLEvent *ev) - { - nsServerSocket *s = (nsServerSocket *) ev->owner; - NS_RELEASE(s); - delete (nsServerSocketEvent *) ev; - } - - nsServerSocketFunc func; + nsRefPtr mServerSocket; + nsServerSocketFunc mFunc; }; static nsresult PostEvent(nsServerSocket *s, nsServerSocketFunc func) { - nsServerSocketEvent *ev = new nsServerSocketEvent(s, func); + nsRefPtr ev = new nsServerSocketEvent(s, func); if (!ev) return NS_ERROR_OUT_OF_MEMORY; - nsresult rv = gSocketTransportService->PostEvent(ev); - if (NS_FAILED(rv)) - PL_DestroyEvent(ev); - return rv; + return gSocketTransportService->Dispatch(ev, NS_DISPATCH_NORMAL); } //----------------------------------------------------------------------------- @@ -182,16 +167,14 @@ nsServerSocket::TryAttach() // if (!gSocketTransportService->CanAttachSocket()) { - PLEvent *event = new nsServerSocketEvent(this, &nsServerSocket::OnMsgAttach); + nsCOMPtr event = + new nsServerSocketEvent(this, &nsServerSocket::OnMsgAttach); if (!event) return NS_ERROR_OUT_OF_MEMORY; nsresult rv = gSocketTransportService->NotifyWhenCanAttachSocket(event); if (NS_FAILED(rv)) - { - PL_DestroyEvent(event); return rv; - } } // @@ -400,10 +383,10 @@ nsServerSocket::AsyncListen(nsIServerSocketListener *aListener) NS_ENSURE_TRUE(mListener == nsnull, NS_ERROR_IN_PROGRESS); { nsAutoLock lock(mLock); - nsresult rv = NS_GetProxyForObject(NS_CURRENT_EVENTQ, + nsresult rv = NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, NS_GET_IID(nsIServerSocketListener), aListener, - PROXY_ASYNC | PROXY_ALWAYS, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, getter_AddRefs(mListener)); if (NS_FAILED(rv)) return rv; diff --git a/mozilla/netwerk/base/src/nsSocketTransport2.cpp b/mozilla/netwerk/base/src/nsSocketTransport2.cpp index 2216e1412f1..5143ed3614b 100644 --- a/mozilla/netwerk/base/src/nsSocketTransport2.cpp +++ b/mozilla/netwerk/base/src/nsSocketTransport2.cpp @@ -50,6 +50,7 @@ #include "nsProxyInfo.h" #include "nsNetCID.h" #include "nsAutoLock.h" +#include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "netCore.h" #include "nsInt64.h" @@ -78,37 +79,26 @@ static NS_DEFINE_CID(kDNSServiceCID, NS_DNSSERVICE_CID); //----------------------------------------------------------------------------- -class nsSocketEvent : public PLEvent +class nsSocketEvent : public nsRunnable { public: nsSocketEvent(nsSocketTransport *transport, PRUint32 type, nsresult status = NS_OK, nsISupports *param = nsnull) - : mType(type) + : mTransport(transport) + , mType(type) , mStatus(status) , mParam(param) - { - NS_ADDREF(transport); - PL_InitEvent(this, transport, HandleEvent, DestroyEvent); - } + {} - PR_STATIC_CALLBACK(void*) - HandleEvent(PLEvent *event) + NS_IMETHOD Run() { - nsSocketTransport *trans = (nsSocketTransport *) event->owner; - nsSocketEvent *se = (nsSocketEvent *) event; - trans->OnSocketEvent(se->mType, se->mStatus, se->mParam); - return nsnull; - } - - PR_STATIC_CALLBACK(void) - DestroyEvent(PLEvent *event) - { - nsSocketTransport *trans = (nsSocketTransport *) event->owner; - NS_RELEASE(trans); - delete (nsSocketEvent *) event; + mTransport->OnSocketEvent(mType, mStatus, mParam); + return NS_OK; } private: + nsRefPtr mTransport; + PRUint32 mType; nsresult mStatus; nsCOMPtr mParam; @@ -854,15 +844,11 @@ nsSocketTransport::PostEvent(PRUint32 type, nsresult status, nsISupports *param) LOG(("nsSocketTransport::PostEvent [this=%p type=%u status=%x param=%p]\n", this, type, status, param)); - PLEvent *event = new nsSocketEvent(this, type, status, param); + nsCOMPtr event = new nsSocketEvent(this, type, status, param); if (!event) return NS_ERROR_OUT_OF_MEMORY; - nsresult rv = gSocketTransportService->PostEvent(event); - if (NS_FAILED(rv)) - PL_DestroyEvent(event); - - return rv; + return gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL); } void @@ -1061,13 +1047,11 @@ nsSocketTransport::InitiateSocket() // 194402 for more info. // if (!gSocketTransportService->CanAttachSocket()) { - PLEvent *event = new nsSocketEvent(this, MSG_RETRY_INIT_SOCKET); + nsCOMPtr event = + new nsSocketEvent(this, MSG_RETRY_INIT_SOCKET); if (!event) return NS_ERROR_OUT_OF_MEMORY; - rv = gSocketTransportService->NotifyWhenCanAttachSocket(event); - if (NS_FAILED(rv)) - PL_DestroyEvent(event); - return rv; + return gSocketTransportService->NotifyWhenCanAttachSocket(event); } // diff --git a/mozilla/netwerk/base/src/nsSocketTransportService2.cpp b/mozilla/netwerk/base/src/nsSocketTransportService2.cpp index e3a15b6d5e5..2f14c513e28 100644 --- a/mozilla/netwerk/base/src/nsSocketTransportService2.cpp +++ b/mozilla/netwerk/base/src/nsSocketTransportService2.cpp @@ -57,31 +57,16 @@ PRLogModuleInfo *gSocketTransportLog = nsnull; nsSocketTransportService *gSocketTransportService = nsnull; PRThread *gSocketThread = nsnull; -#define PLEVENT_FROM_LINK(_link) \ - ((PLEvent*) ((char*) (_link) - offsetof(PLEvent, link))) - -static inline void -MoveCList(PRCList &from, PRCList &to) -{ - if (!PR_CLIST_IS_EMPTY(&from)) { - to.next = from.next; - to.prev = from.prev; - to.next->prev = &to; - to.prev->next = &to; - PR_INIT_CLIST(&from); - } -} - //----------------------------------------------------------------------------- // ctor/dtor (called on the main/UI thread by the service manager) nsSocketTransportService::nsSocketTransportService() - : mInitialized(PR_FALSE) - , mThread(nsnull) + : mThread(nsnull) , mThreadEvent(nsnull) , mAutodialEnabled(PR_FALSE) + , mLock(PR_NewLock()) + , mInitialized(PR_FALSE) , mShuttingDown(PR_FALSE) - , mEventQLock(PR_NewLock()) , mActiveCount(0) , mIdleCount(0) { @@ -89,10 +74,7 @@ nsSocketTransportService::nsSocketTransportService() gSocketTransportLog = PR_NewLogModule("nsSocketTransport"); #endif - NS_ASSERTION(nsIThread::IsMainThread(), "wrong thread"); - - PR_INIT_CLIST(&mEventQ); - PR_INIT_CLIST(&mPendingSocketQ); + NS_ASSERTION(NS_IsMainThread(), "wrong thread"); NS_ASSERTION(!gSocketTransportService, "must not instantiate twice"); gSocketTransportService = this; @@ -100,10 +82,11 @@ nsSocketTransportService::nsSocketTransportService() nsSocketTransportService::~nsSocketTransportService() { - NS_ASSERTION(nsIThread::IsMainThread(), "wrong thread"); + NS_ASSERTION(NS_IsMainThread(), "wrong thread"); NS_ASSERTION(!mInitialized, "not shutdown properly"); - PR_DestroyLock(mEventQLock); + if (mLock) + PR_DestroyLock(mLock); if (mThreadEvent) PR_DestroyPollableEvent(mThreadEvent); @@ -115,43 +98,26 @@ nsSocketTransportService::~nsSocketTransportService() // event queue (any thread) NS_IMETHODIMP -nsSocketTransportService::PostEvent(PLEvent *event) +nsSocketTransportService::Dispatch(nsIRunnable *event, PRUint32 flags) { - LOG(("nsSocketTransportService::PostEvent [event=%p]\n", event)); + LOG(("STS dispatch [%p]\n", event)); - NS_ASSERTION(event, "null event"); - - nsAutoLock lock(mEventQLock); - if (!mInitialized) { - // Allow socket detach handlers to post events - if (!mShuttingDown || (PR_GetCurrentThread() != gSocketThread)) { - NS_WARN_IF_FALSE(PR_GetCurrentThread() != gSocketThread, - "Rejecting event posted to uninitialized sts"); - return NS_ERROR_OFFLINE; - } - - } - - PR_APPEND_LINK(&event->link, &mEventQ); - - if (mThreadEvent) - PR_SetPollableEvent(mThreadEvent); - // else wait for Poll timeout - return NS_OK; + NS_ENSURE_TRUE(mThread, NS_ERROR_NOT_INITIALIZED); + return mThread->Dispatch(event, flags); } NS_IMETHODIMP nsSocketTransportService::IsOnCurrentThread(PRBool *result) { - *result = (PR_GetCurrentThread() == gSocketThread); - return NS_OK; + NS_ENSURE_TRUE(mThread, NS_ERROR_NOT_INITIALIZED); + return mThread->IsOnCurrentThread(result); } //----------------------------------------------------------------------------- // socket api (socket thread only) nsresult -nsSocketTransportService::NotifyWhenCanAttachSocket(PLEvent *event) +nsSocketTransportService::NotifyWhenCanAttachSocket(nsIRunnable *event) { LOG(("nsSocketTransportService::NotifyWhenCanAttachSocket\n")); @@ -159,10 +125,10 @@ nsSocketTransportService::NotifyWhenCanAttachSocket(PLEvent *event) if (CanAttachSocket()) { NS_WARNING("should have called CanAttachSocket"); - return PostEvent(event); + return Dispatch(event, NS_DISPATCH_NORMAL); } - PR_APPEND_LINK(&event->link, &mPendingSocketQ); + mPendingSocketQ.PutEvent(event); return NS_OK; } @@ -208,11 +174,10 @@ nsSocketTransportService::DetachSocket(SocketContext *sock) // // notify the first element on the pending socket queue... // - if (!PR_CLIST_IS_EMPTY(&mPendingSocketQ)) { - // move event from pending queue to event queue - PLEvent *event = PLEVENT_FROM_LINK(PR_LIST_HEAD(&mPendingSocketQ)); - PR_REMOVE_AND_INIT_LINK(&event->link); - PostEvent(event); + nsCOMPtr event; + if (mPendingSocketQ.GetPendingEvent(getter_AddRefs(event))) { + // move event from pending queue to dispatch queue + return Dispatch(event, NS_DISPATCH_NORMAL); } return NS_OK; } @@ -332,7 +297,7 @@ nsSocketTransportService::PollTimeout() } PRInt32 -nsSocketTransportService::Poll(PRUint32 *interval) +nsSocketTransportService::Poll(PRBool wait, PRUint32 *interval) { PRPollDesc *pollList; PRUint32 pollCount; @@ -354,6 +319,9 @@ nsSocketTransportService::Poll(PRUint32 *interval) pollTimeout = PR_MillisecondsToInterval(25); } + if (!wait) + pollTimeout = PR_INTERVAL_NO_WAIT; + PRIntervalTime ts = PR_IntervalNow(); PRInt32 rv = PR_Poll(pollList, pollCount, pollTimeout); @@ -362,40 +330,13 @@ nsSocketTransportService::Poll(PRUint32 *interval) return rv; } -PRBool -nsSocketTransportService::ServiceEventQ() -{ - PRBool keepGoing; - - // grab the event queue - PRCList eq; - PR_INIT_CLIST(&eq); - { - nsAutoLock lock(mEventQLock); - - MoveCList(mEventQ, eq); - - // check to see if we're supposed to shutdown - keepGoing = mInitialized; - } - // service the event queue - PLEvent *event; - while (!PR_CLIST_IS_EMPTY(&eq)) { - event = PLEVENT_FROM_LINK(PR_LIST_HEAD(&eq)); - PR_REMOVE_AND_INIT_LINK(&event->link); - - PL_HandleEvent(event); - } - return keepGoing; -} - - //----------------------------------------------------------------------------- // xpcom api -NS_IMPL_THREADSAFE_ISUPPORTS4(nsSocketTransportService, +NS_IMPL_THREADSAFE_ISUPPORTS5(nsSocketTransportService, nsISocketTransportService, nsIEventTarget, + nsIThreadObserver, nsIRunnable, nsPISocketTransportService) @@ -403,7 +344,12 @@ NS_IMPL_THREADSAFE_ISUPPORTS4(nsSocketTransportService, NS_IMETHODIMP nsSocketTransportService::Init() { - NS_ASSERTION(nsIThread::IsMainThread(), "wrong thread"); + NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY); + + if (!NS_IsMainThread()) { + NS_ERROR("wrong thread"); + return NS_ERROR_UNEXPECTED; + } if (mInitialized) return NS_OK; @@ -424,7 +370,7 @@ nsSocketTransportService::Init() "running socket transport thread without a pollable event"); } - nsresult rv = NS_NewThread(&mThread, this, 0, PR_JOINABLE_THREAD); + nsresult rv = NS_NewThread(&mThread, this); if (NS_FAILED(rv)) return rv; mInitialized = PR_TRUE; @@ -437,16 +383,16 @@ nsSocketTransportService::Shutdown() { LOG(("nsSocketTransportService::Shutdown\n")); - NS_ASSERTION(nsIThread::IsMainThread(), "wrong thread"); + NS_ENSURE_STATE(NS_IsMainThread()); if (!mInitialized) return NS_OK; { - nsAutoLock lock(mEventQLock); + nsAutoLock lock(mLock); - // signal uninitialized to block further events - mInitialized = PR_FALSE; + // signal the socket thread to shutdown + mShuttingDown = PR_TRUE; if (mThreadEvent) PR_SetPollableEvent(mThreadEvent); @@ -454,9 +400,12 @@ nsSocketTransportService::Shutdown() } // join with thread - mThread->Join(); + mThread->Shutdown(); NS_RELEASE(mThread); + mInitialized = PR_FALSE; + mShuttingDown = PR_FALSE; + return NS_OK; } @@ -500,144 +449,187 @@ nsSocketTransportService::SetAutodialEnabled(PRBool value) return NS_OK; } +NS_IMETHODIMP +nsSocketTransportService::OnDispatchedEvent(nsIThreadInternal *thread) +{ + if (mThreadEvent) + PR_SetPollableEvent(mThreadEvent); + return NS_OK; +} + +NS_IMETHODIMP +nsSocketTransportService::OnProcessNextEvent(nsIThreadInternal *thread, + PRBool mayWait, PRUint32 depth) +{ + // DoPollIteration doesn't support being called recursively. This case + // should only happen when someone (e.g., PSM) is issuing a synchronous + // proxy call from this thread to the main thread. + if (depth > 1) + return NS_OK; + + // Favor processing existing sockets before other events. + DoPollIteration(PR_FALSE); + + PRBool val; + while (mayWait && NS_SUCCEEDED(thread->HasPendingEvents(&val)) && !val) + DoPollIteration(PR_TRUE); + + return NS_OK; +} + NS_IMETHODIMP nsSocketTransportService::Run() { - LOG(("nsSocketTransportService::Run")); + LOG(("STS thread init\n")); gSocketThread = PR_GetCurrentThread(); - // // add thread event to poll list (mThreadEvent may be NULL) - // mPollList[0].fd = mThreadEvent; mPollList[0].in_flags = PR_POLL_READ; + nsIThread *thread = NS_GetCurrentThread(); + + // hook ourselves up to observe event processing for this thread + nsCOMPtr threadInt = do_QueryInterface(thread); + threadInt->SetObserver(this); + + for (;;) { + // process all pending events + NS_ProcessPendingEvents(thread); + + // now that our event queue is empty, check to see if we should exit + { + nsAutoLock lock(mLock); + if (mShuttingDown) + break; + } + + // wait for and process the next pending event + NS_ProcessNextEvent(thread); + } + + LOG(("STS shutting down thread\n")); + + // detach any sockets + PRInt32 i; + for (i=mActiveCount-1; i>=0; --i) + DetachSocket(&mActiveList[i]); + for (i=mIdleCount-1; i>=0; --i) + DetachSocket(&mIdleList[i]); + + // Final pass over the event queue. This makes sure that events posted by + // socket detach handlers get processed. + NS_ProcessPendingEvents(thread); + + gSocketThread = nsnull; + + LOG(("STS thread exit\n")); + return NS_OK; +} + +nsresult +nsSocketTransportService::DoPollIteration(PRBool wait) +{ + LOG(("STS poll iter [%d]\n", wait)); + PRInt32 i, count; // // poll loop // - PRBool active = PR_TRUE; - while (active) { - // - // walk active list backwards to see if any sockets should actually be - // idle, then walk the idle list backwards to see if any idle sockets - // should become active. take care to check only idle sockets that - // were idle to begin with ;-) - // - count = mIdleCount; - for (i=mActiveCount-1; i>=0; --i) { - //--- - LOG((" active [%u] { handler=%x condition=%x pollflags=%hu }\n", i, - mActiveList[i].mHandler, - mActiveList[i].mHandler->mCondition, - mActiveList[i].mHandler->mPollFlags)); - //--- - if (NS_FAILED(mActiveList[i].mHandler->mCondition)) - DetachSocket(&mActiveList[i]); - else { - PRUint16 in_flags = mActiveList[i].mHandler->mPollFlags; - if (in_flags == 0) - MoveToIdleList(&mActiveList[i]); - else { - // update poll flags - mPollList[i+1].in_flags = in_flags; - mPollList[i+1].out_flags = 0; - } - } - } - for (i=count-1; i>=0; --i) { - //--- - LOG((" idle [%u] { handler=%x condition=%x pollflags=%hu }\n", i, - mIdleList[i].mHandler, - mIdleList[i].mHandler->mCondition, - mIdleList[i].mHandler->mPollFlags)); - //--- - if (NS_FAILED(mIdleList[i].mHandler->mCondition)) - DetachSocket(&mIdleList[i]); - else if (mIdleList[i].mHandler->mPollFlags != 0) - MoveToPollList(&mIdleList[i]); - } + PRBool pollError = PR_FALSE; - LOG((" calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount)); - - // Measures seconds spent while blocked on PR_Poll - PRUint32 pollInterval; - - PRInt32 n = Poll(&pollInterval); - if (n < 0) { - LOG((" PR_Poll error [%d]\n", PR_GetError())); - active = PR_FALSE; - } + // + // walk active list backwards to see if any sockets should actually be + // idle, then walk the idle list backwards to see if any idle sockets + // should become active. take care to check only idle sockets that + // were idle to begin with ;-) + // + count = mIdleCount; + for (i=mActiveCount-1; i>=0; --i) { + //--- + LOG((" active [%u] { handler=%x condition=%x pollflags=%hu }\n", i, + mActiveList[i].mHandler, + mActiveList[i].mHandler->mCondition, + mActiveList[i].mHandler->mPollFlags)); + //--- + if (NS_FAILED(mActiveList[i].mHandler->mCondition)) + DetachSocket(&mActiveList[i]); else { - // - // service "active" sockets... - // - for (i=0; i 0 && desc.out_flags != 0) { - s.mElapsedTime = 0; - s.mHandler->OnSocketReady(desc.fd, desc.out_flags); - } - // check for timeout errors unless disabled... - else if (s.mHandler->mPollTimeout != PR_UINT16_MAX) { - // update elapsed time counter - if (NS_UNLIKELY(pollInterval > (PR_UINT16_MAX - s.mElapsedTime))) - s.mElapsedTime = PR_UINT16_MAX; - else - s.mElapsedTime += PRUint16(pollInterval); - // check for timeout expiration - if (s.mElapsedTime >= s.mHandler->mPollTimeout) { - s.mElapsedTime = 0; - s.mHandler->OnSocketReady(desc.fd, -1); - } - } - } - - // - // check for "dead" sockets and remove them (need to do this in - // reverse order obviously). - // - for (i=mActiveCount-1; i>=0; --i) { - if (NS_FAILED(mActiveList[i].mHandler->mCondition)) - DetachSocket(&mActiveList[i]); - } - - // - // service the event queue (mPollList[0].fd == mThreadEvent) - // - if (n == 0) - active = ServiceEventQ(); - else if (mPollList[0].out_flags == PR_POLL_READ) { - // acknowledge pollable event (wait should not block) - PR_WaitForPollableEvent(mThreadEvent); - active = ServiceEventQ(); + PRUint16 in_flags = mActiveList[i].mHandler->mPollFlags; + if (in_flags == 0) + MoveToIdleList(&mActiveList[i]); + else { + // update poll flags + mPollList[i+1].in_flags = in_flags; + mPollList[i+1].out_flags = 0; } } } + for (i=count-1; i>=0; --i) { + //--- + LOG((" idle [%u] { handler=%x condition=%x pollflags=%hu }\n", i, + mIdleList[i].mHandler, + mIdleList[i].mHandler->mCondition, + mIdleList[i].mHandler->mPollFlags)); + //--- + if (NS_FAILED(mIdleList[i].mHandler->mCondition)) + DetachSocket(&mIdleList[i]); + else if (mIdleList[i].mHandler->mPollFlags != 0) + MoveToPollList(&mIdleList[i]); + } - // - // shutdown thread - // - - LOG(("shutting down socket transport thread...\n")); + LOG((" calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount)); - mShuttingDown = PR_TRUE; + // Measures seconds spent while blocked on PR_Poll + PRUint32 pollInterval; - // detach any sockets - for (i=mActiveCount-1; i>=0; --i) - DetachSocket(&mActiveList[i]); - for (i=mIdleCount-1; i>=0; --i) - DetachSocket(&mIdleList[i]); + PRInt32 n = Poll(wait, &pollInterval); + if (n < 0) { + LOG((" PR_Poll error [%d]\n", PR_GetError())); + pollError = PR_TRUE; + } + else { + // + // service "active" sockets... + // + for (i=0; i 0 && desc.out_flags != 0) { + s.mElapsedTime = 0; + s.mHandler->OnSocketReady(desc.fd, desc.out_flags); + } + // check for timeout errors unless disabled... + else if (s.mHandler->mPollTimeout != PR_UINT16_MAX) { + // update elapsed time counter + if (NS_UNLIKELY(pollInterval > (PR_UINT16_MAX - s.mElapsedTime))) + s.mElapsedTime = PR_UINT16_MAX; + else + s.mElapsedTime += PRUint16(pollInterval); + // check for timeout expiration + if (s.mElapsedTime >= s.mHandler->mPollTimeout) { + s.mElapsedTime = 0; + s.mHandler->OnSocketReady(desc.fd, -1); + } + } + } - mShuttingDown = PR_FALSE; + // + // check for "dead" sockets and remove them (need to do this in + // reverse order obviously). + // + for (i=mActiveCount-1; i>=0; --i) { + if (NS_FAILED(mActiveList[i].mHandler->mCondition)) + DetachSocket(&mActiveList[i]); + } - // Final pass over the event queue. This makes sure that events posted by - // socket detach handlers get processed. - ServiceEventQ(); + if (n != 0 && mPollList[0].out_flags == PR_POLL_READ) { + // acknowledge pollable event (wait should not block) + PR_WaitForPollableEvent(mThreadEvent); + } + } - gSocketThread = nsnull; return NS_OK; } diff --git a/mozilla/netwerk/base/src/nsSocketTransportService2.h b/mozilla/netwerk/base/src/nsSocketTransportService2.h index cd13f3c8df9..21cb1e5141b 100644 --- a/mozilla/netwerk/base/src/nsSocketTransportService2.h +++ b/mozilla/netwerk/base/src/nsSocketTransportService2.h @@ -1,3 +1,4 @@ +/* vim:set ts=4 sw=4 sts=4 ci et: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -39,9 +40,9 @@ #define nsSocketTransportService2_h__ #include "nsPISocketTransportService.h" -#include "nsIEventTarget.h" -#include "nsIRunnable.h" -#include "nsIThread.h" +#include "nsIThreadInternal.h" +#include "nsThreadUtils.h" +#include "nsEventQueue.h" #include "nsCOMPtr.h" #include "pldhash.h" #include "prinrval.h" @@ -125,6 +126,7 @@ public: class nsSocketTransportService : public nsPISocketTransportService , public nsIEventTarget + , public nsIThreadObserver , public nsIRunnable { public: @@ -132,6 +134,7 @@ public: NS_DECL_NSPISOCKETTRANSPORTSERVICE NS_DECL_NSISOCKETTRANSPORTSERVICE NS_DECL_NSIEVENTTARGET + NS_DECL_NSITHREADOBSERVER NS_DECL_NSIRUNNABLE nsSocketTransportService(); @@ -143,15 +146,17 @@ public: // AttachSocket will fail if the limit is exceeded. consumers should // call CanAttachSocket and check the result before creating a socket. // - PRBool CanAttachSocket() { return mActiveCount + mIdleCount < NS_SOCKET_MAX_COUNT; } + PRBool CanAttachSocket() { + return mActiveCount + mIdleCount < NS_SOCKET_MAX_COUNT; + } // - // if the number of sockets is at the limit, then consumers can be notified - // when the number of sockets becomes less than the limit. the notification - // is asynchronous, delivered via the given PLEvent instance on the socket - // transport thread. + // if the number of sockets reaches the limit, then consumers can be + // notified when the number of sockets becomes less than the limit. the + // notification is asynchronous, delivered via the given nsIRunnable + // instance on the socket transport thread. // - nsresult NotifyWhenCanAttachSocket(PLEvent *); + nsresult NotifyWhenCanAttachSocket(nsIRunnable *); // // add a new socket to the list of controlled sockets. returns a socket @@ -173,25 +178,20 @@ private: // misc (any thread) //------------------------------------------------------------------------- - PRBool mInitialized; nsIThread *mThread; PRFileDesc *mThreadEvent; - - // pref to control autodial code PRBool mAutodialEnabled; + // pref to control autodial code //------------------------------------------------------------------------- - // misc (socket thread only) - //------------------------------------------------------------------------- - // indicates whether we are currently in the process of shutting down - PRBool mShuttingDown; - - //------------------------------------------------------------------------- - // event queue (any thread) + // initialization and shutdown (any thread) //------------------------------------------------------------------------- - PRCList mEventQ; // list of PLEvent objects - PRLock *mEventQLock; + PRLock *mLock; + PRPackedBool mInitialized; + PRPackedBool mShuttingDown; + // indicates whether we are currently in the + // process of shutting down //------------------------------------------------------------------------- // socket lists (socket thread only) @@ -225,9 +225,6 @@ private: void MoveToIdleList(SocketContext *sock); void MoveToPollList(SocketContext *sock); - // returns PR_FALSE to stop processing the main loop - PRBool ServiceEventQ(); - //------------------------------------------------------------------------- // poll list (socket thread only) // @@ -238,7 +235,10 @@ private: PRPollDesc mPollList[ NS_SOCKET_MAX_COUNT + 1 ]; PRIntervalTime PollTimeout(); // computes ideal poll timeout - PRInt32 Poll(PRUint32 *interval); // calls PR_Poll. the out param + nsresult DoPollIteration(PRBool wait); + // perfoms a single poll iteration + PRInt32 Poll(PRBool wait, PRUint32 *interval); + // calls PR_Poll. the out param // interval indicates the poll // duration in seconds. @@ -246,7 +246,7 @@ private: // pending socket queue - see NotifyWhenCanAttachSocket //------------------------------------------------------------------------- - PRCList mPendingSocketQ; // list of PLEvent objects + nsEventQueue mPendingSocketQ; // queue of nsIRunnable objects }; extern nsSocketTransportService *gSocketTransportService; diff --git a/mozilla/netwerk/base/src/nsStreamListenerProxy.cpp b/mozilla/netwerk/base/src/nsStreamListenerProxy.cpp deleted file mode 100644 index 004d791756c..00000000000 --- a/mozilla/netwerk/base/src/nsStreamListenerProxy.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Darin Fisher (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsStreamListenerProxy.h" -#include "netCore.h" -#include "nsIGenericFactory.h" -#include "nsIPipe.h" -#include "nsAutoLock.h" -#include "prlog.h" -#include "nsIOService.h" - -#if defined(PR_LOGGING) -static PRLogModuleInfo *gStreamListenerProxyLog; -#endif - -#define LOG(args) PR_LOG(gStreamListenerProxyLog, PR_LOG_DEBUG, args) - -#define DEFAULT_BUFFER_SEGMENT_SIZE 4096 -#define DEFAULT_BUFFER_MAX_SIZE (4*4096) - -//---------------------------------------------------------------------------- -// Design Overview -// -// A stream listener proxy maintains a pipe. When the request makes data -// available, the proxy copies as much of that data as possible into the pipe. -// If data was written to the pipe, then the proxy posts an asynchronous event -// corresponding to the amount of data written. If no data could be written, -// because the pipe was full, then WOULD_BLOCK is returned to the request, -// indicating that the request should suspend itself. -// -// Once suspended in this manner, the request is only resumed when the pipe is -// emptied. -// -// XXX The current design does NOT allow the request to be "externally" -// suspended!! For the moment this is not a problem, but it should be fixed. -//---------------------------------------------------------------------------- - -//---------------------------------------------------------------------------- -// nsStreamListenerProxy implementation... -//---------------------------------------------------------------------------- - -nsStreamListenerProxy::nsStreamListenerProxy() - : mObserverProxy(nsnull) - , mLock(nsnull) - , mPendingCount(0) - , mPipeEmptied(PR_FALSE) - , mListenerStatus(NS_OK) -{ -} - -nsStreamListenerProxy::~nsStreamListenerProxy() -{ - if (mLock) { - PR_DestroyLock(mLock); - mLock = nsnull; - } - NS_IF_RELEASE(mObserverProxy); -} - -nsresult -nsStreamListenerProxy::GetListener(nsIStreamListener **listener) -{ - NS_ENSURE_TRUE(mObserverProxy, NS_ERROR_NOT_INITIALIZED); - nsIRequestObserver* obs = mObserverProxy->Observer(); - if (!obs) - return NS_ERROR_NULL_POINTER; - return CallQueryInterface(obs, listener); -} - -PRUint32 -nsStreamListenerProxy::GetPendingCount() -{ - return PR_AtomicSet((PRInt32 *) &mPendingCount, 0); -} - -//---------------------------------------------------------------------------- -// nsOnDataAvailableEvent internal class... -//---------------------------------------------------------------------------- - -class nsOnDataAvailableEvent : public nsARequestObserverEvent -{ -public: - nsOnDataAvailableEvent(nsStreamListenerProxy *proxy, - nsIRequest *request, - nsISupports *context, - nsIInputStream *source, - PRUint32 offset) - : nsARequestObserverEvent(request, context) - , mProxy(proxy) - , mSource(source) - , mOffset(offset) - { - MOZ_COUNT_CTOR(nsOnDataAvailableEvent); - NS_PRECONDITION(mProxy, "null pointer"); - NS_ADDREF(mProxy); - } - - ~nsOnDataAvailableEvent() - { - MOZ_COUNT_DTOR(nsOnDataAvailableEvent); - NS_RELEASE(mProxy); - } - - void HandleEvent(); - -protected: - nsStreamListenerProxy *mProxy; - nsCOMPtr mSource; - PRUint32 mOffset; -}; - -void -nsOnDataAvailableEvent::HandleEvent() -{ - LOG(("nsOnDataAvailableEvent: HandleEvent [req=%x]", mRequest.get())); - - if (NS_FAILED(mProxy->GetListenerStatus())) { - LOG(("nsOnDataAvailableEvent: Discarding event [listener_status=%x, req=%x]\n", - mProxy->GetListenerStatus(), mRequest.get())); - return; - } - - nsresult status = NS_OK; - nsresult rv = mRequest->GetStatus(&status); - NS_ASSERTION(NS_SUCCEEDED(rv), "GetStatus failed"); - - // We should only forward this event to the listener if the request is - // still in a "good" state. Because these events are being processed - // asynchronously, there is a very real chance that the listener might - // have cancelled the request after _this_ event was triggered. - - if (NS_FAILED(status)) { - LOG(("nsOnDataAvailableEvent: Not calling OnDataAvailable [req=%x]", - mRequest.get())); - return; - } - - // Find out from the listener proxy how many bytes to report. - PRUint32 count = mProxy->GetPendingCount(); - -#if defined(PR_LOGGING) - { - PRUint32 avail; - mSource->Available(&avail); - LOG(("nsOnDataAvailableEvent: Calling the consumer's OnDataAvailable " - "[offset=%u count=%u avail=%u req=%x]\n", - mOffset, count, avail, mRequest.get())); - } -#endif - - nsCOMPtr listener; - rv = mProxy->GetListener(getter_AddRefs(listener)); - - LOG(("handle dataevent=%8lX\n",(long)this)); - - // Forward call to listener - if (listener) - rv = listener->OnDataAvailable(mRequest, mContext, - mSource, mOffset, count); - - LOG(("nsOnDataAvailableEvent: Done with the consumer's OnDataAvailable " - "[rv=%x, req=%x]\n", rv, mRequest.get())); - - // XXX Need to suspend the underlying request... must consider - // other pending events (such as OnStopRequest). These - // should not be forwarded to the listener if the request - // is suspended. Also, handling the Resume could be tricky. - - if (rv == NS_BASE_STREAM_WOULD_BLOCK) { - NS_NOTREACHED("listener returned NS_BASE_STREAM_WOULD_BLOCK" - " -- support for this is not implemented"); - rv = NS_BINDING_FAILED; - } - - // Cancel the request on unexpected errors - if (NS_FAILED(rv) && (rv != NS_BASE_STREAM_CLOSED)) { - LOG(("OnDataAvailable failed [rv=%x] canceling request!\n")); - mRequest->Cancel(rv); - } - - mProxy->SetListenerStatus(rv); -} - -//---------------------------------------------------------------------------- -// nsStreamListenerProxy::nsISupports implementation... -//---------------------------------------------------------------------------- - -NS_IMPL_THREADSAFE_ISUPPORTS4(nsStreamListenerProxy, - nsIStreamListener, - nsIRequestObserver, - nsIStreamListenerProxy, - nsIInputStreamObserver) - -//---------------------------------------------------------------------------- -// nsStreamListenerProxy::nsIRequestObserver implementation... -//---------------------------------------------------------------------------- - -NS_IMETHODIMP -nsStreamListenerProxy::OnStartRequest(nsIRequest *request, - nsISupports *context) -{ - NS_ENSURE_TRUE(mObserverProxy, NS_ERROR_NOT_INITIALIZED); - - nsresult rv; - nsCOMPtr obs(do_QueryInterface(mPipeIn, &rv)); - if (NS_FAILED(rv)) return rv; - - // This will create a cyclic reference between the pipe and |this|, which - // will be broken when onStopRequest is called. - rv = obs->SetObserver(this); - if (NS_FAILED(rv)) return rv; - - return mObserverProxy->OnStartRequest(request, context); -} - -NS_IMETHODIMP -nsStreamListenerProxy::OnStopRequest(nsIRequest *request, - nsISupports *context, - nsresult status) -{ - NS_ENSURE_TRUE(mObserverProxy, NS_ERROR_NOT_INITIALIZED); - - mPipeIn = 0; - mPipeOut = 0; - - return mObserverProxy->OnStopRequest(request, context, status); -} - -//---------------------------------------------------------------------------- -// nsIStreamListener implementation... -//---------------------------------------------------------------------------- - -NS_IMETHODIMP -nsStreamListenerProxy::OnDataAvailable(nsIRequest *request, - nsISupports *context, - nsIInputStream *source, - PRUint32 offset, - PRUint32 count) -{ - nsresult rv; - PRUint32 bytesWritten=0; - - LOG(("nsStreamListenerProxy: OnDataAvailable [offset=%u count=%u req=%x]\n", - offset, count, request)); - - NS_ENSURE_TRUE(mObserverProxy, NS_ERROR_NOT_INITIALIZED); - NS_PRECONDITION(mRequestToResume == 0, "Unexpected call to OnDataAvailable"); - NS_PRECONDITION(mPipeIn, "Pipe not initialized"); - NS_PRECONDITION(mPipeOut, "Pipe not initialized"); - - // - // Any non-successful listener status gets passed back to the caller - // - { - nsresult status = mListenerStatus; - if (NS_FAILED(status)) { - LOG(("nsStreamListenerProxy: Listener failed [status=%x req=%x]\n", - status, request)); - return status; - } - } - - while (1) { - mPipeEmptied = PR_FALSE; - // - // Try to copy data into the pipe. - // - // If the pipe is full, then we return NS_BASE_STREAM_WOULD_BLOCK - // so the calling request can suspend itself. If, however, we detect - // that the pipe was emptied during this time, we retry copying data - // into the pipe. - // - rv = mPipeOut->WriteFrom(source, count, &bytesWritten); - - LOG(("nsStreamListenerProxy: Wrote data to pipe [rv=%x count=%u bytesWritten=%u req=%x]\n", - rv, count, bytesWritten, request)); - - if (NS_FAILED(rv)) { - if (rv == NS_BASE_STREAM_WOULD_BLOCK) { - nsAutoLock lock(mLock); - if (mPipeEmptied) { - LOG(("nsStreamListenerProxy: Pipe emptied; looping back [req=%x]\n", request)); - continue; - } - LOG(("nsStreamListenerProxy: Pipe full; setting request to resume [req=%x]\n", request)); - mRequestToResume = request; - } - return rv; - } - if (bytesWritten == 0) { - LOG(("nsStreamListenerProxy: Copied zero bytes; not posting an event [req=%x]\n", request)); - return NS_OK; - } - - // Copied something into the pipe... - break; - } - - // - // Update the pending count; return if able to piggy-back on a pending event. - // - PRUint32 total = PR_AtomicAdd((PRInt32 *) &mPendingCount, bytesWritten); - if (total > bytesWritten) { - LOG(("nsStreamListenerProxy: Piggy-backing pending event [total=%u, req=%x]\n", - total, request)); - return NS_OK; - } - - // - // Post an event for the number of bytes actually written. - // - nsOnDataAvailableEvent *ev = - new nsOnDataAvailableEvent(this, request, context, mPipeIn, offset); - if (!ev) return NS_ERROR_OUT_OF_MEMORY; - - // Reuse the event queue of the observer proxy - LOG(("post dataevent=%8lX queue=%8lX\n",(long)ev,(long)mObserverProxy->EventQueue())); - rv = mObserverProxy->FireEvent(ev); - if (NS_FAILED(rv)) - delete ev; - return rv; -} - -//---------------------------------------------------------------------------- -// nsStreamListenerProxy::nsIStreamListenerProxy implementation... -//---------------------------------------------------------------------------- - -NS_IMETHODIMP -nsStreamListenerProxy::Init(nsIStreamListener *listener, - nsIEventQueue *eventQ, - PRUint32 bufferSegmentSize, - PRUint32 bufferMaxSize) -{ - NS_ENSURE_ARG_POINTER(listener); - -#if defined(PR_LOGGING) - if (!gStreamListenerProxyLog) - gStreamListenerProxyLog = PR_NewLogModule("nsStreamListenerProxy"); -#endif - - // - // Create the RequestToResume lock - // - mLock = PR_NewLock(); - if (!mLock) return NS_ERROR_OUT_OF_MEMORY; - - // - // Create the request observer proxy - // - mObserverProxy = new nsRequestObserverProxy(); - if (!mObserverProxy) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(mObserverProxy); - - // - // Create the pipe - // - if (bufferSegmentSize == 0) - bufferSegmentSize = DEFAULT_BUFFER_SEGMENT_SIZE; - if (bufferMaxSize == 0) - bufferMaxSize = DEFAULT_BUFFER_MAX_SIZE; - // The segment size must not exceed the maximum - bufferSegmentSize = PR_MIN(bufferMaxSize, bufferSegmentSize); - - // Use the necko buffer cache for the default buffers - nsIMemory *allocator = nsnull; - if (bufferSegmentSize == DEFAULT_BUFFER_SEGMENT_SIZE) - allocator = nsIOService::gBufferCache; - nsresult rv = NS_NewPipe(getter_AddRefs(mPipeIn), - getter_AddRefs(mPipeOut), - bufferSegmentSize, - bufferMaxSize, - PR_TRUE, PR_TRUE, allocator); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr observer = do_QueryInterface(listener); - return mObserverProxy->Init(observer, eventQ); -} - -//---------------------------------------------------------------------------- -// nsStreamListenerProxy::nsIInputStreamObserver implementation... -//---------------------------------------------------------------------------- - -NS_IMETHODIMP -nsStreamListenerProxy::OnEmpty(nsIInputStream *inputStream) -{ - LOG(("nsStreamListenerProxy: OnEmpty\n")); - // - // The pipe has been emptied by the listener. If the request - // has been suspended (waiting for the pipe to be emptied), then - // go ahead and resume it. But take care not to resume while - // holding the "ChannelToResume" lock. - // - nsCOMPtr req; - { - nsAutoLock lock(mLock); - if (mRequestToResume) { - req = mRequestToResume; - mRequestToResume = 0; - } - mPipeEmptied = PR_TRUE; // Flag this call - } - if (req) { - LOG(("nsStreamListenerProxy: Resuming request\n")); - req->Resume(); - } - return NS_OK; -} - -NS_IMETHODIMP -nsStreamListenerProxy::OnClose(nsIInputStream *aInputStream) -{ - LOG(("nsStreamListenerProxy: OnClose\n")); - return NS_OK; -} diff --git a/mozilla/netwerk/base/src/nsStreamLoader.cpp b/mozilla/netwerk/base/src/nsStreamLoader.cpp index 122830ce94b..9c8b8f86d56 100644 --- a/mozilla/netwerk/base/src/nsStreamLoader.cpp +++ b/mozilla/netwerk/base/src/nsStreamLoader.cpp @@ -38,9 +38,6 @@ #include "nsStreamLoader.h" #include "nsIInputStream.h" #include "nsIChannel.h" -#include "nsProxiedService.h" - -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); NS_IMETHODIMP nsStreamLoader::Init(nsIChannel *channel, diff --git a/mozilla/netwerk/base/src/nsStreamObserverProxy.cpp b/mozilla/netwerk/base/src/nsStreamObserverProxy.cpp index c277bd6105b..e69de29bb2d 100644 --- a/mozilla/netwerk/base/src/nsStreamObserverProxy.cpp +++ b/mozilla/netwerk/base/src/nsStreamObserverProxy.cpp @@ -1,297 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Darin Fisher (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsStreamObserverProxy.h" -#include "nsIGenericFactory.h" -#include "nsIServiceManager.h" -#include "nsIEventQueueService.h" -#include "nsString.h" - -#if defined(PR_LOGGING) -PRLogModuleInfo *gStreamProxyLog; -#endif -#define LOG(args) PR_LOG(gStreamProxyLog, PR_LOG_DEBUG, args) - -static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID); - -// -//---------------------------------------------------------------------------- -// nsStreamObserverEvent implementation... -//---------------------------------------------------------------------------- -// -nsStreamObserverEvent::nsStreamObserverEvent(nsStreamProxyBase *aProxy, - nsIRequest *aRequest, - nsISupports *aContext) - : mProxy(aProxy) - , mRequest(aRequest) - , mContext(aContext) -{ - NS_IF_ADDREF(mProxy); -} - -nsStreamObserverEvent::~nsStreamObserverEvent() -{ - NS_IF_RELEASE(mProxy); -} - -nsresult -nsStreamObserverEvent::FireEvent(nsIEventQueue *aEventQ) -{ - NS_PRECONDITION(aEventQ, "null event queue"); - - PL_InitEvent(&mEvent, nsnull, - nsStreamObserverEvent::HandlePLEvent, - nsStreamObserverEvent::DestroyPLEvent); - - PRStatus status = aEventQ->PostEvent(&mEvent); - return status == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE; -} - -void* PR_CALLBACK -nsStreamObserverEvent::HandlePLEvent(PLEvent *aEvent) -{ - nsStreamObserverEvent *ev = GET_STREAM_OBSERVER_EVENT(aEvent); - NS_ASSERTION(ev, "null event"); - - // Pass control the real event handler - if (ev) - ev->HandleEvent(); - - return nsnull; -} - -void PR_CALLBACK -nsStreamObserverEvent::DestroyPLEvent(PLEvent *aEvent) -{ - nsStreamObserverEvent *ev = GET_STREAM_OBSERVER_EVENT(aEvent); - NS_ASSERTION(ev, "null event"); - delete ev; -} - -// -//---------------------------------------------------------------------------- -// nsOnStartRequestEvent internal class... -//---------------------------------------------------------------------------- -// -class nsOnStartRequestEvent : public nsStreamObserverEvent -{ -public: - nsOnStartRequestEvent(nsStreamProxyBase *aProxy, - nsIRequest *aRequest, - nsISupports *aContext) - : nsStreamObserverEvent(aProxy, aRequest, aContext) - { - MOZ_COUNT_CTOR(nsOnStartRequestEvent); - } - - ~nsOnStartRequestEvent() - { - MOZ_COUNT_DTOR(nsOnStartRequestEvent); - } - - NS_IMETHOD HandleEvent(); -}; - -NS_IMETHODIMP -nsOnStartRequestEvent::HandleEvent() -{ - LOG(("nsOnStartRequestEvent: HandleEvent [event=%x req=%x]\n", - this, mRequest.get())); - - nsCOMPtr observer = mProxy->GetReceiver(); - if (!observer) { - LOG(("nsOnStartRequestEvent: Already called OnStopRequest (observer is NULL)\n")); - return NS_ERROR_FAILURE; - } - - nsresult rv = observer->OnStartRequest(mRequest, mContext); - if (NS_FAILED(rv)) { - LOG(("OnStartRequest failed [rv=%x] canceling request!\n", rv)); - mRequest->Cancel(rv); - } - return rv; -} - -// -//---------------------------------------------------------------------------- -// nsOnStopRequestEvent internal class... -//---------------------------------------------------------------------------- -// -class nsOnStopRequestEvent : public nsStreamObserverEvent -{ -public: - nsOnStopRequestEvent(nsStreamProxyBase *aProxy, - nsIRequest *aRequest, nsISupports *aContext, - nsresult aStatus, const PRUnichar *aStatusText) - : nsStreamObserverEvent(aProxy, aRequest, aContext) - , mStatus(aStatus) - , mStatusText(aStatusText) - { - MOZ_COUNT_CTOR(nsOnStopRequestEvent); - } - - ~nsOnStopRequestEvent() - { - MOZ_COUNT_DTOR(nsOnStopRequestEvent); - } - - NS_IMETHOD HandleEvent(); - -protected: - nsresult mStatus; - nsString mStatusText; -}; - -NS_IMETHODIMP -nsOnStopRequestEvent::HandleEvent() -{ - LOG(("nsOnStopRequestEvent: HandleEvent [event=%x req=%x]\n", - this, mRequest.get())); - - nsCOMPtr observer = mProxy->GetReceiver(); - if (!observer) { - LOG(("nsOnStopRequestEvent: Already called OnStopRequest (observer is NULL)\n")); - return NS_ERROR_FAILURE; - } - - // - // Do not allow any more events to be handled after OnStopRequest - // - mProxy->SetReceiver(nsnull); - - return observer->OnStopRequest(mRequest, - mContext, - mStatus, - mStatusText.get()); -} - -// -//---------------------------------------------------------------------------- -// nsStreamProxyBase: nsISupports implementation... -//---------------------------------------------------------------------------- -// -NS_IMPL_THREADSAFE_ISUPPORTS1(nsStreamProxyBase, - nsIStreamObserver) - -// -//---------------------------------------------------------------------------- -// nsStreamProxyBase: nsIStreamObserver implementation... -//---------------------------------------------------------------------------- -// -NS_IMETHODIMP -nsStreamProxyBase::OnStartRequest(nsIRequest *aRequest, - nsISupports *aContext) -{ - LOG(("nsStreamProxyBase: OnStartRequest [this=%x req=%x]\n", this, aRequest)); - nsOnStartRequestEvent *ev = - new nsOnStartRequestEvent(this, aRequest, aContext); - if (!ev) - return NS_ERROR_OUT_OF_MEMORY; - - nsresult rv = ev->FireEvent(GetEventQueue()); - if (NS_FAILED(rv)) - delete ev; - return rv; -} - -NS_IMETHODIMP -nsStreamProxyBase::OnStopRequest(nsIRequest *aRequest, - nsISupports *aContext, - nsresult aStatus, - const PRUnichar *aStatusText) -{ - LOG(("nsStreamProxyBase: OnStopRequest [this=%x req=%x status=%x]\n", - this, aRequest, aStatus)); - nsOnStopRequestEvent *ev = - new nsOnStopRequestEvent(this, aRequest, aContext, aStatus, aStatusText); - if (!ev) - return NS_ERROR_OUT_OF_MEMORY; - - nsresult rv = ev->FireEvent(GetEventQueue()); - if (NS_FAILED(rv)) - delete ev; - return rv; -} - -// -//---------------------------------------------------------------------------- -// nsStreamProxyBase: implementation... -//---------------------------------------------------------------------------- -// -nsresult -nsStreamProxyBase::SetEventQueue(nsIEventQueue *aEventQ) -{ -#if defined(PR_LOGGING) - if (!gStreamProxyLog) - gStreamProxyLog = PR_NewLogModule("nsStreamProxy"); -#endif - nsresult rv = NS_OK; - if ((aEventQ == NS_CURRENT_EVENTQ) || (aEventQ == NS_UI_THREAD_EVENTQ)) { - nsCOMPtr serv = - do_GetService(kEventQueueService, &rv); - if (NS_FAILED(rv)) - return rv; - rv = serv->GetSpecialEventQueue((PRInt32) aEventQ, - getter_AddRefs(mEventQ)); - } else - mEventQ = aEventQ; - return rv; -} - -// -//---------------------------------------------------------------------------- -// nsStreamObserverProxy: nsISupports implementation... -//---------------------------------------------------------------------------- -// -NS_IMPL_ISUPPORTS_INHERITED1(nsStreamObserverProxy, - nsStreamProxyBase, - nsIStreamObserverProxy) - -// -//---------------------------------------------------------------------------- -// nsStreamObserverProxy: nsIStreamObserverProxy implementation... -//---------------------------------------------------------------------------- -// -NS_IMETHODIMP -nsStreamObserverProxy::Init(nsIStreamObserver *aObserver, - nsIEventQueue *aEventQ) -{ - NS_PRECONDITION(aObserver, "null observer"); - SetReceiver(aObserver); - return SetEventQueue(aEventQ); -} diff --git a/mozilla/netwerk/base/src/nsStreamObserverProxy.h b/mozilla/netwerk/base/src/nsStreamObserverProxy.h index b667a8c78a3..e69de29bb2d 100644 --- a/mozilla/netwerk/base/src/nsStreamObserverProxy.h +++ b/mozilla/netwerk/base/src/nsStreamObserverProxy.h @@ -1,110 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsStreamObserverProxy_h__ -#define nsStreamObserverProxy_h__ - -#include "nsIStreamObserver.h" -#include "nsIEventQueue.h" -#include "nsIChannel.h" -#include "nsCOMPtr.h" -#include "prlog.h" - -#if defined(PR_LOGGING) -extern PRLogModuleInfo *gStreamProxyLog; -#endif - -class nsStreamProxyBase : public nsIStreamObserver -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSISTREAMOBSERVER - - nsStreamProxyBase() { } - virtual ~nsStreamProxyBase() {} - - nsIEventQueue *GetEventQueue() { return mEventQ.get(); } - nsIStreamObserver *GetReceiver() { return mReceiver.get(); } - - nsresult SetEventQueue(nsIEventQueue *); - - nsresult SetReceiver(nsIStreamObserver *aReceiver) { - PRBool same = ::SameCOMIdentity(aReceiver, this); - NS_ASSERTION((!same), "aReceiver is self"); - mReceiver = aReceiver; - return NS_OK; - } - -private: - nsCOMPtr mEventQ; - nsCOMPtr mReceiver; -}; - -class nsStreamObserverProxy : public nsStreamProxyBase - , public nsIStreamObserverProxy -{ -public: - NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_NSISTREAMOBSERVER(nsStreamProxyBase::) - NS_DECL_NSISTREAMOBSERVERPROXY -}; - -class nsStreamObserverEvent -{ -public: - nsStreamObserverEvent(nsStreamProxyBase *proxy, - nsIRequest *request, nsISupports *context); - virtual ~nsStreamObserverEvent(); - - nsresult FireEvent(nsIEventQueue *); - NS_IMETHOD HandleEvent() = 0; - -protected: - static void* PR_CALLBACK HandlePLEvent(PLEvent *); - static void PR_CALLBACK DestroyPLEvent(PLEvent *); - - PLEvent mEvent; - nsStreamProxyBase *mProxy; - nsCOMPtr mRequest; - nsCOMPtr mContext; -}; - -#define GET_STREAM_OBSERVER_EVENT(_mEvent_ptr) \ - ((nsStreamObserverEvent *) \ - ((char *)(_mEvent_ptr) - offsetof(nsStreamObserverEvent, mEvent))) - -#endif /* !nsStreamObserverProxy_h__ */ diff --git a/mozilla/netwerk/base/src/nsStreamTransportService.cpp b/mozilla/netwerk/base/src/nsStreamTransportService.cpp index 02983999a06..d3b6c98b7c9 100644 --- a/mozilla/netwerk/base/src/nsStreamTransportService.cpp +++ b/mozilla/netwerk/base/src/nsStreamTransportService.cpp @@ -36,6 +36,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsStreamTransportService.h" +#include "nsXPCOMCIDInternal.h" #include "nsNetSegmentUtils.h" #include "nsAutoLock.h" #include "nsInt64.h" @@ -51,8 +52,7 @@ #include "nsIPipe.h" #include "nsITransport.h" #include "nsIRunnable.h" -#include "nsIProxyObjectManager.h" -#include "nsIEventTarget.h" +#include "nsIObserverService.h" //----------------------------------------------------------------------------- // nsInputStreamTransport @@ -120,7 +120,7 @@ nsInputStreamTransport::OpenInputStream(PRUint32 flags, nsresult rv; nsCOMPtr target = - do_GetService(NS_IOTHREADPOOL_CONTRACTID, &rv); + do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; // XXX if the caller requests an unbuffered stream, then perhaps @@ -333,7 +333,7 @@ nsOutputStreamTransport::OpenOutputStream(PRUint32 flags, nsresult rv; nsCOMPtr target = - do_GetService(NS_IOTHREADPOOL_CONTRACTID, &rv); + do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; // XXX if the caller requests an unbuffered stream, then perhaps @@ -468,7 +468,47 @@ nsOutputStreamTransport::IsNonBlocking(PRBool *result) // nsStreamTransportService //----------------------------------------------------------------------------- -NS_IMPL_THREADSAFE_ISUPPORTS1(nsStreamTransportService, nsIStreamTransportService) +nsStreamTransportService::~nsStreamTransportService() +{ + NS_ASSERTION(!mPool, "thread pool wasn't shutdown"); +} + +nsresult +nsStreamTransportService::Init() +{ + mPool = do_CreateInstance(NS_THREADPOOL_CONTRACTID); + NS_ENSURE_STATE(mPool); + + // Configure the pool + mPool->SetThreadLimit(4); + mPool->SetIdleThreadLimit(1); + mPool->SetIdleThreadTimeout(PR_SecondsToInterval(60)); + + nsCOMPtr obsSvc = + do_GetService("@mozilla.org/observer-service;1"); + if (obsSvc) + obsSvc->AddObserver(this, "xpcom-shutdown-threads", PR_FALSE); + return NS_OK; +} + +NS_IMPL_THREADSAFE_ISUPPORTS3(nsStreamTransportService, + nsIStreamTransportService, + nsIEventTarget, + nsIObserver) + +NS_IMETHODIMP +nsStreamTransportService::Dispatch(nsIRunnable *task, PRUint32 flags) +{ + NS_ENSURE_TRUE(mPool, NS_ERROR_NOT_INITIALIZED); + return mPool->Dispatch(task, flags); +} + +NS_IMETHODIMP +nsStreamTransportService::IsOnCurrentThread(PRBool *result) +{ + NS_ENSURE_TRUE(mPool, NS_ERROR_NOT_INITIALIZED); + return mPool->IsOnCurrentThread(result); +} NS_IMETHODIMP nsStreamTransportService::CreateInputTransport(nsIInputStream *stream, @@ -499,3 +539,16 @@ nsStreamTransportService::CreateOutputTransport(nsIOutputStream *stream, NS_ADDREF(*result = trans); return NS_OK; } + +NS_IMETHODIMP +nsStreamTransportService::Observe(nsISupports *subject, const char *topic, + const PRUnichar *data) +{ + NS_ASSERTION(strcmp(topic, "xpcom-shutdown-threads") == 0, "oops"); + + if (mPool) { + mPool->Shutdown(); + mPool = nsnull; + } + return NS_OK; +} diff --git a/mozilla/netwerk/base/src/nsStreamTransportService.h b/mozilla/netwerk/base/src/nsStreamTransportService.h index b467115108b..4dac770ecf1 100644 --- a/mozilla/netwerk/base/src/nsStreamTransportService.h +++ b/mozilla/netwerk/base/src/nsStreamTransportService.h @@ -36,13 +36,27 @@ * ***** END LICENSE BLOCK ***** */ #include "nsIStreamTransportService.h" +#include "nsIEventTarget.h" +#include "nsIThreadPool.h" +#include "nsIObserver.h" +#include "nsCOMPtr.h" class nsStreamTransportService : public nsIStreamTransportService + , public nsIEventTarget + , public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSISTREAMTRANSPORTSERVICE + NS_DECL_NSIEVENTTARGET + NS_DECL_NSIOBSERVER + + nsresult Init(); nsStreamTransportService() {} - virtual ~nsStreamTransportService() {} + +private: + ~nsStreamTransportService(); + + nsCOMPtr mPool; }; diff --git a/mozilla/netwerk/base/src/nsSyncStreamListener.cpp b/mozilla/netwerk/base/src/nsSyncStreamListener.cpp index 76a88b0723b..74d35e97295 100644 --- a/mozilla/netwerk/base/src/nsSyncStreamListener.cpp +++ b/mozilla/netwerk/base/src/nsSyncStreamListener.cpp @@ -36,7 +36,6 @@ #include "nsSyncStreamListener.h" #include "nsIPipe.h" -#include "nsEventQueueUtils.h" #include "nsNetSegmentUtils.h" nsresult @@ -53,23 +52,10 @@ nsSyncStreamListener::Init() nsresult nsSyncStreamListener::WaitForData() { - nsresult rv; - - if (!mEventQ) { - rv = NS_GetCurrentEventQ(getter_AddRefs(mEventQ)); - if (NS_FAILED(rv)) return rv; - } - mKeepWaiting = PR_TRUE; - PLEvent *ev; - while (mKeepWaiting) { - rv = mEventQ->WaitForEvent(&ev); - if (NS_FAILED(rv)) return rv; - - rv = mEventQ->HandleEvent(ev); - if (NS_FAILED(rv)) return rv; - } + while (mKeepWaiting) + NS_ENSURE_STATE(NS_ProcessNextEvent(NS_GetCurrentThread())); return NS_OK; } diff --git a/mozilla/netwerk/base/src/nsSyncStreamListener.h b/mozilla/netwerk/base/src/nsSyncStreamListener.h index ecfd65f13f9..0c03d439839 100644 --- a/mozilla/netwerk/base/src/nsSyncStreamListener.h +++ b/mozilla/netwerk/base/src/nsSyncStreamListener.h @@ -40,7 +40,7 @@ #include "nsISyncStreamListener.h" #include "nsIInputStream.h" #include "nsIOutputStream.h" -#include "nsIEventQueue.h" +#include "nsThreadUtils.h" #include "nsCOMPtr.h" //----------------------------------------------------------------------------- @@ -59,17 +59,16 @@ public: : mStatus(NS_OK) , mKeepWaiting(PR_FALSE) , mDone(PR_FALSE) {} - virtual ~nsSyncStreamListener() {} nsresult Init(); private: + ~nsSyncStreamListener() {} nsresult WaitForData(); nsCOMPtr mPipeIn; nsCOMPtr mPipeOut; - nsCOMPtr mEventQ; nsresult mStatus; PRPackedBool mKeepWaiting; PRPackedBool mDone; diff --git a/mozilla/netwerk/base/src/nsTransportUtils.cpp b/mozilla/netwerk/base/src/nsTransportUtils.cpp index fb325b048a9..529a8d5e380 100644 --- a/mozilla/netwerk/base/src/nsTransportUtils.cpp +++ b/mozilla/netwerk/base/src/nsTransportUtils.cpp @@ -36,11 +36,11 @@ #include "nsTransportUtils.h" #include "nsITransport.h" -#include "nsIEventTarget.h" #include "nsProxyRelease.h" +#include "nsThreadUtils.h" #include "nsAutoLock.h" +#include "nsAutoPtr.h" #include "nsCOMPtr.h" -#include "plevent.h" //----------------------------------------------------------------------------- @@ -81,7 +81,7 @@ public: PRBool mCoalesceAll; }; -class nsTransportStatusEvent : public PLEvent +class nsTransportStatusEvent : public nsRunnable { public: nsTransportStatusEvent(nsTransportEventSinkProxy *proxy, @@ -89,46 +89,31 @@ public: nsresult status, PRUint64 progress, PRUint64 progressMax) - : mTransport(transport) + : mProxy(proxy) + , mTransport(transport) , mStatus(status) , mProgress(progress) , mProgressMax(progressMax) - { - NS_ADDREF(proxy); - PL_InitEvent(this, proxy, HandleEvent, DestroyEvent); - } + {} - ~nsTransportStatusEvent() - { - nsTransportEventSinkProxy *proxy = - (nsTransportEventSinkProxy *) owner; - NS_RELEASE(proxy); - } + ~nsTransportStatusEvent() {} - PR_STATIC_CALLBACK(void*) HandleEvent(PLEvent *event) + NS_IMETHOD Run() { - nsTransportStatusEvent *self = (nsTransportStatusEvent *) event; - nsTransportEventSinkProxy *proxy = (nsTransportEventSinkProxy *) event->owner; - // since this event is being handled, we need to clear the proxy's ref. // if not coalescing all, then last event may not equal self! { - nsAutoLock lock(proxy->mLock); - if (proxy->mLastEvent == self) - proxy->mLastEvent = nsnull; + nsAutoLock lock(mProxy->mLock); + if (mProxy->mLastEvent == this) + mProxy->mLastEvent = nsnull; } - proxy->mSink->OnTransportStatus(self->mTransport, - self->mStatus, - self->mProgress, - self->mProgressMax); + mProxy->mSink->OnTransportStatus(mTransport, mStatus, mProgress, + mProgressMax); return nsnull; } - PR_STATIC_CALLBACK(void) DestroyEvent(PLEvent *event) - { - delete (nsTransportStatusEvent *) event; - } + nsRefPtr mProxy; // parameters to OnTransportStatus nsCOMPtr mTransport; @@ -146,7 +131,7 @@ nsTransportEventSinkProxy::OnTransportStatus(nsITransport *transport, PRUint64 progressMax) { nsresult rv = NS_OK; - PLEvent *event; + nsRefPtr event; { nsAutoLock lock(mLock); @@ -155,21 +140,19 @@ nsTransportEventSinkProxy::OnTransportStatus(nsITransport *transport, mLastEvent->mStatus = status; mLastEvent->mProgress = progress; mLastEvent->mProgressMax = progressMax; - event = nsnull; } else { event = new nsTransportStatusEvent(this, transport, status, progress, progressMax); if (!event) rv = NS_ERROR_OUT_OF_MEMORY; - mLastEvent = (nsTransportStatusEvent *) event; + mLastEvent = event; // weak ref } } if (event) { - rv = mTarget->PostEvent(event); + rv = mTarget->Dispatch(event, NS_DISPATCH_NORMAL); if (NS_FAILED(rv)) { NS_WARNING("unable to post transport status event"); - PL_DestroyEvent(event); nsAutoLock lock(mLock); // cleanup.. don't reference anymore! mLastEvent = nsnull; diff --git a/mozilla/netwerk/base/src/nsUnicharStreamLoader.cpp b/mozilla/netwerk/base/src/nsUnicharStreamLoader.cpp index 8ed9ee09e7b..f34555271e3 100644 --- a/mozilla/netwerk/base/src/nsUnicharStreamLoader.cpp +++ b/mozilla/netwerk/base/src/nsUnicharStreamLoader.cpp @@ -50,8 +50,6 @@ #include "nsReadableUtils.h" #endif // DEBUG -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); - NS_IMETHODIMP nsUnicharStreamLoader::Init(nsIChannel *aChannel, nsIUnicharStreamLoaderObserver *aObserver, diff --git a/mozilla/netwerk/build/nsNetCID.h b/mozilla/netwerk/build/nsNetCID.h index e6a0ff8475c..24e3147c98c 100644 --- a/mozilla/netwerk/build/nsNetCID.h +++ b/mozilla/netwerk/build/nsNetCID.h @@ -61,20 +61,6 @@ #define NS_NETUTIL_CONTRACTID \ "@mozilla.org/network/util;1" -// service implementing nsIEventTarget. events dispatched to this event -// target will be executed on one of necko's background i/o threads. -#define NS_IOTHREADPOOL_CLASSNAME \ - "nsIOThreadPool" -#define NS_IOTHREADPOOL_CONTRACTID \ - "@mozilla.org/network/io-thread-pool;1" -#define NS_IOTHREADPOOL_CID \ -{ /* f1d62b49-5051-48e2-9155-c3509428461e */ \ - 0xf1d62b49, \ - 0x5051, \ - 0x48e2, \ - {0x91, 0x55, 0xc3, 0x50, 0x94, 0x28, 0x46, 0x1e} \ -} - // service implementing nsIProtocolProxyService and nsPIProtocolProxyService. #define NS_PROTOCOLPROXYSERVICE_CLASSNAME \ "nsProtocolProxyService" diff --git a/mozilla/netwerk/build/nsNetModule.cpp b/mozilla/netwerk/build/nsNetModule.cpp index 66fbdf9e682..8edd49f12c1 100644 --- a/mozilla/netwerk/build/nsNetModule.cpp +++ b/mozilla/netwerk/build/nsNetModule.cpp @@ -50,13 +50,11 @@ #include "nsLoadGroup.h" #include "nsStreamLoader.h" #include "nsUnicharStreamLoader.h" -#include "nsAsyncStreamListener.h" #include "nsFileStreams.h" #include "nsBufferedStreams.h" #include "nsMIMEInputStream.h" #include "nsSOCKSSocketProvider.h" #include "nsCacheService.h" -#include "nsIOThreadPool.h" #include "nsMimeTypes.h" #include "nsNetStrings.h" @@ -83,7 +81,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsProtocolProxyService, Init) NS_DECL_CLASSINFO(nsProtocolProxyService) #include "nsStreamTransportService.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsStreamTransportService) +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStreamTransportService, Init) #include "nsSocketTransportService2.h" #undef LOG @@ -630,10 +628,6 @@ static const nsModuleComponentInfo gNetModuleInfo[] = { NS_IOSERVICE_CID, NS_NETUTIL_CONTRACTID, nsIOServiceConstructor }, - { NS_IOTHREADPOOL_CLASSNAME, - NS_IOTHREADPOOL_CID, - NS_IOTHREADPOOL_CONTRACTID, - net_NewIOThreadPool }, { NS_STREAMTRANSPORTSERVICE_CLASSNAME, NS_STREAMTRANSPORTSERVICE_CID, NS_STREAMTRANSPORTSERVICE_CONTRACTID, @@ -698,10 +692,6 @@ static const nsModuleComponentInfo gNetModuleInfo[] = { NS_SIMPLESTREAMLISTENER_CID, NS_SIMPLESTREAMLISTENER_CONTRACTID, nsSimpleStreamListenerConstructor }, - { NS_ASYNCSTREAMLISTENER_CLASSNAME, - NS_ASYNCSTREAMLISTENER_CID, - NS_ASYNCSTREAMLISTENER_CONTRACTID, - nsAsyncStreamListener::Create }, { NS_STREAMLISTENERTEE_CLASSNAME, NS_STREAMLISTENERTEE_CID, NS_STREAMLISTENERTEE_CONTRACTID, diff --git a/mozilla/netwerk/cache/src/nsCacheEntry.cpp b/mozilla/netwerk/cache/src/nsCacheEntry.cpp index 82cf9720316..f1f1cad8fb8 100644 --- a/mozilla/netwerk/cache/src/nsCacheEntry.cpp +++ b/mozilla/netwerk/cache/src/nsCacheEntry.cpp @@ -44,6 +44,8 @@ #include "nsCacheEntryDescriptor.h" #include "nsCacheMetaData.h" #include "nsCacheRequest.h" +#include "nsThreadUtils.h" +#include "nsProxyRelease.h" #include "nsError.h" #include "nsICacheService.h" #include "nsCache.h" @@ -85,11 +87,11 @@ nsCacheEntry::~nsCacheEntry() // proxy release of of memory cache nsISupports objects if (!mData) return; - nsISupports * data = mData; - NS_ADDREF(data); // this reference will be owned by the proxy - mData = nsnull; // release our reference before switching threads + nsISupports *data = nsnull; + mData.swap(data); // this reference will be owned by the proxy + // release our reference before switching threads - nsCacheService::ProxyObjectRelease(data, mThread); + NS_ProxyRelease(mThread, data); } @@ -138,6 +140,13 @@ nsCacheEntry::TouchData() } +void +nsCacheEntry::SetThread() +{ + mThread = do_GetCurrentThread(); +} + + void nsCacheEntry::TouchMetaData() { diff --git a/mozilla/netwerk/cache/src/nsCacheEntry.h b/mozilla/netwerk/cache/src/nsCacheEntry.h index 2b19eb7031e..9f886186053 100644 --- a/mozilla/netwerk/cache/src/nsCacheEntry.h +++ b/mozilla/netwerk/cache/src/nsCacheEntry.h @@ -43,6 +43,7 @@ #include "nsICache.h" #include "nsICacheEntryDescriptor.h" +#include "nsIThread.h" #include "nsCacheMetaData.h" #include "nspr.h" @@ -110,7 +111,7 @@ public: void TouchData(); - void SetThread(PRThread *aThread) { mThread = aThread; } + void SetThread(); /** * Meta data accessors @@ -241,7 +242,7 @@ private: nsCacheDevice * mCacheDevice; // 4 nsCOMPtr mSecurityInfo; // nsCOMPtr mData; // - PRThread * mThread; + nsCOMPtr mThread; nsCacheMetaData mMetaData; // 4 PRCList mRequestQ; // 8 PRCList mDescriptorQ; // 8 diff --git a/mozilla/netwerk/cache/src/nsCacheRequest.h b/mozilla/netwerk/cache/src/nsCacheRequest.h index 7015aa6b588..68d6fc336c4 100644 --- a/mozilla/netwerk/cache/src/nsCacheRequest.h +++ b/mozilla/netwerk/cache/src/nsCacheRequest.h @@ -45,7 +45,6 @@ #include "nsCOMPtr.h" #include "nsICache.h" #include "nsICacheListener.h" -#include "nsIEventQueue.h" #include "nsCacheSession.h" @@ -63,7 +62,6 @@ private: : mKey(key), mInfo(0), mListener(listener), - mThread(nsnull), mLock(nsnull), mCondVar(nsnull) { @@ -189,7 +187,7 @@ private: nsCString * mKey; PRUint32 mInfo; nsCOMPtr mListener; - PRThread * mThread; + nsCOMPtr mThread; PRLock * mLock; PRCondVar * mCondVar; }; diff --git a/mozilla/netwerk/cache/src/nsCacheService.cpp b/mozilla/netwerk/cache/src/nsCacheService.cpp index b0899c1c354..4508d35070e 100644 --- a/mozilla/netwerk/cache/src/nsCacheService.cpp +++ b/mozilla/netwerk/cache/src/nsCacheService.cpp @@ -56,7 +56,6 @@ #endif #include "nsAutoLock.h" -#include "nsIEventQueue.h" #include "nsIObserverService.h" #include "nsIPrefService.h" #include "nsIPrefBranch.h" @@ -64,6 +63,7 @@ #include "nsILocalFile.h" #include "nsDirectoryServiceDefs.h" #include "nsAppDirectoryServiceDefs.h" +#include "nsThreadUtils.h" #include "nsVoidArray.h" #include "nsDeleteDir.h" #include // for log() @@ -105,7 +105,7 @@ public: virtual ~nsCacheProfilePrefObserver() {} nsresult Install(); - nsresult Remove(); + void Remove(); nsresult ReadPrefs(nsIPrefBranch* branch); PRBool DiskCacheEnabled(); @@ -189,46 +189,31 @@ nsCacheProfilePrefObserver::Install() } -nsresult +void nsCacheProfilePrefObserver::Remove() { - nsresult rv, rv2 = NS_OK; - // remove Observer Service observers - nsCOMPtr observerService = do_GetService("@mozilla.org/observer-service;1", &rv); - if (NS_FAILED(rv)) return rv; - - rv = observerService->RemoveObserver(this, "profile-before-change"); - if (NS_FAILED(rv)) rv2 = rv; - - rv = observerService->RemoveObserver(this, "profile-after-change"); - if (NS_FAILED(rv)) rv2 = rv; - - rv = observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); - if (NS_FAILED(rv)) rv2 = rv; - + nsCOMPtr obs = + do_GetService("@mozilla.org/observer-service;1"); + if (obs) { + obs->RemoveObserver(this, "profile-before-change"); + obs->RemoveObserver(this, "profile-after-change"); + obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); + } // remove Pref Service observers - nsCOMPtr prefInternal = do_GetService(NS_PREFSERVICE_CONTRACTID); + nsCOMPtr prefs = + do_GetService(NS_PREFSERVICE_CONTRACTID); + if (prefs) { + // remove Disk cache pref observers + prefs->RemoveObserver(DISK_CACHE_ENABLE_PREF, this); + prefs->RemoveObserver(DISK_CACHE_CAPACITY_PREF, this); + prefs->RemoveObserver(DISK_CACHE_DIR_PREF, this); - // remove Disk cache pref observers - rv = prefInternal->RemoveObserver(DISK_CACHE_ENABLE_PREF, this); - if (NS_FAILED(rv)) rv2 = rv; - - rv = prefInternal->RemoveObserver(DISK_CACHE_CAPACITY_PREF, this); - if (NS_FAILED(rv)) rv2 = rv; - - rv = prefInternal->RemoveObserver(DISK_CACHE_DIR_PREF, this); - if (NS_FAILED(rv)) rv2 = rv; - - // remove Memory cache pref observers - rv = prefInternal->RemoveObserver(MEMORY_CACHE_ENABLE_PREF, this); - if (NS_FAILED(rv)) rv2 = rv; - - rv = prefInternal->RemoveObserver(MEMORY_CACHE_CAPACITY_PREF, this); - // if (NS_FAILED(rv)) rv2 = rv; - - return NS_SUCCEEDED(rv) ? rv2 : rv; + // remove Memory cache pref observers + prefs->RemoveObserver(MEMORY_CACHE_ENABLE_PREF, this); + prefs->RemoveObserver(MEMORY_CACHE_CAPACITY_PREF, this); + } } @@ -532,13 +517,6 @@ nsCacheService::Init() nsresult rv = mActiveEntries.Init(); if (NS_FAILED(rv)) return rv; - // get references to services we'll be using frequently - mEventQService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) return rv; - - mProxyObjectManager = do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv); - if (NS_FAILED(rv)) return rv; - // create profile/preference observer mObserver = new nsCacheProfilePrefObserver(); if (!mObserver) return NS_ERROR_OUT_OF_MEMORY; @@ -651,9 +629,9 @@ nsCacheService::EvictEntriesForClient(const char * clientID, // notification happens before or after the actual eviction. nsCOMPtr obsProxy; - NS_GetProxyForObject(NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIObserverService), - obsSvc, PROXY_ASYNC, getter_AddRefs(obsProxy)); + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIObserverService), obsSvc, + NS_PROXY_ASYNC, getter_AddRefs(obsProxy)); if (obsProxy) { obsProxy->NotifyObservers(this, @@ -854,8 +832,8 @@ nsCacheService::CreateRequest(nsCacheSession * session, if (!listener) return NS_OK; // we're sync, we're done. - // get the nsIEventQueue for the request's thread - (*request)->mThread = PR_GetCurrentThread(); + // get the request's thread + (*request)->mThread = do_GetCurrentThread(); return NS_OK; } @@ -871,14 +849,12 @@ nsCacheService::NotifyListener(nsCacheRequest * request, nsCOMPtr listenerProxy; NS_ASSERTION(request->mThread, "no thread set in async request!"); - nsCOMPtr eventQ; - mEventQService->GetThreadEventQueue(request->mThread, - getter_AddRefs(eventQ)); - rv = mProxyObjectManager->GetProxyForObject(eventQ, - NS_GET_IID(nsICacheListener), - request->mListener, - PROXY_ASYNC|PROXY_ALWAYS, - getter_AddRefs(listenerProxy)); + + rv = NS_GetProxyForObject(request->mThread, + NS_GET_IID(nsICacheListener), + request->mListener, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, + getter_AddRefs(listenerProxy)); if (NS_FAILED(rv)) return rv; return listenerProxy->OnCacheEntryAvailable(descriptor, accessGranted, error); @@ -1178,45 +1154,6 @@ nsCacheService::DoomEntry_Internal(nsCacheEntry * entry) } -static void* PR_CALLBACK -EventHandler(PLEvent *self) -{ - nsISupports * object = (nsISupports *)PL_GetEventOwner(self); - NS_RELEASE(object); - return 0; -} - - -static void PR_CALLBACK -DestroyHandler(PLEvent *self) -{ - delete self; -} - - -void -nsCacheService::ProxyObjectRelease(nsISupports * object, PRThread * thread) -{ - NS_ASSERTION(gService, "nsCacheService not initialized"); - NS_ASSERTION(thread, "no thread"); - // XXX if thread == current thread, we could avoid posting an event, - // XXX by add this object to a queue and release it when the cache service is unlocked. - - nsCOMPtr eventQ; - gService->mEventQService->GetThreadEventQueue(thread, getter_AddRefs(eventQ)); - NS_ASSERTION(eventQ, "no event queue for thread"); - if (!eventQ) return; - - PLEvent * event = new PLEvent; - if (!event) { - NS_WARNING("failed to allocate a PLEvent."); - return; - } - PL_InitEvent(event, object, EventHandler, DestroyHandler); - eventQ->PostEvent(event); -} - - void nsCacheService::OnProfileShutdown(PRBool cleanse) { @@ -1413,7 +1350,7 @@ nsCacheService::ServiceLock() nsresult nsCacheService::SetCacheElement(nsCacheEntry * entry, nsISupports * element) { - entry->SetThread(PR_GetCurrentThread()); + entry->SetThread(); entry->SetData(element); entry->TouchData(); return NS_OK; diff --git a/mozilla/netwerk/cache/src/nsCacheService.h b/mozilla/netwerk/cache/src/nsCacheService.h index 4c7e4e3e6dd..c1eff46f341 100644 --- a/mozilla/netwerk/cache/src/nsCacheService.h +++ b/mozilla/netwerk/cache/src/nsCacheService.h @@ -52,7 +52,6 @@ #include "nspr.h" #include "nsIObserver.h" #include "nsString.h" -#include "nsIEventQueueService.h" #include "nsProxiedService.h" class nsCacheRequest; @@ -131,8 +130,6 @@ public: static nsresult DoomEntry(nsCacheEntry * entry); - static void ProxyObjectRelease(nsISupports * object, PRThread * thread); - static PRBool IsStorageEnabledForPolicy_Locked(nsCacheStoragePolicy policy); /** @@ -212,8 +209,6 @@ private: */ static nsCacheService * gService; // there can be only one... - nsCOMPtr mEventQService; - nsCOMPtr mProxyObjectManager; nsCacheProfilePrefObserver * mObserver; diff --git a/mozilla/netwerk/dns/public/nsIDNSService.idl b/mozilla/netwerk/dns/public/nsIDNSService.idl index 151f6b9a044..d7d5e135c2b 100644 --- a/mozilla/netwerk/dns/public/nsIDNSService.idl +++ b/mozilla/netwerk/dns/public/nsIDNSService.idl @@ -46,7 +46,7 @@ interface nsIDNSListener; /** * nsIDNSService */ -[scriptable, uuid(5c8ec09d-bfbf-4eaf-8a36-0d84b5c8f35b)] +[scriptable, uuid(3ac9e611-e6b6-44b5-b312-c040e65b2929)] interface nsIDNSService : nsISupports { /** @@ -58,19 +58,19 @@ interface nsIDNSService : nsISupports * a bitwise OR of the RESOLVE_ prefixed constants defined below. * @param aListener * the listener to be notified when the result is available. - * @param aListenerEventTarget + * @param aListenerTarget * optional parameter (may be null). if non-null, this parameter - * specifies the nsIEventTarget of the thread on which the listener's - * onLookupComplete should be called. however, if this parameter is - * null, then onLookupComplete will be called on an unspecified - * thread (possibly recursively). + * specifies the nsIEventTarget of the thread on which the + * listener's onLookupComplete should be called. however, if this + * parameter is null, then onLookupComplete will be called on an + * unspecified thread (possibly recursively). * * @return An object that can be used to cancel the host lookup. */ - nsICancelable asyncResolve(in AUTF8String aHostName, - in unsigned long aFlags, - in nsIDNSListener aListener, - in nsIEventTarget aListenerEventTarget); + nsICancelable asyncResolve(in AUTF8String aHostName, + in unsigned long aFlags, + in nsIDNSListener aListener, + in nsIEventTarget aListenerTarget); /** * called to synchronously resolve a hostname. warning this method may diff --git a/mozilla/netwerk/dns/src/nsDNSService2.cpp b/mozilla/netwerk/dns/src/nsDNSService2.cpp index c6aaefcaff1..d11292479aa 100644 --- a/mozilla/netwerk/dns/src/nsDNSService2.cpp +++ b/mozilla/netwerk/dns/src/nsDNSService2.cpp @@ -326,11 +326,13 @@ nsDNSService::Init() return NS_ERROR_OUT_OF_MEMORY; // register as prefs observer - prefs->AddObserver(kPrefDnsCacheEntries, this, PR_FALSE); - prefs->AddObserver(kPrefDnsCacheExpiration, this, PR_FALSE); - prefs->AddObserver(kPrefEnableIDN, this, PR_FALSE); - prefs->AddObserver(kPrefIPv4OnlyDomains, this, PR_FALSE); - prefs->AddObserver(kPrefDisableIPv6, this, PR_FALSE); + if (prefs) { + prefs->AddObserver(kPrefDnsCacheEntries, this, PR_FALSE); + prefs->AddObserver(kPrefDnsCacheExpiration, this, PR_FALSE); + prefs->AddObserver(kPrefEnableIDN, this, PR_FALSE); + prefs->AddObserver(kPrefIPv4OnlyDomains, this, PR_FALSE); + prefs->AddObserver(kPrefDisableIPv6, this, PR_FALSE); + } } // we have to null out mIDN since we might be getting re-initialized @@ -370,11 +372,11 @@ nsDNSService::Shutdown() } NS_IMETHODIMP -nsDNSService::AsyncResolve(const nsACString &hostname, - PRUint32 flags, - nsIDNSListener *listener, - nsIEventTarget *eventTarget, - nsICancelable **result) +nsDNSService::AsyncResolve(const nsACString &hostname, + PRUint32 flags, + nsIDNSListener *listener, + nsIEventTarget *target, + nsICancelable **result) { // grab reference to global host resolver and IDN service. beware // simultaneous shutdown!! @@ -397,13 +399,11 @@ nsDNSService::AsyncResolve(const nsACString &hostname, } nsCOMPtr listenerProxy; - nsCOMPtr eventQ = do_QueryInterface(eventTarget); - // TODO(darin): make XPCOM proxies support any nsIEventTarget impl - if (eventQ) { - rv = NS_GetProxyForObject(eventQ, + if (target) { + rv = NS_GetProxyForObject(target, NS_GET_IID(nsIDNSListener), listener, - PROXY_ASYNC | PROXY_ALWAYS, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, getter_AddRefs(listenerProxy)); if (NS_FAILED(rv)) return rv; listener = listenerProxy; diff --git a/mozilla/netwerk/protocol/about/public/nsIAboutModule.idl b/mozilla/netwerk/protocol/about/public/nsIAboutModule.idl index 536cdcc1d2d..53c496e7edc 100644 --- a/mozilla/netwerk/protocol/about/public/nsIAboutModule.idl +++ b/mozilla/netwerk/protocol/about/public/nsIAboutModule.idl @@ -36,12 +36,9 @@ * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" -#include "nsIChannel.idl" interface nsIURI; -interface nsILoadGroup; -interface nsIInterfaceRequestor; -interface nsIEventQueue; +interface nsIChannel; [scriptable, uuid(692303c0-2f83-11d3-8cd0-0060b0fc14a3)] interface nsIAboutModule : nsISupports diff --git a/mozilla/netwerk/protocol/file/src/nsFileChannel.cpp b/mozilla/netwerk/protocol/file/src/nsFileChannel.cpp index f613b1745cf..b82caef39d3 100644 --- a/mozilla/netwerk/protocol/file/src/nsFileChannel.cpp +++ b/mozilla/netwerk/protocol/file/src/nsFileChannel.cpp @@ -40,7 +40,7 @@ #include "nsFileChannel.h" #include "nsBaseContentStream.h" #include "nsDirectoryIndexStream.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsTransportUtils.h" #include "nsStreamUtils.h" #include "nsURLHelper.h" @@ -54,7 +54,7 @@ //----------------------------------------------------------------------------- -class nsFileCopyEvent : public PLEvent { +class nsFileCopyEvent : public nsRunnable { public: nsFileCopyEvent(nsIOutputStream *dest, nsIInputStream *source, PRInt64 len) : mDest(dest) @@ -62,7 +62,6 @@ public: , mLen(len) , mStatus(NS_OK) , mInterruptStatus(NS_OK) { - PL_InitEvent(this, nsnull, HandleEvent, DestroyEvent); } // Read the current status of the file copy operation. @@ -85,18 +84,12 @@ public: mInterruptStatus = status; } + NS_IMETHOD Run() { + DoCopy(); + return NS_OK; + } + private: - - PR_STATIC_CALLBACK(void *) HandleEvent(PLEvent *ev) { - nsFileCopyEvent *f = NS_STATIC_CAST(nsFileCopyEvent *, ev); - f->DoCopy(); - return nsnull; - } - - PR_STATIC_CALLBACK(void) DestroyEvent(PLEvent *ev) { - // nothing to do - } - nsCOMPtr mCallback; nsCOMPtr mSink; nsCOMPtr mDest; @@ -151,8 +144,10 @@ nsFileCopyEvent::DoCopy() mDest->Close(); // Notify completion - if (mCallback) + if (mCallback) { mCallback->OnOutputStreamReady(nsnull); + mCallback = nsnull; + } } nsresult @@ -173,15 +168,13 @@ nsFileCopyEvent::Dispatch(nsIOutputStreamCallback *callback, if (NS_FAILED(rv)) return rv; - // PostEvent to I/O thread... + // Dispatch ourselves to I/O thread pool... nsCOMPtr pool = - do_GetService(NS_IOTHREADPOOL_CONTRACTID, &rv); + do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; - // We don't have to call PL_DestroyEvent here if PostEvent fails because of - // the way we are allocated. - return pool->PostEvent(this); + return pool->Dispatch(this, NS_DISPATCH_NORMAL); } //----------------------------------------------------------------------------- @@ -201,17 +194,21 @@ public: PRInt64 len, nsITransportEventSink *sink) : nsBaseContentStream(nonBlocking) - , mCopyEvent(dest, source, len) + , mCopyEvent(new nsFileCopyEvent(dest, source, len)) , mSink(sink) { } + PRBool IsInitialized() { + return mCopyEvent != nsnull; + } + NS_IMETHODIMP ReadSegments(nsWriteSegmentFun fun, void *closure, PRUint32 count, PRUint32 *result); NS_IMETHODIMP AsyncWait(nsIInputStreamCallback *callback, PRUint32 flags, PRUint32 count, nsIEventTarget *target); private: - nsFileCopyEvent mCopyEvent; + nsRefPtr mCopyEvent; nsCOMPtr mSink; }; @@ -236,8 +233,8 @@ nsFileUploadContentStream::ReadSegments(nsWriteSegmentFun fun, void *closure, } // Perform copy synchronously, and then close out the stream. - mCopyEvent.DoCopy(); - nsresult status = mCopyEvent.Status(); + mCopyEvent->DoCopy(); + nsresult status = mCopyEvent->Status(); CloseWithStatus(NS_FAILED(status) ? status : NS_BASE_STREAM_CLOSED); return status; } @@ -252,7 +249,7 @@ nsFileUploadContentStream::AsyncWait(nsIInputStreamCallback *callback, return rv; if (IsNonBlocking()) - mCopyEvent.Dispatch(this, mSink, target); + mCopyEvent->Dispatch(this, mSink, target); return NS_OK; } @@ -261,7 +258,7 @@ NS_IMETHODIMP nsFileUploadContentStream::OnOutputStreamReady(nsIAsyncOutputStream *unused) { // This method is being called to indicate that we are done copying. - nsresult status = mCopyEvent.Status(); + nsresult status = mCopyEvent->Status(); CloseWithStatus(NS_FAILED(status) ? status : NS_BASE_STREAM_CLOSED); return NS_OK; @@ -325,10 +322,12 @@ nsFileChannel::OpenContentStream(PRBool async, nsIInputStream **result) if (NS_FAILED(rv)) return rv; - stream = new nsFileUploadContentStream(async, fileStream, mUploadStream, - mUploadLength, this); - if (!stream) + nsFileUploadContentStream *uploadStream = + new nsFileUploadContentStream(async, fileStream, mUploadStream, + mUploadLength, this); + if (!uploadStream || !uploadStream->IsInitialized()) return NS_ERROR_OUT_OF_MEMORY; + stream = uploadStream; SetContentLength64(0); diff --git a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp index 470cbc7a6d6..8cf9c27e5e8 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp @@ -41,6 +41,7 @@ #include "nsIStreamListener.h" #include "nsIServiceManager.h" +#include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsMimeTypes.h" #include "nsIProxyObjectManager.h" @@ -175,12 +176,13 @@ nsFtpChannel::GetFTPEventSink(nsCOMPtr &aResult) if (!mFTPEventSink) { nsCOMPtr ftpSink; GetCallback(ftpSink); - if (ftpSink) - NS_GetProxyForObject(NS_CURRENT_EVENTQ, + if (ftpSink) { + NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, NS_GET_IID(nsIFTPEventSink), ftpSink, - PROXY_ASYNC | PROXY_ALWAYS, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, getter_AddRefs(mFTPEventSink)); + } } aResult = mFTPEventSink; } diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp index a89d0e865f1..bac3c4548a2 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp @@ -56,7 +56,7 @@ #include "nsEscape.h" #include "nsMimeTypes.h" #include "nsNetUtil.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsStreamUtils.h" #include "nsIURL.h" #include "nsISocketTransport.h" @@ -1445,11 +1445,7 @@ nsFtpState::R_pasv() { LOG(("FTP:(%x) created DT (%s:%x)\n", this, hostStr, port)); // hook ourself up as a proxy for status notifications - nsCOMPtr eventQ; - rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - NS_ENSURE_SUCCESS(rv, FTP_ERROR); - - rv = mDataTransport->SetEventSink(this, eventQ); + rv = mDataTransport->SetEventSink(this, NS_GetCurrentThread()); NS_ENSURE_SUCCESS(rv, FTP_ERROR); if (mAction == PUT) { @@ -1623,11 +1619,7 @@ nsFtpState::OpenCacheDataStream() getter_AddRefs(transport)); NS_ENSURE_STATE(transport); - nsCOMPtr eventQ; - NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - NS_ENSURE_STATE(eventQ); - - nsresult rv = transport->SetEventSink(this, eventQ); + nsresult rv = transport->SetEventSink(this, NS_GetCurrentThread()); NS_ENSURE_SUCCESS(rv, rv); // Open a non-blocking, buffered input stream... diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h index 31c20318b53..b650a3169a3 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h @@ -61,7 +61,6 @@ #include "nsIOutputStream.h" #include "nsAutoLock.h" #include "nsAutoPtr.h" -#include "nsIEventQueueService.h" #include "nsIPrompt.h" #include "nsIAuthPrompt.h" #include "nsITransport.h" diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpControlConnection.cpp b/mozilla/netwerk/protocol/ftp/src/nsFtpControlConnection.cpp index cf16e12367c..15c7c458901 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpControlConnection.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpControlConnection.cpp @@ -44,7 +44,7 @@ #include "nsISocketTransportService.h" #include "nsISocketTransport.h" #include "nsNetUtil.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsCRT.h" #if defined(PR_LOGGING) @@ -136,12 +136,8 @@ nsFtpControlConnection::Connect(nsIProxyInfo* proxyInfo, return rv; // proxy transport events back to current thread - if (eventSink) { - nsCOMPtr eventQ; - rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - if (NS_SUCCEEDED(rv)) - mSocket->SetEventSink(eventSink, eventQ); - } + if (eventSink) + mSocket->SetEventSink(eventSink, NS_GetCurrentThread()); // open buffered, blocking output stream to socket. so long as commands // do not exceed 1024 bytes in length, the writing thread (the main thread) @@ -177,12 +173,8 @@ nsFtpControlConnection::WaitData(nsFtpControlConnectionListener *listener) NS_ENSURE_STATE(mSocketInput); - nsCOMPtr eventQ; - NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - NS_ENSURE_STATE(eventQ); - mListener = listener; - return mSocketInput->AsyncWait(this, 0, 0, eventQ); + return mSocketInput->AsyncWait(this, 0, 0, NS_GetCurrentThread()); } nsresult diff --git a/mozilla/netwerk/protocol/gopher/src/nsGopherChannel.cpp b/mozilla/netwerk/protocol/gopher/src/nsGopherChannel.cpp index 1e90f11b861..f03dcf5cd16 100644 --- a/mozilla/netwerk/protocol/gopher/src/nsGopherChannel.cpp +++ b/mozilla/netwerk/protocol/gopher/src/nsGopherChannel.cpp @@ -49,7 +49,8 @@ #include "nsIStringBundle.h" #include "nsITXTToHTMLConv.h" #include "nsIPrompt.h" -#include "nsEventQueueUtils.h" +#include "nsServiceManagerUtils.h" +#include "nsThreadUtils.h" #include "nsStreamUtils.h" #include "nsMimeTypes.h" #include "nsNetCID.h" diff --git a/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp b/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp index 59142e3da79..309e6217a90 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -240,48 +240,8 @@ nsHttpChannel::Init(nsIURI *uri, nsresult nsHttpChannel::AsyncCall(nsAsyncCallback funcPtr) { - nsresult rv; - - nsAsyncCallEvent *event = new nsAsyncCallEvent; - if (!event) - return NS_ERROR_OUT_OF_MEMORY; - - event->mFuncPtr = funcPtr; - - NS_ADDREF_THIS(); - - PL_InitEvent(event, this, - nsHttpChannel::AsyncCall_EventHandlerFunc, - nsHttpChannel::AsyncCall_EventCleanupFunc); - - rv = mEventQ->PostEvent(event); - if (NS_FAILED(rv)) { - PL_DestroyEvent(event); - NS_RELEASE_THIS(); - } - return rv; -} - -void *PR_CALLBACK -nsHttpChannel::AsyncCall_EventHandlerFunc(PLEvent *ev) -{ - nsHttpChannel *chan = - NS_STATIC_CAST(nsHttpChannel *, PL_GetEventOwner(ev)); - - nsAsyncCallEvent *ace = (nsAsyncCallEvent *) ev; - nsAsyncCallback funcPtr = ace->mFuncPtr; - - if (chan) { - (chan->*funcPtr)(); - NS_RELEASE(chan); - } - return nsnull; -} - -void PR_CALLBACK -nsHttpChannel::AsyncCall_EventCleanupFunc(PLEvent *ev) -{ - delete (nsAsyncCallEvent *) ev; + nsCOMPtr event = NS_NewRunnableMethod(this, funcPtr); + return NS_DispatchToCurrentThread(event); } nsresult @@ -375,7 +335,8 @@ nsHttpChannel::AsyncAbort(nsresult status) // create a proxy for the listener.. nsCOMPtr observer; - NS_NewRequestObserverProxy(getter_AddRefs(observer), mListener, mEventQ); + NS_NewRequestObserverProxy(getter_AddRefs(observer), mListener, + NS_GetCurrentThread()); if (observer) { observer->OnStartRequest(this, mListenerContext); observer->OnStopRequest(this, mListenerContext, mStatus); @@ -594,7 +555,7 @@ nsHttpChannel::SetupTransaction() nsCOMPtr responseStream; rv = mTransaction->Init(mCaps, mConnectionInfo, &mRequestHead, mUploadStream, mUploadStreamHasHeaders, - mEventQ, callbacks, this, + NS_GetCurrentThread(), callbacks, this, getter_AddRefs(responseStream)); if (NS_FAILED(rv)) return rv; @@ -3312,14 +3273,6 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context) nsresult rv; - // we want to grab a reference to the calling thread's event queue at - // this point. we will proxy all events back to the current thread via - // this event queue. - if (!mEventQ) { - rv = gHttpHandler->GetCurrentEventQ(getter_AddRefs(mEventQ)); - if (NS_FAILED(rv)) return rv; - } - PRInt32 port; rv = mURI->GetPort(&port); if (NS_FAILED(rv)) @@ -4099,7 +4052,6 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st mCallbacks = nsnull; mProgressSink = nsnull; - mEventQ = nsnull; return NS_OK; } diff --git a/mozilla/netwerk/protocol/http/src/nsHttpChannel.h b/mozilla/netwerk/protocol/http/src/nsHttpChannel.h index 1e56cb0bb95..cec7bc09f3b 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpChannel.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpChannel.h @@ -44,14 +44,14 @@ #include "nsHttpTransaction.h" #include "nsHttpRequestHead.h" #include "nsHttpAuthCache.h" +#include "nsHashPropertyBag.h" #include "nsInputStreamPump.h" -#include "nsXPIDLString.h" +#include "nsThreadUtils.h" +#include "nsString.h" #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsInt64.h" -#include "nsHashPropertyBag.h" - #include "nsIHttpChannel.h" #include "nsIHttpChannelInternal.h" #include "nsIHttpHeaderVisitor.h" @@ -140,14 +140,7 @@ private: getter_AddRefs(aResult)); } - // // AsyncCall may be used to call a member function asynchronously. - // - struct nsAsyncCallEvent : PLEvent - { - nsAsyncCallback mFuncPtr; - }; - nsresult AsyncCall(nsAsyncCallback funcPtr); nsresult Connect(PRBool firstTime = PR_TRUE); @@ -208,9 +201,6 @@ private: void ClearPasswordManagerEntry(const char *scheme, const char *host, PRInt32 port, const char *realm, const PRUnichar *user); nsresult DoAuthRetry(nsAHttpConnection *); - static void *PR_CALLBACK AsyncCall_EventHandlerFunc(PLEvent *); - static void PR_CALLBACK AsyncCall_EventCleanupFunc(PLEvent *); - private: nsCOMPtr mOriginalURI; nsCOMPtr mURI; @@ -224,7 +214,6 @@ private: nsCOMPtr mUploadStream; nsCOMPtr mReferrer; nsCOMPtr mSecurityInfo; - nsCOMPtr mEventQ; nsCOMPtr mProxyRequest; nsHttpRequestHead mRequestHead; diff --git a/mozilla/netwerk/protocol/http/src/nsHttpConnection.cpp b/mozilla/netwerk/protocol/http/src/nsHttpConnection.cpp index dfa3d6c6bef..0d844aa53ed 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpConnection.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpConnection.cpp @@ -51,7 +51,6 @@ #include "nsNetCID.h" #include "nsAutoLock.h" #include "prmem.h" -#include "plevent.h" #ifdef DEBUG // defined by the socket transport service while active diff --git a/mozilla/netwerk/protocol/http/src/nsHttpConnection.h b/mozilla/netwerk/protocol/http/src/nsHttpConnection.h index df0f2e2ed24..98cd848c776 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpConnection.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpConnection.h @@ -49,7 +49,6 @@ #include "nsIStreamListener.h" #include "nsISocketTransport.h" -#include "nsIEventTarget.h" #include "nsIAsyncInputStream.h" #include "nsIAsyncOutputStream.h" #include "nsIInterfaceRequestor.h" diff --git a/mozilla/netwerk/protocol/http/src/nsHttpConnectionMgr.cpp b/mozilla/netwerk/protocol/http/src/nsHttpConnectionMgr.cpp index b3739ae1339..2dc38483c0c 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpConnectionMgr.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpConnectionMgr.cpp @@ -112,7 +112,7 @@ nsHttpConnectionMgr::Init(PRUint16 maxConns, nsAutoMonitor mon(mMonitor); // do nothing if already initialized - if (mSTEventTarget) + if (mSocketThreadTarget) return NS_OK; // no need to do any special synchronization here since there cannot be @@ -125,7 +125,7 @@ nsHttpConnectionMgr::Init(PRUint16 maxConns, mMaxRequestDelay = maxRequestDelay; mMaxPipelinedRequests = maxPipelinedRequests; - mSTEventTarget = sts; + mSocketThreadTarget = sts; return rv; } @@ -137,7 +137,7 @@ nsHttpConnectionMgr::Shutdown() nsAutoMonitor mon(mMonitor); // do nothing if already shutdown - if (!mSTEventTarget) + if (!mSocketThreadTarget) return NS_OK; nsresult rv = PostEvent(&nsHttpConnectionMgr::OnMsgShutdown); @@ -145,7 +145,7 @@ nsHttpConnectionMgr::Shutdown() // release our reference to the STS to prevent further events // from being posted. this is how we indicate that we are // shutting down. - mSTEventTarget = 0; + mSocketThreadTarget = 0; if (NS_FAILED(rv)) { NS_WARNING("unable to post SHUTDOWN message\n"); @@ -163,19 +163,16 @@ nsHttpConnectionMgr::PostEvent(nsConnEventHandler handler, PRInt32 iparam, void nsAutoMonitor mon(mMonitor); nsresult rv; - if (!mSTEventTarget) { + if (!mSocketThreadTarget) { NS_WARNING("cannot post event if not initialized"); rv = NS_ERROR_NOT_INITIALIZED; } else { - PLEvent *event = new nsConnEvent(this, handler, iparam, vparam); + nsRefPtr event = new nsConnEvent(this, handler, iparam, vparam); if (!event) rv = NS_ERROR_OUT_OF_MEMORY; - else { - rv = mSTEventTarget->PostEvent(event); - if (NS_FAILED(rv)) - PL_DestroyEvent(event); - } + else + rv = mSocketThreadTarget->Dispatch(event, NS_DISPATCH_NORMAL); } return rv; } @@ -225,10 +222,10 @@ nsHttpConnectionMgr::PruneDeadConnections() } nsresult -nsHttpConnectionMgr::GetSocketThreadEventTarget(nsIEventTarget **target) +nsHttpConnectionMgr::GetSocketThreadTarget(nsIEventTarget **target) { nsAutoMonitor mon(mMonitor); - NS_IF_ADDREF(*target = mSTEventTarget); + NS_IF_ADDREF(*target = mSocketThreadTarget); return NS_OK; } diff --git a/mozilla/netwerk/protocol/http/src/nsHttpConnectionMgr.h b/mozilla/netwerk/protocol/http/src/nsHttpConnectionMgr.h index 50bdd154b1f..922033222e3 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpConnectionMgr.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpConnectionMgr.h @@ -43,11 +43,11 @@ #include "nsHttpConnection.h" #include "nsHttpTransaction.h" #include "nsVoidArray.h" +#include "nsThreadUtils.h" #include "nsHashtable.h" +#include "nsAutoPtr.h" #include "prmon.h" -#include "nsIEventTarget.h" - class nsHttpPipeline; //----------------------------------------------------------------------------- @@ -115,7 +115,7 @@ public: // called to get a reference to the socket transport service. the socket // transport service is not available when the connection manager is down. - nsresult GetSocketThreadEventTarget(nsIEventTarget **); + nsresult GetSocketThreadTarget(nsIEventTarget **); // called when a connection is done processing a transaction. if the // connection can be reused then it will be added to the idle list, else @@ -187,9 +187,9 @@ private: // NOTE: these members may be accessed from any thread (use mMonitor) //------------------------------------------------------------------------- - PRInt32 mRef; - PRMonitor *mMonitor; - nsCOMPtr mSTEventTarget; // event target for socket thread + PRInt32 mRef; + PRMonitor *mMonitor; + nsCOMPtr mSocketThreadTarget; // connection limits PRUint16 mMaxConns; @@ -222,44 +222,35 @@ private: // nsConnEvent // - // subclass of PLEvent used to marshall events to the socket transport + // subclass of nsRunnable used to marshall events to the socket transport // thread. this class is used to implement PostEvent. // class nsConnEvent; friend class nsConnEvent; - class nsConnEvent : public PLEvent + class nsConnEvent : public nsRunnable { public: nsConnEvent(nsHttpConnectionMgr *mgr, nsConnEventHandler handler, PRInt32 iparam, void *vparam) - : mHandler(handler) + : mMgr(mgr) + , mHandler(handler) , mIParam(iparam) , mVParam(vparam) - { - NS_ADDREF(mgr); - PL_InitEvent(this, mgr, HandleEvent, DestroyEvent); - } + {} - PR_STATIC_CALLBACK(void*) HandleEvent(PLEvent *event) + NS_IMETHOD Run() { - nsHttpConnectionMgr *mgr = (nsHttpConnectionMgr *) event->owner; - nsConnEvent *self = (nsConnEvent *) event; - nsConnEventHandler handler = self->mHandler; - (mgr->*handler)(self->mIParam, self->mVParam); - NS_RELEASE(mgr); - return nsnull; - } - PR_STATIC_CALLBACK(void) DestroyEvent(PLEvent *event) - { - delete (nsConnEvent *) event; + (mMgr->*mHandler)(mIParam, mVParam); + return NS_OK; } private: - nsConnEventHandler mHandler; - PRInt32 mIParam; - void *mVParam; + nsRefPtr mMgr; + nsConnEventHandler mHandler; + PRInt32 mIParam; + void *mVParam; }; nsresult PostEvent(nsConnEventHandler handler, diff --git a/mozilla/netwerk/protocol/http/src/nsHttpHandler.cpp b/mozilla/netwerk/protocol/http/src/nsHttpHandler.cpp index a619bbe52c6..b7a9ca193ed 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpHandler.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpHandler.cpp @@ -92,7 +92,6 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID); static NS_DEFINE_CID(kCookieServiceCID, NS_COOKIESERVICE_CID); static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kSocketProviderServiceCID, NS_SOCKETPROVIDERSERVICE_CID); #define UA_PREF_PREFIX "general.useragent." @@ -434,17 +433,6 @@ nsHttpHandler::GetCacheSession(nsCacheStoragePolicy storagePolicy, return NS_OK; } -nsresult -nsHttpHandler::GetCurrentEventQ(nsIEventQueue **result) -{ - if (!mEventQueueService) { - nsresult rv; - mEventQueueService = do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - } - return mEventQueueService->ResolveEventQueue(NS_CURRENT_EVENTQ, result); -} - nsresult nsHttpHandler::GetStreamConverterService(nsIStreamConverterService **result) { diff --git a/mozilla/netwerk/protocol/http/src/nsHttpHandler.h b/mozilla/netwerk/protocol/http/src/nsHttpHandler.h index 882a61b874b..1cd8a0117a4 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpHandler.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpHandler.h @@ -58,7 +58,6 @@ #include "nsIProxyObjectManager.h" #include "nsIStreamConverterService.h" #include "nsICacheSession.h" -#include "nsIEventQueueService.h" #include "nsICookieService.h" #include "nsIIDNService.h" #include "nsITimer.h" @@ -161,16 +160,15 @@ public: return mConnMgr->ProcessPendingQ(cinfo); } - nsresult GetSocketThreadEventTarget(nsIEventTarget **target) + nsresult GetSocketThreadTarget(nsIEventTarget **target) { - return mConnMgr->GetSocketThreadEventTarget(target); + return mConnMgr->GetSocketThreadTarget(target); } // // The HTTP handler caches pointers to specific XPCOM services, and // provides the following helper routines for accessing those services: // - nsresult GetCurrentEventQ(nsIEventQueue **); nsresult GetStreamConverterService(nsIStreamConverterService **); nsresult GetIOService(nsIIOService** service); nsICookieService * GetCookieService(); // not addrefed @@ -221,7 +219,6 @@ private: // cached services nsCOMPtr mIOService; - nsCOMPtr mEventQueueService; nsCOMPtr mStreamConvSvc; nsCOMPtr mObserverService; nsCOMPtr mCookieService; diff --git a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp index 64dd8b375ed..0c4d3e375f0 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp @@ -46,11 +46,11 @@ #include "nsHttpChunkedDecoder.h" #include "nsNetSegmentUtils.h" #include "nsTransportUtils.h" +#include "nsProxyRelease.h" #include "nsIOService.h" #include "nsNetUtil.h" #include "nsAutoLock.h" #include "pratom.h" -#include "plevent.h" #include "nsISeekableStream.h" #include "nsISocketTransport.h" @@ -132,7 +132,6 @@ nsHttpTransaction::nsHttpTransaction() , mRestartCount(0) , mCaps(0) , mClosed(PR_FALSE) - , mDestroying(PR_FALSE) , mConnected(PR_FALSE) , mHaveStatusLine(PR_FALSE) , mHaveAllHeaders(PR_FALSE) @@ -166,7 +165,7 @@ nsHttpTransaction::Init(PRUint8 caps, nsHttpRequestHead *requestHead, nsIInputStream *requestBody, PRBool requestBodyHasHeaders, - nsIEventQueue *queue, + nsIEventTarget *target, nsIInterfaceRequestor *callbacks, nsITransportEventSink *eventsink, nsIAsyncInputStream **responseBody) @@ -177,16 +176,16 @@ nsHttpTransaction::Init(PRUint8 caps, NS_ASSERTION(cinfo, "ouch"); NS_ASSERTION(requestHead, "ouch"); - NS_ASSERTION(queue, "ouch"); + NS_ASSERTION(target, "ouch"); // create transport event sink proxy that coalesces all events rv = net_NewTransportEventSinkProxy(getter_AddRefs(mTransportSink), - eventsink, queue, PR_TRUE); + eventsink, target, PR_TRUE); if (NS_FAILED(rv)) return rv; NS_ADDREF(mConnInfo = cinfo); mCallbacks = callbacks; - mConsumerEventQ = queue; + mConsumerTarget = target; mCaps = caps; if (requestHead->Method() == nsHttp::Head) @@ -394,7 +393,7 @@ nsHttpTransaction::ReadSegments(nsAHttpSegmentReader *reader, do_QueryInterface(mRequestStream); if (asyncIn) { nsCOMPtr target; - gHttpHandler->GetSocketThreadEventTarget(getter_AddRefs(target)); + gHttpHandler->GetSocketThreadTarget(getter_AddRefs(target)); if (target) asyncIn->AsyncWait(this, 0, 0, target); else { @@ -458,7 +457,7 @@ nsHttpTransaction::WriteSegments(nsAHttpSegmentWriter *writer, // occur on socket thread so we stay synchronized. if (rv == NS_BASE_STREAM_WOULD_BLOCK) { nsCOMPtr target; - gHttpHandler->GetSocketThreadEventTarget(getter_AddRefs(target)); + gHttpHandler->GetSocketThreadTarget(getter_AddRefs(target)); if (target) mPipeOut->AsyncWait(this, 0, 0, target); else { @@ -938,54 +937,18 @@ nsHttpTransaction::ProcessData(char *buf, PRUint32 count, PRUint32 *countRead) void nsHttpTransaction::DeleteSelfOnConsumerThread() { - nsCOMPtr eqs; - nsCOMPtr currentEventQ; - LOG(("nsHttpTransaction::DeleteSelfOnConsumerThread [this=%x]\n", this)); - NS_ASSERTION(!mDestroying, "deleting self again"); - mDestroying = PR_TRUE; - - gHttpHandler->GetCurrentEventQ(getter_AddRefs(currentEventQ)); - - if (currentEventQ == mConsumerEventQ) + PRBool val; + if (NS_SUCCEEDED(mConsumerTarget->IsOnCurrentThread(&val)) && val) delete this; else { LOG(("proxying delete to consumer thread...\n")); - - PLEvent *event = new PLEvent; - if (!event) { - NS_WARNING("out of memory"); - // probably better to leak |this| than to delete it on this thread. - return; - } - - PL_InitEvent(event, this, DeleteThis_Handler, DeleteThis_Cleanup); - - nsresult status = mConsumerEventQ->PostEvent(event); - if (NS_FAILED(status)) - NS_ERROR("PostEvent failed"); + NS_ProxyRelease(mConsumerTarget, + NS_STATIC_CAST(nsIInputStreamCallback *, this)); } } -void *PR_CALLBACK -nsHttpTransaction::DeleteThis_Handler(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_Cleanup(PLEvent *ev) -{ - delete ev; -} - //----------------------------------------------------------------------------- // nsHttpTransaction::nsISupports //----------------------------------------------------------------------------- diff --git a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h index 7c3289e33ee..c57f13ad727 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h @@ -52,7 +52,7 @@ #include "nsIInterfaceRequestor.h" #include "nsISocketTransportService.h" #include "nsITransport.h" -#include "nsIEventQueue.h" +#include "nsIEventTarget.h" //----------------------------------------------------------------------------- @@ -92,8 +92,8 @@ public: // the request body (POST or PUT data stream) // @param reqBodyIncludesHeaders // fun stuff to support NPAPI plugins. - // @param eventQ - // the event queue were notifications should be sent. + // @param target + // the dispatch target were notifications should be sent. // @param callbacks // the notification callbacks to be given to PSM. // @param responseBody @@ -106,7 +106,7 @@ public: nsHttpRequestHead *reqHeaders, nsIInputStream *reqBody, PRBool reqBodyIncludesHeaders, - nsIEventQueue *consumerEventQ, + nsIEventTarget *consumerTarget, nsIInterfaceRequestor *callbacks, nsITransportEventSink *eventsink, nsIAsyncInputStream **responseBody); @@ -119,7 +119,7 @@ public: nsISupports *SecurityInfo() { return mSecurityInfo; } nsIInterfaceRequestor *Callbacks() { return mCallbacks; } - nsIEventQueue *ConsumerEventQ() { return mConsumerEventQ; } + nsIEventTarget *ConsumerTarget() { return mConsumerTarget; } nsAHttpConnection *Connection() { return mConnection; } // Called to take ownership of the response headers; the transaction @@ -146,11 +146,6 @@ private: nsresult ProcessData(char *, PRUint32, PRUint32 *); void DeleteSelfOnConsumerThread(); - static void *PR_CALLBACK TransportStatus_Handler(PLEvent *); - static void PR_CALLBACK TransportStatus_Cleanup(PLEvent *); - static void *PR_CALLBACK DeleteThis_Handler(PLEvent *); - static void PR_CALLBACK DeleteThis_Cleanup(PLEvent *); - static NS_METHOD ReadRequestSegment(nsIInputStream *, void *, const char *, PRUint32, PRUint32, PRUint32 *); static NS_METHOD WritePipeSegment(nsIOutputStream *, void *, char *, @@ -159,7 +154,7 @@ private: private: nsCOMPtr mCallbacks; nsCOMPtr mTransportSink; - nsCOMPtr mConsumerEventQ; + nsCOMPtr mConsumerTarget; nsCOMPtr mSecurityInfo; nsCOMPtr mPipeIn; nsCOMPtr mPipeOut; @@ -192,7 +187,6 @@ private: // state flags PRUint32 mClosed : 1; - PRUint32 mDestroying : 1; PRUint32 mConnected : 1; PRUint32 mHaveStatusLine : 1; PRUint32 mHaveAllHeaders : 1; diff --git a/mozilla/netwerk/streamconv/test/TestStreamConv.cpp b/mozilla/netwerk/streamconv/test/TestStreamConv.cpp index ffc27e00c13..1ced7e806ed 100644 --- a/mozilla/netwerk/streamconv/test/TestStreamConv.cpp +++ b/mozilla/netwerk/streamconv/test/TestStreamConv.cpp @@ -45,6 +45,7 @@ #include "nsIStringStream.h" #include "nsCOMPtr.h" #include "nsNetUtil.h" +#include "nsThreadUtils.h" #include "nspr.h" @@ -53,7 +54,6 @@ ///////////////////////////////// // Event pump setup ///////////////////////////////// -#include "nsIEventQueueService.h" #ifdef XP_WIN #include #endif @@ -62,7 +62,6 @@ #endif static int gKeepRunning = 0; -static nsIEventQueue* gEventQ = nsnull; ///////////////////////////////// // Event pump END ///////////////////////////////// @@ -74,7 +73,6 @@ static nsIEventQueue* gEventQ = nsnull; #include "Converters.h" // CID setup -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID); //////////////////////////////////////////////////////////////////////// @@ -153,12 +151,7 @@ main(int argc, char* argv[]) if (registrar) registrar->AutoRegister(nsnull); - // Create the Event Queue for this thread... - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); + nsCOMPtr thread = do_GetCurrentThread(); nsCOMPtr catman = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv); @@ -281,10 +274,8 @@ main(int argc, char* argv[]) // Enter the message pump to allow the URL load to proceed. while ( gKeepRunning ) { - PLEvent *gEvent; - gEventQ->WaitForEvent(&gEvent); - gEventQ->HandleEvent(gEvent); - /* gKeepRunning = PR_FALSE; */ + if (!NS_ProcessNextEvent(thread)) + break; } } // this scopes the nsCOMPtrs // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM diff --git a/mozilla/netwerk/system/win32/nsNotifyAddrListener.cpp b/mozilla/netwerk/system/win32/nsNotifyAddrListener.cpp index 5a6d41d5d66..64e6b7d8154 100644 --- a/mozilla/netwerk/system/win32/nsNotifyAddrListener.cpp +++ b/mozilla/netwerk/system/win32/nsNotifyAddrListener.cpp @@ -45,9 +45,8 @@ #include #include #include "prmem.h" -#include "prthread.h" #include "plstr.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsIObserverService.h" #include "nsServiceManagerUtils.h" #include "nsNotifyAddrListener.h" @@ -274,7 +273,6 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsNotifyAddrListener, nsNotifyAddrListener::nsNotifyAddrListener() : mLinkUp(PR_TRUE) // assume true by default , mStatusKnown(PR_FALSE) - , mThread(0) , mShutdownEvent(nsnull) { mOSVerInfo.dwOSVersionInfoSize = sizeof(mOSVerInfo); @@ -371,8 +369,7 @@ nsNotifyAddrListener::Init(void) mShutdownEvent = CreateEvent(NULL, FALSE, FALSE, NULL); NS_ENSURE_TRUE(mShutdownEvent, NS_ERROR_OUT_OF_MEMORY); - rv = NS_NewThread(getter_AddRefs(mThread), this, 0, - PR_JOINABLE_THREAD); + rv = NS_NewThread(getter_AddRefs(mThread), this); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; @@ -392,7 +389,7 @@ nsNotifyAddrListener::Shutdown(void) SetEvent(mShutdownEvent); - nsresult rv = mThread->Join(); + nsresult rv = mThread->Shutdown(); // Have to break the cycle here, otherwise nsNotifyAddrListener holds // onto the thread and the thread holds onto the nsNotifyAddrListener @@ -411,52 +408,26 @@ nsNotifyAddrListener::Shutdown(void) nsresult nsNotifyAddrListener::SendEventToUI(const char *aEventID) { + if (!aEventID) + return NS_ERROR_NULL_POINTER; + nsresult rv; - - if (!aEventID) return NS_ERROR_NULL_POINTER; - - nsCOMPtr eq; - rv = NS_GetMainEventQ(getter_AddRefs(eq)); - if (NS_FAILED(rv)) - return rv; - - ChangeEvent *event = new ChangeEvent(aEventID); - if (!event) - return NS_ERROR_OUT_OF_MEMORY; - // AddRef this because it is being placed in the PLEvent; it'll be Released - // when DestroyInterfaceEvent is called - NS_ADDREF_THIS(); - PL_InitEvent(event, this, HandleInterfaceEvent, DestroyInterfaceEvent); - - if (NS_FAILED(rv = eq->PostEvent(event))) { - NS_ERROR("failed to post event to UI EventQueue"); - PL_DestroyEvent(event); - } + nsCOMPtr event = new ChangeEvent(this, aEventID); + if (NS_FAILED(rv = NS_DispatchToMainThread(event))) + NS_WARNING("Failed to dispatch ChangeEvent"); return rv; } -/*static*/ void *PR_CALLBACK -nsNotifyAddrListener::HandleInterfaceEvent(PLEvent *aEvent) +NS_IMETHODIMP +nsNotifyAddrListener::ChangeEvent::Run() { - ChangeEvent *event = NS_STATIC_CAST(ChangeEvent *, aEvent); - nsCOMPtr observerService = do_GetService("@mozilla.org/observer-service;1"); if (observerService) observerService->NotifyObservers( - NS_STATIC_CAST(nsINetworkLinkService *, PL_GetEventOwner(aEvent)), - NS_NETWORK_LINK_TOPIC, - NS_ConvertASCIItoUTF16(event->mEventID).get()); - return nsnull; -} - -/*static*/ void PR_CALLBACK -nsNotifyAddrListener::DestroyInterfaceEvent(PLEvent *aEvent) -{ - nsNotifyAddrListener *self = - NS_STATIC_CAST(nsNotifyAddrListener *, PL_GetEventOwner(aEvent)); - NS_RELEASE(self); - delete aEvent; + mService, NS_NETWORK_LINK_TOPIC, + NS_ConvertASCIItoUTF16(mEventID).get()); + return NS_OK; } DWORD diff --git a/mozilla/netwerk/system/win32/nsNotifyAddrListener.h b/mozilla/netwerk/system/win32/nsNotifyAddrListener.h index 6d146a2a3a9..c2a3b2dad49 100644 --- a/mozilla/netwerk/system/win32/nsNotifyAddrListener.h +++ b/mozilla/netwerk/system/win32/nsNotifyAddrListener.h @@ -42,7 +42,7 @@ #include "nsINetworkLinkService.h" #include "nsIRunnable.h" #include "nsIObserver.h" -#include "nsIThread.h" +#include "nsThreadUtils.h" #include "nsCOMPtr.h" class nsNotifyAddrListener : public nsINetworkLinkService, @@ -61,8 +61,14 @@ public: nsresult Init(void); protected: - struct ChangeEvent : public PLEvent { - ChangeEvent(const char *aEventID) : mEventID(aEventID) { } + class ChangeEvent : public nsRunnable { + public: + NS_DECL_NSIRUNNABLE + ChangeEvent(nsINetworkLinkService *aService, const char *aEventID) + : mService(aService), mEventID(aEventID) { + } + private: + nsCOMPtr mService; const char *mEventID; }; @@ -78,9 +84,6 @@ protected: DWORD CheckAdaptersAddresses(void); void CheckLinkStatus(void); - PR_STATIC_CALLBACK(void*) HandleInterfaceEvent(PLEvent *aEvent); - PR_STATIC_CALLBACK(void) DestroyInterfaceEvent(PLEvent *aEvent); - nsCOMPtr mThread; OSVERSIONINFO mOSVerInfo; diff --git a/mozilla/netwerk/test/PropertiesTest.cpp b/mozilla/netwerk/test/PropertiesTest.cpp index a9958054154..b87e4e0c6f2 100644 --- a/mozilla/netwerk/test/PropertiesTest.cpp +++ b/mozilla/netwerk/test/PropertiesTest.cpp @@ -39,7 +39,6 @@ #include "TestCommon.h" #include "nsXPCOM.h" #include "nsStringAPI.h" -#include "nsIEventQueueService.h" #include "nsIPersistentProperties2.h" #include "nsIServiceManager.h" #include "nsIComponentRegistrar.h" @@ -57,7 +56,6 @@ static NS_DEFINE_CID(kPersistentPropertiesCID, NS_IPERSISTENTPROPERTIES_CID); static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); /***************************************************************************/ @@ -69,7 +67,6 @@ main(int argc, char* argv[]) nsresult ret; - nsCOMPtr servMan; NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull); nsCOMPtr registrar = do_QueryInterface(servMan); @@ -81,18 +78,10 @@ main(int argc, char* argv[]) nsCOMPtr service(do_GetService(kIOServiceCID, &ret)); if (NS_FAILED(ret)) return ret; - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &ret); - if (NS_FAILED(ret)) return ret; - nsIChannel *channel = nsnull; ret = service->NewChannel(NS_LITERAL_CSTRING(TEST_URL), nsnull, nsnull, &channel); if (NS_FAILED(ret)) return ret; - nsIEventQueue *eventQ = nsnull; - ret = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ); - if (NS_FAILED(ret)) return ret; - ret = channel->Open(&in); if (NS_FAILED(ret)) return ret; diff --git a/mozilla/netwerk/test/TestCallbacks.cpp b/mozilla/netwerk/test/TestCallbacks.cpp index f18141347ac..37cfbf2ebc9 100644 --- a/mozilla/netwerk/test/TestCallbacks.cpp +++ b/mozilla/netwerk/test/TestCallbacks.cpp @@ -43,7 +43,6 @@ #include "nspr.h" #include "nscore.h" #include "nsCOMPtr.h" -#include "nsIEventQueueService.h" #include "nsIIOService.h" #include "nsIServiceManager.h" #include "nsIStreamListener.h" @@ -58,12 +57,10 @@ #include "nsNetUtil.h" #include "nsStringAPI.h" -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); -static int gKeepRunning = 0; -static nsIEventQueue* gEventQ = nsnull; static PRBool gError = PR_FALSE; +static PRInt32 gKeepRunning = 0; #define NS_IEQUALS_IID \ { 0x11c5c8ee, 0x1dd2, 0x11b2, \ @@ -201,7 +198,8 @@ Consumer::~Consumer() { } fprintf(stderr, "Consumer::~Consumer -> out\n\n"); - gKeepRunning--; + if (--gKeepRunning == 0) + QuitPumpingEvents(); } nsresult @@ -256,14 +254,6 @@ int main(int argc, char *argv[]) { rv = NS_InitXPCOM2(nsnull, nsnull, nsnull); if (NS_FAILED(rv)) return rv; - // Create the Event Queue for this thread... - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - if (NS_FAILED(rv)) return rv; - if (cmdLineURL) { rv = StartLoad(argv[1]); } else { @@ -272,11 +262,7 @@ int main(int argc, char *argv[]) { if (NS_FAILED(rv)) return rv; // Enter the message pump to allow the URL load to proceed. - while ( gKeepRunning ) { - PLEvent *gEvent; - gEventQ->WaitForEvent(&gEvent); - gEventQ->HandleEvent(gEvent); - } + PumpEvents(); NS_ShutdownXPCOM(nsnull); if (gError) { diff --git a/mozilla/netwerk/test/TestCommon.h b/mozilla/netwerk/test/TestCommon.h index 711ad8d32a8..e640e88205f 100644 --- a/mozilla/netwerk/test/TestCommon.h +++ b/mozilla/netwerk/test/TestCommon.h @@ -37,9 +37,45 @@ #ifndef TestCommon_h__ #define TestCommon_h__ +#include +#include "nsThreadUtils.h" + inline int test_common_init(int *argc, char ***argv) { return 0; } +//----------------------------------------------------------------------------- + +static PRBool gKeepPumpingEvents = PR_FALSE; + +class nsQuitPumpingEvent : public nsIRunnable { +public: + NS_DECL_ISUPPORTS + NS_IMETHOD Run() { + gKeepPumpingEvents = PR_FALSE; + return NS_OK; + } +}; +NS_IMPL_THREADSAFE_ISUPPORTS1(nsQuitPumpingEvent, nsIRunnable) + +static void PumpEvents() +{ + nsCOMPtr thread = do_GetCurrentThread(); + + gKeepPumpingEvents = PR_TRUE; + while (gKeepPumpingEvents) + NS_ProcessNextEvent(thread); + + NS_ProcessPendingEvents(thread); +} + +static void QuitPumpingEvents() +{ + // Dispatch a task that toggles gKeepPumpingEvents so that we flush all + // of the pending tasks before exiting from PumpEvents. + nsCOMPtr event = new nsQuitPumpingEvent(); + NS_DispatchToMainThread(event); +} + #endif diff --git a/mozilla/netwerk/test/TestDNS.cpp b/mozilla/netwerk/test/TestDNS.cpp index 6f63f3667b9..359007586f9 100644 --- a/mozilla/netwerk/test/TestDNS.cpp +++ b/mozilla/netwerk/test/TestDNS.cpp @@ -93,9 +93,10 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(myDNSListener, nsIDNSListener) static PRBool IsAscii(const char *s) { - while (*s) + for (; *s; ++s) { if (*s & 0x80) return PR_FALSE; + } return PR_TRUE; } diff --git a/mozilla/netwerk/test/TestIOThreads.cpp b/mozilla/netwerk/test/TestIOThreads.cpp index 32fc19c94f1..c60a154d592 100644 --- a/mozilla/netwerk/test/TestIOThreads.cpp +++ b/mozilla/netwerk/test/TestIOThreads.cpp @@ -40,7 +40,7 @@ #include "nsServiceManagerUtils.h" #include "nsIEventTarget.h" #include "nsCOMPtr.h" -#include "plevent.h" +#include "nsNetCID.h" #include "prlog.h" #if defined(PR_LOGGING) @@ -51,33 +51,37 @@ static PRLogModuleInfo *gTestLog = nsnull; #endif #define LOG(args) PR_LOG(gTestLog, PR_LOG_DEBUG, args) -PR_STATIC_CALLBACK(void *) HandleEvent(PLEvent *event) -{ - LOG(("HandleEvent:%d\n", NS_PTR_TO_INT32(event->owner))); - return nsnull; -} +class nsIOEvent : public nsIRunnable { +public: + NS_DECL_ISUPPORTS -PR_STATIC_CALLBACK(void) DestroyEvent(PLEvent *event) -{ - delete event; -} + nsIOEvent(int i) : mIndex(i) {} + + NS_IMETHOD Run() { + LOG(("Run [%d]\n", mIndex)); + return NS_OK; + } + +private: + int mIndex; +}; +NS_IMPL_THREADSAFE_ISUPPORTS1(nsIOEvent, nsIRunnable) static nsresult RunTest() { nsresult rv; - nsCOMPtr target = do_GetService("@mozilla.org/network/io-thread-pool;1", &rv); + nsCOMPtr target = + do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; for (int i=0; i<10; ++i) { - PLEvent *event = new PLEvent(); - PL_InitEvent(event, (void *) i, HandleEvent, DestroyEvent); - LOG(("PostEvent:%d\n", i)); - if (NS_FAILED(target->PostEvent(event))) - PL_DestroyEvent(event); + nsCOMPtr event = new nsIOEvent(i); + LOG(("Dispatch %d\n", i)); + target->Dispatch(event, NS_DISPATCH_NORMAL); } - return rv; + return NS_OK; } int main(int argc, char **argv) diff --git a/mozilla/netwerk/test/TestIncrementalDownload.cpp b/mozilla/netwerk/test/TestIncrementalDownload.cpp index 5bb0bbe1ed5..a5065a06d00 100644 --- a/mozilla/netwerk/test/TestIncrementalDownload.cpp +++ b/mozilla/netwerk/test/TestIncrementalDownload.cpp @@ -37,54 +37,18 @@ * ***** END LICENSE BLOCK ***** */ #include +#include "TestCommon.h" #include "nsNetUtil.h" #include "nsIIncrementalDownload.h" #include "nsIRequestObserver.h" #include "nsIProgressEventSink.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" +#include "nsThreadUtils.h" #include "nsAutoPtr.h" #include "prprf.h" #include "prenv.h" //----------------------------------------------------------------------------- -static nsresult SetupEventQ() -{ - nsresult rv; - - nsCOMPtr eqs = - do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return rv; - - return eqs->CreateMonitoredThreadEventQueue(); -} - -static nsresult PumpEvents() -{ - nsresult rv; - - nsCOMPtr eqs = - do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr eq; - rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eq)); - if (NS_FAILED(rv)) - return rv; - - return eq->EventLoop(); -} - -static void QuitPumpingEvents() -{ - PR_Interrupt(PR_GetCurrentThread()); -} - -//----------------------------------------------------------------------------- - class FetchObserver : public nsIRequestObserver , public nsIProgressEventSink { @@ -160,15 +124,12 @@ DoIncrementalFetch(const char *uriSpec, const char *resultPath, PRInt32 chunkSiz if (NS_FAILED(rv)) return rv; - rv = SetupEventQ(); - if (NS_FAILED(rv)) - return rv; - rv = download->Start(observer, nsnull); if (NS_FAILED(rv)) return rv; - return PumpEvents(); + PumpEvents(); + return NS_OK; } int diff --git a/mozilla/netwerk/test/TestPageLoad.cpp b/mozilla/netwerk/test/TestPageLoad.cpp index 6ef63550386..36d79f4fd56 100644 --- a/mozilla/netwerk/test/TestPageLoad.cpp +++ b/mozilla/netwerk/test/TestPageLoad.cpp @@ -37,7 +37,6 @@ #include "TestCommon.h" #include "nsNetUtil.h" -#include "nsIEventQueueService.h" #include "nsIServiceManager.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" @@ -65,9 +64,6 @@ nsresult auxLoad(char *uriBuf); } \ PR_END_MACRO -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); -static nsIEventQueue* gEventQ = nsnull; -static PRBool gKeepRunning = PR_FALSE; static nsCString globalStream; //static char urlBuf[256]; static nsCOMPtr baseURI; @@ -77,6 +73,8 @@ static nsCOMPtr uriList; static int numStart=0; static int numFound=0; +static PRInt32 gKeepRunning = 0; + //--------writer fun---------------------- @@ -186,7 +184,8 @@ NS_IMETHODIMP MyListener::OnStopRequest(nsIRequest *req, nsISupports *ctxt, nsresult status) { //printf(">>> OnStopRequest status=%x\n", status); - gKeepRunning--; + if (--gKeepRunning == 0) + QuitPumpingEvents(); return NS_OK; } @@ -371,17 +370,6 @@ int main(int argc, char **argv) uriList = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv); RETURN_IF_FAILED(rv, "do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID)"); - // Create the Event Queue for this thread... - nsCOMPtr eqs = - do_GetService(kEventQueueServiceCID, &rv); - RETURN_IF_FAILED(rv, "do_GetService(EventQueueService)"); - - rv = eqs->CreateMonitoredThreadEventQueue(); - RETURN_IF_FAILED(rv, "CreateMonitoredThreadEventQueue"); - - rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - RETURN_IF_FAILED(rv, "GetThreadEventQueue"); - printf("Loading necko ... \n"); nsCOMPtr chan; nsCOMPtr listener = new MyListener(); @@ -400,9 +388,7 @@ int main(int argc, char **argv) rv = chan->AsyncOpen(listener, nsnull); RETURN_IF_FAILED(rv, "AsyncOpen"); - while (gKeepRunning) { - gEventQ->ProcessPendingEvents(); - } + PumpEvents(); finish = PR_Now(); PRUint32 totalTime32; diff --git a/mozilla/netwerk/test/TestPerf.cpp b/mozilla/netwerk/test/TestPerf.cpp index 6352c12e60e..4516d920f9b 100644 --- a/mozilla/netwerk/test/TestPerf.cpp +++ b/mozilla/netwerk/test/TestPerf.cpp @@ -2,7 +2,6 @@ #include #include "nsCRT.h" /* should be "plstr.h"? */ #include "nsNetUtil.h" -#include "nsIEventQueueService.h" #include "nsIServiceManager.h" #include "nsIComponentRegistrar.h" #include "nsISupportsArray.h" @@ -53,8 +52,6 @@ load_sync(nsISupportsArray *urls) //----------------------------------------------------------------------------- static int gRequestCount = 0; -static nsIEventQueue *gEventQ = 0; - class MyListener : public nsIStreamListener { @@ -95,18 +92,6 @@ MyListener::OnDataAvailable(nsIRequest *req, nsISupports *ctx, return NS_OK; } -static void *PR_CALLBACK -ShutdownEvent_Handler(PLEvent *ev) -{ - return nsnull; -} - -static void PR_CALLBACK -ShutdownEvent_Cleanup(PLEvent *ev) -{ - delete ev; -} - NS_IMETHODIMP MyListener::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status) { @@ -117,11 +102,7 @@ MyListener::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status) } if (--gRequestCount == 0) { // post shutdown event - PLEvent *ev = new PLEvent; - PL_InitEvent(ev, nsnull, - ShutdownEvent_Handler, - ShutdownEvent_Cleanup); - gEventQ->PostEvent(ev); + QuitPumpingEvents(); } return NS_OK; } @@ -149,29 +130,9 @@ load_async_1(nsISupports *element, void *data) static nsresult load_async(nsISupportsArray *urls) { - nsresult rv; - - // Create the Event Queue for this thread... - nsCOMPtr eqs( - do_GetService("@mozilla.org/event-queue-service;1", &rv) ); - if (NS_FAILED(rv)) return rv; - - rv = eqs->CreateMonitoredThreadEventQueue(); - if (NS_FAILED(rv)) return rv; - - rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - if (NS_FAILED(rv)) return rv; - urls->EnumerateForwards(load_async_1, nsnull); - while (1) { - PLEvent *ev; - gEventQ->WaitForEvent(&ev); - if (gRequestCount == 0) - break; - gEventQ->HandleEvent(ev); - } - NS_RELEASE(gEventQ); + PumpEvents(); return NS_OK; } diff --git a/mozilla/netwerk/test/TestProtocols.cpp b/mozilla/netwerk/test/TestProtocols.cpp index 946299db5dd..e7160905804 100644 --- a/mozilla/netwerk/test/TestProtocols.cpp +++ b/mozilla/netwerk/test/TestProtocols.cpp @@ -57,7 +57,6 @@ #include "nspr.h" #include "nscore.h" #include "nsCOMPtr.h" -#include "nsIEventQueueService.h" #include "nsIIOService.h" #include "nsIServiceManager.h" #include "nsIStreamListener.h" @@ -97,13 +96,11 @@ static PRLogModuleInfo *gTestLog = nsnull; #endif #define LOG(args) PR_LOG(gTestLog, PR_LOG_DEBUG, args) -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); //static PRTime gElapsedTime; // enable when we time it... static int gKeepRunning = 0; static PRBool gVerbose = PR_FALSE; -static nsIEventQueue* gEventQ = nsnull; static PRBool gAskUserForInput = PR_FALSE; static PRBool gResume = PR_FALSE; static PRUint64 gStartAt = 0; @@ -504,29 +501,6 @@ InputTestConsumer::OnDataAvailable(nsIRequest *request, return NS_OK; } -PR_STATIC_CALLBACK(void) DecrementDestroyHandler(PLEvent *self) -{ - PR_Free(self); -} - - -PR_STATIC_CALLBACK(void*) DecrementEventHandler(PLEvent *self) -{ - gKeepRunning--; - return nsnull; -} - -void FireDecrement() -{ - PLEvent *event = PR_NEW(PLEvent); - PL_InitEvent(event, - nsnull, - DecrementEventHandler, - DecrementDestroyHandler); - - gEventQ->PostEvent(event); -} - NS_IMETHODIMP InputTestConsumer::OnStopRequest(nsIRequest *request, nsISupports* context, nsresult aStatus) @@ -572,7 +546,8 @@ InputTestConsumer::OnStopRequest(nsIRequest *request, nsISupports* context, LOG(("\nFinished loading: UNKNOWN URL. Status Code: %x\n", aStatus)); } - FireDecrement(); + if (--gKeepRunning == 0) + QuitPumpingEvents(); return NS_OK; } @@ -708,7 +683,7 @@ nsresult StartLoadingURL(const char* aUrlString) info); if (NS_SUCCEEDED(rv)) { - gKeepRunning += 1; + gKeepRunning++; } else { LOG(("ERROR: AsyncOpen failed [rv=%x]\n", rv)); @@ -833,13 +808,6 @@ main(int argc, char* argv[]) if (NS_FAILED(rv)) return rv; { - // Create the Event Queue for this thread... - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - int i; LOG(("Trying to load:\n")); for (i=1; iWaitForEvent(&gEvent); - gEventQ->HandleEvent(gEvent); - } + // Enter the message pump to allow the URL load to proceed. + PumpEvents(); } // this scopes the nsCOMPtrs // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM NS_ShutdownXPCOM(nsnull); diff --git a/mozilla/netwerk/test/TestServ.cpp b/mozilla/netwerk/test/TestServ.cpp index 0fbf0084720..dbb4e7a06a0 100644 --- a/mozilla/netwerk/test/TestServ.cpp +++ b/mozilla/netwerk/test/TestServ.cpp @@ -38,8 +38,6 @@ #include "TestCommon.h" #include #include "nsIServiceManager.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" #include "nsIServerSocket.h" #include "nsISocketTransport.h" #include "nsNetUtil.h" @@ -55,9 +53,6 @@ static PRLogModuleInfo *gTestLog = nsnull; #endif #define LOG(args) PR_LOG(gTestLog, PR_LOG_DEBUG, args) -static PRBool gKeepRunning = PR_TRUE; -static nsIEventQueue* gEventQ = nsnull; - class MySocketListener : public nsIServerSocketListener { public: @@ -117,7 +112,7 @@ NS_IMETHODIMP MySocketListener::OnStopListening(nsIServerSocket *serv, nsresult status) { LOG(("MySocketListener::OnStopListening [serv=%p status=%x]\n", serv, status)); - gKeepRunning = PR_FALSE; + QuitPumpingEvents(); return NS_OK; } @@ -167,13 +162,6 @@ main(int argc, char* argv[]) if (NS_FAILED(rv)) return rv; { - // Create the Event Queue for this thread... - nsCOMPtr eqs = - do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) return rv; - - eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - rv = MakeServer(atoi(argv[1])); if (NS_FAILED(rv)) { LOG(("MakeServer failed [rv=%x]\n", rv)); @@ -181,11 +169,7 @@ main(int argc, char* argv[]) } // Enter the message pump to allow the URL load to proceed. - while (gKeepRunning) { - PLEvent *event; - gEventQ->WaitForEvent(&event); - gEventQ->HandleEvent(event); - } + PumpEvents(); } // this scopes the nsCOMPtrs // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM NS_ShutdownXPCOM(nsnull); diff --git a/mozilla/netwerk/test/TestSocketTransport.cpp b/mozilla/netwerk/test/TestSocketTransport.cpp index ffdfac41fa9..562db706b63 100644 --- a/mozilla/netwerk/test/TestSocketTransport.cpp +++ b/mozilla/netwerk/test/TestSocketTransport.cpp @@ -54,8 +54,6 @@ #include "nsIDNSService.h" #include "nsIFileStreams.h" #include "nsIStreamListener.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" #include "nsILocalFile.h" #include "nsNetUtil.h" #include "nsAutoLock.h" @@ -74,39 +72,6 @@ static PRLogModuleInfo *gTestLog = nsnull; //////////////////////////////////////////////////////////////////////////////// static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - -PRBool gDone = PR_FALSE; -nsIEventQueue* gEventQ = nsnull; - -//////////////////////////////////////////////////////////////////////////////// - -static void *PR_CALLBACK -DoneEvent_Handler(PLEvent *ev) -{ - gDone = PR_TRUE; - return nsnull; -} - -static void PR_CALLBACK -DoneEvent_Cleanup(PLEvent *ev) -{ - delete ev; -} - -static void -PostDoneEvent() -{ - LOG(("PostDoneEvent\n")); - - PLEvent *ev = new PLEvent(); - - PL_InitEvent(ev, nsnull, - DoneEvent_Handler, - DoneEvent_Cleanup); - - gEventQ->PostEvent(ev); -} //////////////////////////////////////////////////////////////////////////////// @@ -169,7 +134,7 @@ public: if (NS_FAILED(rv) || (n == 0)) { if (rv != NS_BASE_STREAM_WOULD_BLOCK) { - PostDoneEvent(); + QuitPumpingEvents(); return NS_OK; } } @@ -261,16 +226,8 @@ RunTest(nsISocketTransportService *sts, rv = asyncOut->AsyncWait(handler, 0, 0, nsnull); - if (NS_SUCCEEDED(rv)) { - PLEvent* event; - gDone = PR_FALSE; - while (!gDone) { - rv = gEventQ->WaitForEvent(&event); - if (NS_FAILED(rv)) return rv; - rv = gEventQ->HandleEvent(event); - if (NS_FAILED(rv)) return rv; - } - } + if (NS_SUCCEEDED(rv)) + PumpEvents(); NS_RELEASE(handler); @@ -309,16 +266,6 @@ main(int argc, char* argv[]) do_GetService(NS_DNSSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - rv = eventQService->CreateMonitoredThreadEventQueue(); - if (NS_FAILED(rv)) return rv; - - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - if (NS_FAILED(rv)) return rv; - nsCOMPtr sts = do_GetService(kSocketTransportServiceCID, &rv); if (NS_FAILED(rv)) return rv; @@ -387,8 +334,6 @@ main(int argc, char* argv[]) LOG(("calling Shutdown on socket transport service:\n")); sts->Shutdown(); - NS_RELEASE(gEventQ); - // give background threads a chance to finish whatever work they may // be doing. LOG(("waiting 1 second before exiting...\n")); diff --git a/mozilla/netwerk/test/TestStreamChannel.cpp b/mozilla/netwerk/test/TestStreamChannel.cpp index 58a8fb5863a..05f8a4cd734 100644 --- a/mozilla/netwerk/test/TestStreamChannel.cpp +++ b/mozilla/netwerk/test/TestStreamChannel.cpp @@ -51,8 +51,6 @@ #include "nsStringAPI.h" #include "nsIFileStreams.h" #include "nsIStreamListener.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" #include "nsILocalFile.h" #include "nsNetUtil.h" #include "nsAutoLock.h" @@ -73,39 +71,6 @@ static PRLogModuleInfo *gTestLog = nsnull; //////////////////////////////////////////////////////////////////////////////// static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - -PRBool gDone = PR_FALSE; -nsIEventQueue *gEventQ = nsnull; - -//////////////////////////////////////////////////////////////////////////////// - -static void *PR_CALLBACK -DoneEvent_Handler(PLEvent *ev) -{ - gDone = PR_TRUE; - return nsnull; -} - -static void PR_CALLBACK -DoneEvent_Cleanup(PLEvent *ev) -{ - delete ev; -} - -static void -PostDoneEvent() -{ - LOG(("PostDoneEvent\n")); - - PLEvent *ev = new PLEvent(); - - PL_InitEvent(ev, nsnull, - DoneEvent_Handler, - DoneEvent_Cleanup); - - gEventQ->PostEvent(ev); -} //////////////////////////////////////////////////////////////////////////////// @@ -151,7 +116,7 @@ public: NS_IMETHOD OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status) { LOG(("MyListener::OnStopRequest [status=%x]\n", status)); - PostDoneEvent(); + QuitPumpingEvents(); return NS_OK; } }; @@ -225,15 +190,7 @@ RunTest(nsIFile *file) rv = chan->AsyncOpen(new MyListener(), nsnull); if (NS_FAILED(rv)) return rv; - gDone = PR_FALSE; - while (!gDone) { - PLEvent *event; - rv = gEventQ->WaitForEvent(&event); - if (NS_FAILED(rv)) return rv; - rv = gEventQ->HandleEvent(event); - if (NS_FAILED(rv)) return rv; - } - + PumpEvents(); return NS_OK; } @@ -264,13 +221,6 @@ main(int argc, char* argv[]) gTestLog = PR_NewLogModule("Test"); #endif - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - if (NS_FAILED(rv)) return rv; - nsCOMPtr file; rv = NS_NewNativeLocalFile(nsDependentCString(fileName), PR_FALSE, getter_AddRefs(file)); if (NS_FAILED(rv)) return rv; @@ -278,8 +228,6 @@ main(int argc, char* argv[]) rv = RunTest(file); NS_ASSERTION(NS_SUCCEEDED(rv), "RunTest failed"); - NS_RELEASE(gEventQ); - // give background threads a chance to finish whatever work they may // be doing. PR_Sleep(PR_SecondsToInterval(1)); diff --git a/mozilla/netwerk/test/TestStreamLoader.cpp b/mozilla/netwerk/test/TestStreamLoader.cpp index 5bf2a26b7af..55e56219aa5 100644 --- a/mozilla/netwerk/test/TestStreamLoader.cpp +++ b/mozilla/netwerk/test/TestStreamLoader.cpp @@ -1,7 +1,7 @@ #include #include "TestCommon.h" #include "nsNetUtil.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "prlog.h" #if defined(PR_LOGGING) @@ -12,9 +12,6 @@ static PRLogModuleInfo *gTestLog = nsnull; #endif #define LOG(args) PR_LOG(gTestLog, PR_LOG_DEBUG, args) -static PRBool gKeepRunning = PR_TRUE; -static nsIEventQueue* gEventQ = nsnull; - class MyStreamLoaderObserver : public nsIStreamLoaderObserver { public: @@ -37,7 +34,7 @@ MyStreamLoaderObserver::OnStreamComplete(nsIStreamLoader *loader, loader->GetRequest(getter_AddRefs(request)); LOG((" request=%p\n", request.get())); - gKeepRunning = PR_FALSE; + QuitPumpingEvents(); return NS_OK; } @@ -60,11 +57,6 @@ int main(int argc, char **argv) return -1; { - // Create the Event Queue for this thread... - rv = NS_GetMainEventQ(&gEventQ); - if (NS_FAILED(rv)) - return -1; - nsCOMPtr uri; rv = NS_NewURI(getter_AddRefs(uri), nsDependentCString(argv[1])); if (NS_FAILED(rv)) @@ -84,12 +76,7 @@ int main(int argc, char **argv) if (NS_FAILED(rv)) return -1; - // Enter the message pump to allow the URL load to proceed. - while (gKeepRunning) { - PLEvent *e; - gEventQ->WaitForEvent(&e); - gEventQ->HandleEvent(e); - } + PumpEvents(); } // this scopes the nsCOMPtrs // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM NS_ShutdownXPCOM(nsnull); diff --git a/mozilla/netwerk/test/TestStreamPump.cpp b/mozilla/netwerk/test/TestStreamPump.cpp index a32a7283433..4d73376ca26 100644 --- a/mozilla/netwerk/test/TestStreamPump.cpp +++ b/mozilla/netwerk/test/TestStreamPump.cpp @@ -52,8 +52,6 @@ #include "nsStringAPI.h" #include "nsIFileStreams.h" #include "nsIStreamListener.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" #include "nsILocalFile.h" #include "nsNetUtil.h" #include "nsAutoLock.h" @@ -74,42 +72,6 @@ static PRLogModuleInfo *gTestLog = nsnull; //////////////////////////////////////////////////////////////////////////////// -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - -PRBool gDone = PR_FALSE; -nsIEventQueue *gEventQ = nsnull; - -//////////////////////////////////////////////////////////////////////////////// - -static void *PR_CALLBACK -DoneEvent_Handler(PLEvent *ev) -{ - gDone = PR_TRUE; - return nsnull; -} - -static void PR_CALLBACK -DoneEvent_Cleanup(PLEvent *ev) -{ - delete ev; -} - -static void -PostDoneEvent() -{ - LOG(("PostDoneEvent\n")); - - PLEvent *ev = new PLEvent(); - - PL_InitEvent(ev, nsnull, - DoneEvent_Handler, - DoneEvent_Cleanup); - - gEventQ->PostEvent(ev); -} - -//////////////////////////////////////////////////////////////////////////////// - class MyListener : public nsIStreamListener { public: @@ -155,7 +117,7 @@ public: NS_IMETHOD OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status) { LOG(("MyListener::OnStopRequest [status=%x]\n", status)); - PostDoneEvent(); + QuitPumpingEvents(); return NS_OK; } }; @@ -187,15 +149,7 @@ RunTest(nsIFile *file, PRInt64 offset, PRInt64 length) rv = pump->AsyncRead(new MyListener(), nsnull); if (NS_FAILED(rv)) return rv; - gDone = PR_FALSE; - while (!gDone) { - PLEvent *event; - rv = gEventQ->WaitForEvent(&event); - if (NS_FAILED(rv)) return rv; - rv = gEventQ->HandleEvent(event); - if (NS_FAILED(rv)) return rv; - } - + PumpEvents(); return NS_OK; } @@ -238,13 +192,6 @@ main(int argc, char* argv[]) gTestLog = PR_NewLogModule("Test"); #endif - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - if (NS_FAILED(rv)) return rv; - nsCOMPtr file; rv = NS_NewNativeLocalFile(nsDependentCString(fileName), PR_FALSE, getter_AddRefs(file)); if (NS_FAILED(rv)) return rv; @@ -252,8 +199,6 @@ main(int argc, char* argv[]) rv = RunTest(file, offset, length); NS_ASSERTION(NS_SUCCEEDED(rv), "RunTest failed"); - NS_RELEASE(gEventQ); - // give background threads a chance to finish whatever work they may // be doing. PR_Sleep(PR_SecondsToInterval(1)); diff --git a/mozilla/netwerk/test/TestStreamTransport.cpp b/mozilla/netwerk/test/TestStreamTransport.cpp index 57faf86e34c..ad2b9463f89 100644 --- a/mozilla/netwerk/test/TestStreamTransport.cpp +++ b/mozilla/netwerk/test/TestStreamTransport.cpp @@ -51,8 +51,6 @@ #include "nsStringAPI.h" #include "nsIFileStreams.h" #include "nsIStreamListener.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" #include "nsILocalFile.h" #include "nsNetUtil.h" #include "nsAutoLock.h" @@ -72,39 +70,6 @@ static PRLogModuleInfo *gTestLog = nsnull; //////////////////////////////////////////////////////////////////////////////// static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - -PRBool gDone = PR_FALSE; -nsIEventQueue* gEventQ = nsnull; - -//////////////////////////////////////////////////////////////////////////////// - -static void *PR_CALLBACK -DoneEvent_Handler(PLEvent *ev) -{ - gDone = PR_TRUE; - return nsnull; -} - -static void PR_CALLBACK -DoneEvent_Cleanup(PLEvent *ev) -{ - delete ev; -} - -static void -PostDoneEvent() -{ - LOG(("PostDoneEvent\n")); - - PLEvent *ev = new PLEvent(); - - PL_InitEvent(ev, nsnull, - DoneEvent_Handler, - DoneEvent_Cleanup); - - gEventQ->PostEvent(ev); -} //////////////////////////////////////////////////////////////////////////////// @@ -162,7 +127,7 @@ public: mInput = 0; // post done copying event - PostDoneEvent(); + QuitPumpingEvents(); } void Process_Locked() @@ -277,15 +242,7 @@ RunTest(nsIFile *srcFile, nsIFile *destFile) rv = copier->AsyncCopy(srcTransport, destTransport); if (NS_FAILED(rv)) return rv; - PLEvent* event; - - gDone = PR_FALSE; - while (!gDone) { - rv = gEventQ->WaitForEvent(&event); - if (NS_FAILED(rv)) return rv; - rv = gEventQ->HandleEvent(event); - if (NS_FAILED(rv)) return rv; - } + PumpEvents(); NS_RELEASE(copier); return NS_OK; @@ -361,13 +318,6 @@ main(int argc, char* argv[]) gTestLog = PR_NewLogModule("Test"); #endif - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - if (NS_FAILED(rv)) return rv; - nsCOMPtr srcFile; rv = NS_NewNativeLocalFile(nsDependentCString(fileName), PR_FALSE, getter_AddRefs(srcFile)); if (NS_FAILED(rv)) return rv; @@ -396,8 +346,6 @@ main(int argc, char* argv[]) rv = RunBlockingTest(srcFile, destFile); NS_ASSERTION(NS_SUCCEEDED(rv), "RunBlockingTest failed"); - NS_RELEASE(gEventQ); - // give background threads a chance to finish whatever work they may // be doing. PR_Sleep(PR_SecondsToInterval(1)); diff --git a/mozilla/netwerk/test/TestUpload.cpp b/mozilla/netwerk/test/TestUpload.cpp index c4f80c85cc5..b2542ce357c 100644 --- a/mozilla/netwerk/test/TestUpload.cpp +++ b/mozilla/netwerk/test/TestUpload.cpp @@ -41,14 +41,12 @@ #endif #include "nsIComponentRegistrar.h" -#include "nsIEventQueueService.h" #include "nsIIOService.h" #include "nsIServiceManager.h" #include "nsNetUtil.h" #include "nsIUploadChannel.h" -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #include "prlog.h" @@ -60,9 +58,6 @@ static PRLogModuleInfo *gTestLog = nsnull; #endif #define LOG(args) PR_LOG(gTestLog, PR_LOG_DEBUG, args) -static int gKeepRunning = 1; -static nsIEventQueue* gEventQ = nsnull; - //----------------------------------------------------------------------------- // InputTestConsumer //----------------------------------------------------------------------------- @@ -126,7 +121,7 @@ InputTestConsumer::OnStopRequest(nsIRequest *request, nsISupports* context, nsresult aStatus) { LOG(("InputTestConsumer::OnStopRequest [status=%x]\n", aStatus)); - gKeepRunning = PR_FALSE; + QuitPumpingEvents(); return NS_OK; } @@ -158,13 +153,6 @@ main(int argc, char* argv[]) if (registrar) registrar->AutoRegister(nsnull); - // Create the Event Queue for this thread... - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - nsCOMPtr ioService(do_GetService(kIOServiceCID, &rv)); // first thing to do is create ourselves a stream that // is to be uploaded. @@ -200,11 +188,7 @@ main(int argc, char* argv[]) channel->AsyncOpen(listener, nsnull); - while ( gKeepRunning ) { - PLEvent *gEvent; - gEventQ->WaitForEvent(&gEvent); - gEventQ->HandleEvent(gEvent); - } + PumpEvents(); } // this scopes the nsCOMPtrs // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM rv = NS_ShutdownXPCOM(nsnull); diff --git a/mozilla/parser/htmlparser/src/nsParser.cpp b/mozilla/parser/htmlparser/src/nsParser.cpp index e6426b1af50..9184dc63cb7 100644 --- a/mozilla/parser/htmlparser/src/nsParser.cpp +++ b/mozilla/parser/htmlparser/src/nsParser.cpp @@ -54,8 +54,6 @@ #include "nsParserCIID.h" #include "nsReadableUtils.h" #include "nsCOMPtr.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" #include "nsExpatDriver.h" #include "nsIServiceManager.h" #include "nsICategoryManager.h" @@ -78,8 +76,6 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID); static NS_DEFINE_IID(kIParserIID, NS_IPARSER_IID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - //------------------------------------------------------------------- nsCOMArray *nsParser::sParserDataListeners; @@ -140,30 +136,19 @@ For more details @see bugzilla bug 76722 */ -struct nsParserContinueEvent : public PLEvent +class nsParserContinueEvent : public nsRunnable { +public: + nsRefPtr mParser; + nsParserContinueEvent(nsParser* aParser) - { - NS_ADDREF(aParser); - PL_InitEvent(this, aParser, HandleEvent, DestroyEvent); - } + : mParser(aParser) + {} - ~nsParserContinueEvent() + NS_IMETHOD Run() { - nsParser *parser = (nsParser*) owner; - NS_RELEASE(parser); - } - - PR_STATIC_CALLBACK(void*) HandleEvent(PLEvent* aEvent) - { - nsParser *parser = (nsParser*) aEvent->owner; - parser->HandleParserContinueEvent(); - return nsnull; - } - - PR_STATIC_CALLBACK(void) DestroyEvent(PLEvent* aEvent) - { - delete (nsParserContinueEvent*) aEvent; + mParser->HandleParserContinueEvent(this); + return NS_OK; } }; @@ -253,7 +238,8 @@ nsParser::nsParser() mParserContext=0; mStreamStatus=0; mCharsetSource=kCharsetUninitialized; - mInternalState=NS_OK;; + mInternalState=NS_OK; + mContinueEvent=nsnull; mCommand=eViewNormal; mFlags = NS_PARSER_FLAG_OBSERVERS_ENABLED | NS_PARSER_FLAG_PARSER_ENABLED | @@ -263,20 +249,6 @@ nsParser::nsParser() MOZ_TIMER_RESET(mParseTime); MOZ_TIMER_RESET(mDTDTime); MOZ_TIMER_RESET(mTokenizeTime); - - nsresult rv = NS_OK; - if (mEventQueue == nsnull) { - // Cache the event queue of the current UI thread - nsCOMPtr eventService = - do_GetService(kEventQueueServiceCID, &rv); - // XXX This implies that the UI is the current thread. - if (NS_SUCCEEDED(rv) && eventService) { - rv = eventService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(mEventQueue)); - } - - // NS_ASSERTION(mEventQueue, "event queue is null"); - } } /** @@ -311,10 +283,10 @@ nsParser::~nsParser() mParserContext = pc; } - if (mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT) { - NS_ASSERTION(mEventQueue != nsnull, "Event queue is null"); - mEventQueue->RevokeEvents(this); - } + // It should not be possible for this flag to be set when we are getting + // destroyed since this flag implies a pending nsParserContinueEvent, which + // has an owning reference to |this|. + NS_ASSERTION(!(mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT), "bad"); } NS_IMPL_ISUPPORTS3(nsParser, @@ -330,14 +302,18 @@ NS_IMPL_ISUPPORTS3(nsParser, nsresult nsParser::PostContinueEvent() { - if (!(mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT) && mEventQueue) { - nsParserContinueEvent* ev = new nsParserContinueEvent(this); - NS_ENSURE_TRUE(ev, NS_ERROR_OUT_OF_MEMORY); - if (NS_FAILED(mEventQueue->PostEvent(ev))) { - NS_ERROR("failed to post parser continuation event"); - PL_DestroyEvent(ev); + if (!(mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT)) { + // If this flag isn't set, then there shouldn't be a live continue event! + NS_ASSERTION(!mContinueEvent, "bad"); + + // This creates a reference cycle between this and the event that is + // broken when the event fires. + nsCOMPtr event = new nsParserContinueEvent(this); + if (NS_FAILED(NS_DispatchToCurrentThread(event))) { + NS_WARNING("failed to dispatch parser continuation event"); } else { mFlags |= NS_PARSER_FLAG_PENDING_CONTINUE_EVENT; + mContinueEvent = event; } } return NS_OK; @@ -907,12 +883,9 @@ NS_IMETHODIMP nsParser::CancelParsingEvents() { if (mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT) { - NS_ASSERTION(mEventQueue,"Event queue is null"); - // Revoke all pending continue parsing events - if (mEventQueue != nsnull) { - mEventQueue->RevokeEvents(this); - } - + NS_ASSERTION(mContinueEvent, "mContinueEvent is null"); + // Revoke the pending continue parsing event + mContinueEvent = nsnull; mFlags &= ~NS_PARSER_FLAG_PENDING_CONTINUE_EVENT; } return NS_OK; @@ -1194,8 +1167,14 @@ nsParser::IsComplete() } -void nsParser::HandleParserContinueEvent() { +void nsParser::HandleParserContinueEvent(nsParserContinueEvent *ev) { + // Ignore any revoked continue events... + if (mContinueEvent != ev) + return; + mFlags &= ~NS_PARSER_FLAG_PENDING_CONTINUE_EVENT; + mContinueEvent = nsnull; + ContinueInterruptedParsing(); } diff --git a/mozilla/parser/htmlparser/src/nsParser.h b/mozilla/parser/htmlparser/src/nsParser.h index 10080929332..f3913fc9f9e 100644 --- a/mozilla/parser/htmlparser/src/nsParser.h +++ b/mozilla/parser/htmlparser/src/nsParser.h @@ -83,7 +83,7 @@ #include "nsHTMLTags.h" #include "nsDTDUtils.h" #include "nsTimer.h" -#include "nsIEventQueue.h" +#include "nsThreadUtils.h" #include "nsIContentSink.h" #include "nsIParserFilter.h" #include "nsCOMArray.h" @@ -372,7 +372,7 @@ class nsParser : public nsIParser, * Fired when the continue parse event is triggered. * @update kmcclusk 5/18/98 */ - void HandleParserContinueEvent(void); + void HandleParserContinueEvent(class nsParserContinueEvent *); /** * Called by top-level scanners when data from necko is added to @@ -446,10 +446,10 @@ protected: //********************************************* - nsCOMPtr mEventQueue; CParserContext* mParserContext; nsCOMPtr mObserver; nsCOMPtr mSink; + nsIRunnable* mContinueEvent; // weak ref nsCOMPtr mParserFilter; nsTokenAllocator mTokenAllocator; diff --git a/mozilla/parser/htmlparser/tests/grabpage/grabpage.cpp b/mozilla/parser/htmlparser/tests/grabpage/grabpage.cpp index 26d9248686f..7a100ad32f7 100644 --- a/mozilla/parser/htmlparser/tests/grabpage/grabpage.cpp +++ b/mozilla/parser/htmlparser/tests/grabpage/grabpage.cpp @@ -39,6 +39,7 @@ #include "nsIURL.h" #include "nsServiceManagerUtils.h" #include "nsComponentManagerUtils.h" +#include "nsThreadUtils.h" #include "nsNetCID.h" #include "nsCOMPtr.h" @@ -47,10 +48,6 @@ #include "nsILocalFile.h" static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); -#include "nsIEventQueueService.h" -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); -static nsIEventQueue* gEventQ = nsnull; - #include "nsStringAPI.h" #include "nsCRT.h" #include "prprf.h" @@ -220,14 +217,7 @@ nsresult PageGrabber::Grab(const nsCString& aURL) { nsresult rv; - // Create the Event Queue for this thread... // Unix needs this - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); - nsCOMPtr file = NextFile("html"); if (!file) { return NS_ERROR_OUT_OF_MEMORY; @@ -270,10 +260,10 @@ PageGrabber::Grab(const nsCString& aURL) } // Enter the message pump to allow the URL load to proceed. + nsCOMPtr thread = do_GetCurrentThread(); while ( !copier->IsDone() ) { - PLEvent *gEvent; - gEventQ->WaitForEvent(&gEvent); - gEventQ->HandleEvent(gEvent); + if (!NS_ProcessNextEvent(thread)) + break; } rv = copier->HaveError() ? NS_ERROR_FAILURE : NS_OK; diff --git a/mozilla/profile/pref-migrator/src/nsPrefMigration.cpp b/mozilla/profile/pref-migrator/src/nsPrefMigration.cpp index 95286f69626..fa7efb8eaa6 100644 --- a/mozilla/profile/pref-migrator/src/nsPrefMigration.cpp +++ b/mozilla/profile/pref-migrator/src/nsPrefMigration.cpp @@ -294,16 +294,9 @@ nsPrefMigration::getPrefService() nsCOMPtr pIMyService(do_GetService(kPrefServiceCID, &rv)); if(NS_FAILED(rv)) return rv; - nsCOMPtr pIProxyObjectManager = - do_GetService(kProxyObjectManagerCID, &rv); - if(NS_FAILED(rv)) - return rv; - - return pIProxyObjectManager->GetProxyForObject(NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIPref), - pIMyService, - PROXY_SYNC, - getter_AddRefs(m_prefs)); + return NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIPref), + pIMyService, NS_PROXY_SYNC, + getter_AddRefs(m_prefs)); } @@ -387,14 +380,6 @@ extern "C" void ProfileMigrationController(void *data) return; } - nsCOMPtr pIProxyObjectManager = - do_GetService(kProxyObjectManagerCID, &rv); - if(NS_FAILED(rv)) - { - migrator->mErrorCode = rv; - return; - } - nsCOMPtr migratorInterface = do_QueryInterface(interfaceM, &rv); if (NS_FAILED(rv)) { @@ -404,11 +389,10 @@ extern "C" void ProfileMigrationController(void *data) if (!prefProxy) { - rv = pIProxyObjectManager->GetProxyForObject(NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIPrefMigration), - migratorInterface, - PROXY_SYNC, - getter_AddRefs(prefProxy)); + rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIPrefMigration), + migratorInterface, NS_PROXY_SYNC, + getter_AddRefs(prefProxy)); if (NS_FAILED(rv)) { migrator->mErrorCode = rv; diff --git a/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp b/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp index 39d92378ef0..5f60ea59a69 100644 --- a/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp +++ b/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp @@ -45,12 +45,11 @@ #include "nsChromeRegistry.h" #include "nsCOMPtr.h" #include "nsContentCID.h" +#include "nsThreadUtils.h" #include "nsCRT.h" #include "nsIChannel.h" #include "nsIChromeRegistry.h" #include "nsIComponentManager.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" #include "nsIFastLoadService.h" #include "nsIFile.h" #include "nsIFileURL.h" @@ -70,13 +69,13 @@ #endif #include "nsNetCID.h" #include "nsNetUtil.h" +#include "nsAutoPtr.h" #include "nsXPIDLString.h" #include "nsString.h" #include "prlog.h" //---------------------------------------------------------------------- -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID); #ifdef MOZ_XUL @@ -123,17 +122,26 @@ protected: nsCOMPtr mOwner; nsresult mStatus; - struct LoadEvent { - PLEvent mEvent; - nsCachedChromeChannel* mChannel; + typedef void (*LoadEventCallback)(nsCachedChromeChannel*); + + struct LoadEvent : nsRunnable { + LoadEvent(nsCachedChromeChannel *chan, LoadEventCallback callback) + : mChannel(chan), mCallback(callback) {} + + nsRefPtr mChannel; + LoadEventCallback mCallback; + + NS_IMETHOD Run() { + mCallback(mChannel); + return NS_OK; + } }; static nsresult - PostLoadEvent(nsCachedChromeChannel* aChannel, PLHandleEventProc aHandler); + PostLoadEvent(nsCachedChromeChannel* aChannel, LoadEventCallback aCallback); - static void* PR_CALLBACK HandleStartLoadEvent(PLEvent* aEvent); - static void* PR_CALLBACK HandleStopLoadEvent(PLEvent* aEvent); - static void PR_CALLBACK DestroyLoadEvent(PLEvent* aEvent); + static void HandleStartLoadEvent(nsCachedChromeChannel* channel); + static void HandleStopLoadEvent(nsCachedChromeChannel* channel); #ifdef PR_LOGGING static PRLogModuleInfo* gLog; @@ -394,60 +402,26 @@ nsCachedChromeChannel::SetContentLength(PRInt32 aContentLength) nsresult nsCachedChromeChannel::PostLoadEvent(nsCachedChromeChannel* aChannel, - PLHandleEventProc aHandler) + LoadEventCallback aCallback) { - nsresult rv; - - nsCOMPtr svc = do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - if (! svc) - return NS_ERROR_UNEXPECTED; - - nsCOMPtr queue; - rv = svc->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - if (NS_FAILED(rv)) return rv; - - if (! queue) - return NS_ERROR_UNEXPECTED; - - LoadEvent* event = new LoadEvent; + nsCOMPtr event = new LoadEvent(aChannel, aCallback); if (! event) return NS_ERROR_OUT_OF_MEMORY; - PL_InitEvent(NS_REINTERPRET_CAST(PLEvent*, event), - nsnull, - aHandler, - DestroyLoadEvent); - - event->mChannel = aChannel; - NS_ADDREF(event->mChannel); - - rv = queue->EnterMonitor(); - if (NS_SUCCEEDED(rv)) { - (void) queue->PostEvent(NS_REINTERPRET_CAST(PLEvent*, event)); - (void) queue->ExitMonitor(); - return NS_OK; - } - - // If we get here, something bad happened. Clean up. - NS_RELEASE(event->mChannel); - delete event; - return rv; + return NS_DispatchToCurrentThread(event); } -void* PR_CALLBACK -nsCachedChromeChannel::HandleStartLoadEvent(PLEvent* aEvent) +/*static*/ void +nsCachedChromeChannel::HandleStartLoadEvent(nsCachedChromeChannel *channel) { // Fire the OnStartRequest() for the cached chrome channel, then // queue another event to trigger the OnStopRequest()... - LoadEvent* event = NS_REINTERPRET_CAST(LoadEvent*, aEvent); - nsCachedChromeChannel* channel = event->mChannel; // If the load has been cancelled, then just bail now. We won't // send On[Start|Stop]Request(). + // XXX(darin): this violates the nsIChannel API if (NS_FAILED(channel->mStatus)) - return nsnull; + return; PR_LOG(gLog, PR_LOG_DEBUG, ("nsCachedChromeChannel[%p]: firing OnStartRequest for %p", @@ -455,25 +429,20 @@ nsCachedChromeChannel::HandleStartLoadEvent(PLEvent* aEvent) (void) channel->mListener->OnStartRequest(channel, channel->mContext); (void) PostLoadEvent(channel, HandleStopLoadEvent); - return nsnull; } -void* PR_CALLBACK -nsCachedChromeChannel::HandleStopLoadEvent(PLEvent* aEvent) +/*static*/ void +nsCachedChromeChannel::HandleStopLoadEvent(nsCachedChromeChannel* channel) { // Fire the OnStopRequest() for the cached chrome channel, and // remove it from the load group. - LoadEvent* event = NS_REINTERPRET_CAST(LoadEvent*, aEvent); - nsCachedChromeChannel* channel = event->mChannel; - nsIRequest* request = NS_REINTERPRET_CAST(nsIRequest*, channel); - PR_LOG(gLog, PR_LOG_DEBUG, ("nsCachedChromeChannel[%p]: firing OnStopRequest for %p", channel, channel->mListener.get())); - (void) channel->mListener->OnStopRequest(request, channel->mContext, + (void) channel->mListener->OnStopRequest(channel, channel->mContext, channel->mStatus); if (channel->mLoadGroup) { @@ -481,21 +450,11 @@ nsCachedChromeChannel::HandleStopLoadEvent(PLEvent* aEvent) ("nsCachedChromeChannel[%p]: removing self from load group %p", channel, channel->mLoadGroup.get())); - (void) channel->mLoadGroup->RemoveRequest(request, nsnull, NS_OK); + (void) channel->mLoadGroup->RemoveRequest(channel, nsnull, NS_OK); } channel->mListener = nsnull; channel->mContext = nsnull; - - return nsnull; -} - -void PR_CALLBACK -nsCachedChromeChannel::DestroyLoadEvent(PLEvent* aEvent) -{ - LoadEvent* event = NS_REINTERPRET_CAST(LoadEvent*, aEvent); - NS_RELEASE(event->mChannel); - delete event; } //////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/rdf/tests/rdfcat/rdfcat.cpp b/mozilla/rdf/tests/rdfcat/rdfcat.cpp index 9368ff8e78f..67cb63fc157 100644 --- a/mozilla/rdf/tests/rdfcat/rdfcat.cpp +++ b/mozilla/rdf/tests/rdfcat/rdfcat.cpp @@ -53,7 +53,6 @@ #include "nsIComponentManager.h" #include "nsComponentManagerUtils.h" #include "nsServiceManagerUtils.h" -#include "nsIEventQueueService.h" #include "nsIIOService.h" #include "nsIInputStream.h" #include "nsIOutputStream.h" @@ -66,7 +65,7 @@ #include "nsIStreamListener.h" #include "nsIURL.h" #include "nsRDFCID.h" -#include "plevent.h" +#include "nsThreadUtils.h" #include "plstr.h" #include "prio.h" #include "prthread.h" @@ -77,9 +76,6 @@ // rdf static NS_DEFINE_CID(kRDFXMLDataSourceCID, NS_RDFXMLDATASOURCE_CID); -// xpcom -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - //////////////////////////////////////////////////////////////////////// // Blatantly stolen from netwerk/test/ #define RETURN_IF_FAILED(rv, step) \ @@ -153,15 +149,6 @@ main(int argc, char** argv) NS_InitXPCOM2(nsnull, nsnull, nsnull); - // Get netlib off the floor... - nsCOMPtr theEventQueueService = - do_GetService(kEventQueueServiceCID, &rv); - RETURN_IF_FAILED(rv, "EventQueueService"); - - nsIEventQueue* eq = nsnull; - rv = theEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, &eq); - RETURN_IF_FAILED(rv, "GetThreadEventQueue"); - // Create a stream data source and initialize it on argv[1], which // is hopefully a "file:" URL. nsCOMPtr ds = do_CreateInstance(kRDFXMLDataSourceCID, @@ -179,9 +166,10 @@ main(int argc, char** argv) RETURN_IF_FAILED(rv, "datasource refresh"); // Pump events until the load is finished + nsCOMPtr thread = do_GetCurrentThread(); PRBool done = PR_FALSE; while (!done) { - eq->ProcessPendingEvents(); + NS_ENSURE_STATE(NS_ProcessNextEvent(thread)); remote->GetLoaded(&done); } @@ -197,7 +185,5 @@ main(int argc, char** argv) rv = source->Serialize(out); RETURN_IF_FAILED(rv, "datasoure serialization"); - theEventQueueService->DestroyThreadEventQueue(); - return NS_OK; } diff --git a/mozilla/rdf/tests/rdfpoll/rdfpoll.cpp b/mozilla/rdf/tests/rdfpoll/rdfpoll.cpp index dbd00835eee..2c21d72d7f4 100644 --- a/mozilla/rdf/tests/rdfpoll/rdfpoll.cpp +++ b/mozilla/rdf/tests/rdfpoll/rdfpoll.cpp @@ -51,7 +51,6 @@ #include #include "nsXPCOM.h" #include "nsCOMPtr.h" -#include "nsIEventQueueService.h" #include "nsIInputStream.h" #include "nsIIOService.h" #include "nsIRDFCompositeDataSource.h" @@ -66,8 +65,8 @@ #include "nsRDFCID.h" #include "nsIComponentManager.h" #include "nsComponentManagerUtils.h" +#include "nsThreadUtils.h" #include "prthread.h" -#include "plevent.h" #include "plstr.h" #include "nsEmbedString.h" #include "nsNetCID.h" @@ -78,9 +77,6 @@ // rdf static NS_DEFINE_CID(kRDFXMLDataSourceCID, NS_RDFXMLDATASOURCE_CID); -// xpcom -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - //////////////////////////////////////////////////////////////////////// // IIDs @@ -260,15 +256,6 @@ main(int argc, char** argv) return 1; } - // Get netlib off the floor... - nsCOMPtr theEventQueueService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - rv = theEventQueueService->CreateThreadEventQueue(); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create thread event queue"); - if (NS_FAILED(rv)) return rv; - // Create a stream data source and initialize it on argv[1], which // is hopefully a "file:" URL. (Actually, we can do _any_ kind of // URL, but only a "file:" URL will be written back to disk.) diff --git a/mozilla/rdf/tests/triplescat/triplescat.cpp b/mozilla/rdf/tests/triplescat/triplescat.cpp index 521c6353b4b..20f684b52fd 100644 --- a/mozilla/rdf/tests/triplescat/triplescat.cpp +++ b/mozilla/rdf/tests/triplescat/triplescat.cpp @@ -52,7 +52,7 @@ #include "nsIComponentManager.h" #include "nsComponentManagerUtils.h" #include "nsServiceManagerUtils.h" -#include "nsIEventQueueService.h" +#include "nsThreadUtils.h" #include "nsIIOService.h" #include "nsIInputStream.h" #include "nsIOutputStream.h" @@ -65,7 +65,6 @@ #include "nsIStreamListener.h" #include "nsIURL.h" #include "nsRDFCID.h" -#include "plevent.h" #include "plstr.h" #include "prio.h" #include "prthread.h" @@ -148,15 +147,6 @@ main(int argc, char** argv) NS_InitXPCOM2(nsnull, nsnull, nsnull); - // Get netlib off the floor... - nsCOMPtr theEventQueueService = - do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - RETURN_IF_FAILED(rv, "EventQueueService"); - - nsIEventQueue* eq = nsnull; - rv = theEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, &eq); - RETURN_IF_FAILED(rv, "GetThreadEventQueue"); - // Create a stream data source and initialize it on argv[1], which // is hopefully a "file:" URL. nsCOMPtr ds = @@ -175,9 +165,10 @@ main(int argc, char** argv) RETURN_IF_FAILED(rv, "datasource refresh"); // Pump events until the load is finished + nsCOMPtr thread = do_GetCurrentThread(); PRBool done = PR_FALSE; while (!done) { - eq->ProcessPendingEvents(); + NS_ENSURE_STATE(NS_ProcessNextEvent(thread)); remote->GetLoaded(&done); } @@ -193,7 +184,5 @@ main(int argc, char** argv) out->Close(); } - theEventQueueService->DestroyThreadEventQueue(); - return NS_OK; } diff --git a/mozilla/security/manager/boot/src/nsSecureBrowserUIImpl.cpp b/mozilla/security/manager/boot/src/nsSecureBrowserUIImpl.cpp index 8cd8c52f3ac..2790c3fd6be 100644 --- a/mozilla/security/manager/boot/src/nsSecureBrowserUIImpl.cpp +++ b/mozilla/security/manager/boot/src/nsSecureBrowserUIImpl.cpp @@ -77,6 +77,7 @@ #include "nsIFormSubmitObserver.h" #include "nsISecurityWarningDialogs.h" #include "nsIProxyObjectManager.h" +#include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsCRT.h" @@ -1424,15 +1425,11 @@ GetNSSDialogs(nsISecurityWarningDialogs **result) if (NS_FAILED(rv)) return rv; - nsCOMPtr proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID)); - if (!proxyman) - return NS_ERROR_FAILURE; - nsCOMPtr proxiedResult; - proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsISecurityWarningDialogs), - my_result, PROXY_SYNC, - getter_AddRefs(proxiedResult)); + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsISecurityWarningDialogs), + my_result, NS_PROXY_SYNC, + getter_AddRefs(proxiedResult)); if (!proxiedResult) { return NS_ERROR_FAILURE; diff --git a/mozilla/security/manager/ssl/src/Makefile.in b/mozilla/security/manager/ssl/src/Makefile.in index c9b1cfa55ea..ba745d15463 100644 --- a/mozilla/security/manager/ssl/src/Makefile.in +++ b/mozilla/security/manager/ssl/src/Makefile.in @@ -90,7 +90,6 @@ CPPSRCS = \ nsCRLManager.cpp \ nsNSSShutDown.cpp \ nsNTLMAuthModule.cpp \ - nsNSSEvent.cpp \ nsSmartCardMonitor.cpp \ nsSmartCardEvent.cpp \ $(NULL) diff --git a/mozilla/security/manager/ssl/src/nsCrypto.cpp b/mozilla/security/manager/ssl/src/nsCrypto.cpp index 7c8a31ee21b..f5d5145dff5 100644 --- a/mozilla/security/manager/ssl/src/nsCrypto.cpp +++ b/mozilla/security/manager/ssl/src/nsCrypto.cpp @@ -44,8 +44,10 @@ #include "nsNSSCertificateDB.h" #include "nsPKCS12Blob.h" #include "nsPK11TokenDB.h" +#include "nsThreadUtils.h" #include "nsIServiceManager.h" #include "nsIMemory.h" +#include "nsAutoPtr.h" #include "nsCRT.h" #include "prprf.h" #include "prmem.h" @@ -1625,7 +1627,7 @@ nsCrypto::GenerateCRMFRequest(nsIDOMCRMFObject** aReturn) if (!cryptoRunnable) return NS_ERROR_OUT_OF_MEMORY; - nsresult rv = nsNSSEventPostToUIEventQueue(cryptoRunnable); + nsresult rv = NS_DispatchToMainThread(cryptoRunnable); if (NS_FAILED(rv)) delete cryptoRunnable; @@ -2016,7 +2018,7 @@ nsCrypto::ImportUserCertificates(const nsAString& aNickname, // memory on the way out. certArr = nsnull; - rv = nsNSSEventPostToUIEventQueue(p12Runnable); + rv = NS_DispatchToMainThread(p12Runnable); if (NS_FAILED(rv)) goto loser; } @@ -2189,19 +2191,11 @@ nsCrypto::SignText(const nsAString& aStringToSign, const nsAString& aCaOption, return NS_OK; } - nsCOMPtr proxyman = - do_GetService(NS_XPCOMPROXY_CONTRACTID); - if (!proxyman) { - aResult.Append(internalError); - - return NS_OK; - } - nsCOMPtr proxied_fsd; - nsresult rv = proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIFormSigningDialog), - fsd, PROXY_SYNC, - getter_AddRefs(proxied_fsd)); + nsresult rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIFormSigningDialog), + fsd, NS_PROXY_SYNC, + getter_AddRefs(proxied_fsd)); if (NS_FAILED(rv)) { aResult.Append(internalError); diff --git a/mozilla/security/manager/ssl/src/nsCrypto.h b/mozilla/security/manager/ssl/src/nsCrypto.h index 9520ca1061d..23cc4a1e6e7 100644 --- a/mozilla/security/manager/ssl/src/nsCrypto.h +++ b/mozilla/security/manager/ssl/src/nsCrypto.h @@ -44,10 +44,8 @@ #include "nsIDOMPkcs11.h" #include "nsIRunnable.h" #include "nsString.h" -#include "nsNSSEvent.h" #include "jsapi.h" #include "nsIPrincipal.h" -#include "plevent.h" #define NS_CRYPTO_CLASSNAME "Crypto JavaScript Class" #define NS_CRYPTO_CID \ @@ -108,19 +106,4 @@ public: }; -// -// This is the class we'll use to post ui events -// -struct CryptoRunnableEvent : PLEvent { - CryptoRunnableEvent(nsIRunnable* runnable); - ~CryptoRunnableEvent(); - - nsIRunnable* mRunnable; -}; - - #endif //_nsCrypto_h_ - - - - diff --git a/mozilla/security/manager/ssl/src/nsKeygenThread.cpp b/mozilla/security/manager/ssl/src/nsKeygenThread.cpp index 5029f7b8613..1edcd7cb099 100644 --- a/mozilla/security/manager/ssl/src/nsKeygenThread.cpp +++ b/mozilla/security/manager/ssl/src/nsKeygenThread.cpp @@ -39,6 +39,7 @@ #include "pk11func.h" #include "nsCOMPtr.h" #include "nsProxiedService.h" +#include "nsThreadUtils.h" #include "nsKeygenThread.h" #include "nsIObserver.h" #include "nsNSSShutDown.h" @@ -149,16 +150,12 @@ nsresult nsKeygenThread::StartKeyGeneration(nsIObserver* aObserver) if (!aObserver) return NS_OK; - nsCOMPtr proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID)); - if (!proxyman) - return NS_OK; - nsCOMPtr obs; - proxyman->GetProxyForObject( NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIObserver), - aObserver, - PROXY_SYNC | PROXY_ALWAYS, - getter_AddRefs(obs)); + NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIObserver), + aObserver, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs(obs)); PR_Lock(mutex); diff --git a/mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp b/mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp index 008f0d2dd02..a512a09ff7a 100644 --- a/mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp +++ b/mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp @@ -47,6 +47,7 @@ #include "nsIStringBundle.h" #include "nsXPIDLString.h" #include "nsCOMPtr.h" +#include "nsAutoPtr.h" #include "nsIServiceManager.h" #include "nsReadableUtils.h" #include "nsIPrompt.h" @@ -55,9 +56,9 @@ #include "nsIInterfaceRequestorUtils.h" #include "nsCRT.h" #include "nsNSSShutDown.h" -#include "nsNSSEvent.h" #include "nsIUploadChannel.h" #include "nsSSLThread.h" +#include "nsThreadUtils.h" #include "nsAutoLock.h" #include "nsIThread.h" #include "nsIWindowWatcher.h" @@ -69,9 +70,11 @@ static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); -struct nsHTTPDownloadEvent : PLEvent { +struct nsHTTPDownloadEvent : nsRunnable { nsHTTPDownloadEvent(); ~nsHTTPDownloadEvent(); + + NS_IMETHOD Run(); nsNSSHttpRequestSession *mRequestSession; // no ownership @@ -90,20 +93,20 @@ nsHTTPDownloadEvent::~nsHTTPDownloadEvent() mListener->send_done_signal(); } -static void PR_CALLBACK HandleHTTPDownloadPLEvent(nsHTTPDownloadEvent *aEvent) +NS_IMETHODIMP +nsHTTPDownloadEvent::Run() { - if((!aEvent) || (!aEvent->mListener)) - return; + if (!mListener) + return NS_OK; nsresult rv; - nsCOMPtr ios = do_GetIOService(&rv); - if (NS_FAILED(rv)) - return; + + nsCOMPtr ios = do_GetIOService(); + NS_ENSURE_STATE(ios); nsCOMPtr chan; - ios->NewChannel(aEvent->mRequestSession->mURL, nsnull, nsnull, getter_AddRefs(chan)); - if (NS_FAILED(rv)) - return; + ios->NewChannel(mRequestSession->mURL, nsnull, nsnull, getter_AddRefs(chan)); + NS_ENSURE_STATE(chan); // Create a loadgroup for this new channel. This way if the channel // is redirected, we'll have a way to cancel the resulting channel. @@ -111,71 +114,57 @@ static void PR_CALLBACK HandleHTTPDownloadPLEvent(nsHTTPDownloadEvent *aEvent) do_CreateInstance(NS_LOADGROUP_CONTRACTID); chan->SetLoadGroup(loadGroup); - if (aEvent->mRequestSession->mHasPostData) + if (mRequestSession->mHasPostData) { nsCOMPtr uploadStream; rv = NS_NewPostDataStream(getter_AddRefs(uploadStream), PR_FALSE, - aEvent->mRequestSession->mPostData, + mRequestSession->mPostData, 0, ios); - if (NS_FAILED(rv)) - return; + NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr uploadChannel(do_QueryInterface(chan, &rv)); - if (NS_FAILED(rv)) - return; + nsCOMPtr uploadChannel(do_QueryInterface(chan)); + NS_ENSURE_STATE(uploadChannel); rv = uploadChannel->SetUploadStream(uploadStream, - aEvent->mRequestSession->mPostContentType, + mRequestSession->mPostContentType, -1); - if (NS_FAILED(rv)) - return; + NS_ENSURE_SUCCESS(rv, rv); } - nsCOMPtr hchan = do_QueryInterface(chan, &rv); - if (NS_FAILED(rv)) - return; + nsCOMPtr hchan = do_QueryInterface(chan); + NS_ENSURE_STATE(hchan); - rv = hchan->SetRequestMethod(aEvent->mRequestSession->mRequestMethod); - if (NS_FAILED(rv)) - return; + rv = hchan->SetRequestMethod(mRequestSession->mRequestMethod); + NS_ENSURE_SUCCESS(rv, rv); nsSSLThread::rememberPendingHTTPRequest(loadGroup); - aEvent->mResponsibleForDoneSignal = PR_FALSE; - aEvent->mListener->mResponsibleForDoneSignal = PR_TRUE; + mResponsibleForDoneSignal = PR_FALSE; + mListener->mResponsibleForDoneSignal = PR_TRUE; - rv = NS_NewStreamLoader(getter_AddRefs(aEvent->mListener->mLoader), + rv = NS_NewStreamLoader(getter_AddRefs(mListener->mLoader), hchan, - aEvent->mListener, + mListener, nsnull); if (NS_FAILED(rv)) { - aEvent->mListener->mResponsibleForDoneSignal = PR_FALSE; - aEvent->mResponsibleForDoneSignal = PR_TRUE; + mListener->mResponsibleForDoneSignal = PR_FALSE; + mResponsibleForDoneSignal = PR_TRUE; nsSSLThread::rememberPendingHTTPRequest(nsnull); } + + return NS_OK; } -static void PR_CALLBACK DestroyHTTPDownloadPLEvent(nsHTTPDownloadEvent* aEvent) -{ - delete aEvent; -} - -struct nsCancelHTTPDownloadEvent : PLEvent { +struct nsCancelHTTPDownloadEvent : nsRunnable { + NS_IMETHOD Run() { + nsSSLThread::cancelPendingHTTPRequest(); + return NS_OK; + } }; -static void PR_CALLBACK HandleCancelHTTPDownloadPLEvent(nsCancelHTTPDownloadEvent *aEvent) -{ - nsSSLThread::cancelPendingHTTPRequest(); -} - -static void PR_CALLBACK DestroyCancelHTTPDownloadPLEvent(nsCancelHTTPDownloadEvent* aEvent) -{ - delete aEvent; -} - SECStatus nsNSSHttpServerSession::createSessionFcn(const char *host, PRUint16 portnum, SEC_HTTP_SERVER_SESSION *pSession) @@ -264,7 +253,7 @@ SECStatus nsNSSHttpRequestSession::trySendAndReceiveFcn(PRPollDesc **pPollDesc, const char **http_response_data, PRUint32 *http_response_data_len) { - if (nsIThread::IsMainThread()) + if (NS_IsMainThread()) { nsresult rv; nsCOMPtr nssComponent(do_GetService(kNSSComponentCID, &rv)); @@ -304,10 +293,6 @@ SECStatus nsNSSHttpRequestSession::trySendAndReceiveFcn(PRPollDesc **pPollDesc, *http_response_data_len = 0; } - nsCOMPtr uiQueue = nsNSSEventGetUIEventQueue(); - if (!uiQueue) - return SECFailure; - if (!mListener) return SECFailure; @@ -319,20 +304,17 @@ SECStatus nsNSSHttpRequestSession::trySendAndReceiveFcn(PRPollDesc **pPollDesc, volatile PRBool &waitFlag = mListener->mWaitFlag; waitFlag = PR_TRUE; - nsHTTPDownloadEvent *event = new nsHTTPDownloadEvent; + nsRefPtr event = new nsHTTPDownloadEvent; if (!event) return SECFailure; event->mListener = mListener; event->mRequestSession = this; - PL_InitEvent(event, nsnull, (PLHandleEventProc)HandleHTTPDownloadPLEvent, - (PLDestroyEventProc)DestroyHTTPDownloadPLEvent); - nsresult rv = uiQueue->PostEvent(event); + nsresult rv = NS_DispatchToMainThread(event); if (NS_FAILED(rv)) { event->mResponsibleForDoneSignal = PR_FALSE; - delete event; return SECFailure; } @@ -359,14 +341,11 @@ SECStatus nsNSSHttpRequestSession::trySendAndReceiveFcn(PRPollDesc **pPollDesc, request_canceled = PR_TRUE; // but we'll to continue to wait for waitFlag - nsCancelHTTPDownloadEvent *cancelevent = new nsCancelHTTPDownloadEvent; - PL_InitEvent(cancelevent, nsnull, (PLHandleEventProc)HandleCancelHTTPDownloadPLEvent, - (PLDestroyEventProc)DestroyCancelHTTPDownloadPLEvent); - rv = uiQueue->PostEvent(cancelevent); + nsCOMPtr cancelevent = new nsCancelHTTPDownloadEvent; + rv = NS_DispatchToMainThread(cancelevent); if (NS_FAILED(rv)) { NS_WARNING("cannot post cancel event"); - delete cancelevent; aborted_wait = PR_TRUE; break; } @@ -658,15 +637,12 @@ PK11PasswordPrompt(PK11SlotInfo* slot, PRBool retry, void* arg) { // The interface requestor object may not be safe, so // proxy the call to get the nsIPrompt. - nsCOMPtr proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID)); - if (!proxyman) return nsnull; - nsCOMPtr proxiedCallbacks; - proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIInterfaceRequestor), - ir, - PROXY_SYNC, - getter_AddRefs(proxiedCallbacks)); + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIInterfaceRequestor), + ir, + NS_PROXY_SYNC, + getter_AddRefs(proxiedCallbacks)); // Get the desired interface nsCOMPtr prompt(do_GetInterface(proxiedCallbacks)); @@ -676,12 +652,11 @@ PK11PasswordPrompt(PK11SlotInfo* slot, PRBool retry, void* arg) { } // Finally, get a proxy for the nsIPrompt - proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIPrompt), - prompt, - PROXY_SYNC, - getter_AddRefs(proxyPrompt)); - + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIPrompt), + prompt, + NS_PROXY_SYNC, + getter_AddRefs(proxyPrompt)); nsAutoString promptString; nsCOMPtr nssComponent(do_GetService(kNSSComponentCID, &rv)); diff --git a/mozilla/security/manager/ssl/src/nsNSSCertificate.cpp b/mozilla/security/manager/ssl/src/nsNSSCertificate.cpp index 6a60fe34587..ccff8c804fa 100644 --- a/mozilla/security/manager/ssl/src/nsNSSCertificate.cpp +++ b/mozilla/security/manager/ssl/src/nsNSSCertificate.cpp @@ -66,6 +66,7 @@ #include "nsNSSCertHelper.h" #include "nsISupportsPrimitives.h" #include "nsUnicharUtils.h" +#include "nsThreadUtils.h" #include "nsCertVerificationThread.h" #include "nspr.h" @@ -209,12 +210,6 @@ nsNSSCertificate::FormatUIStrings(const nsAutoString &nickname, nsAutoString &ni { nsresult rv = NS_OK; - nsCOMPtr proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv)); - - if (NS_FAILED(rv) || !proxyman) { - return NS_ERROR_FAILURE; - } - nsCOMPtr nssComponent(do_GetService(kNSSComponentCID, &rv)); if (NS_FAILED(rv) || !nssComponent) { @@ -222,11 +217,11 @@ nsNSSCertificate::FormatUIStrings(const nsAutoString &nickname, nsAutoString &ni } nsCOMPtr x509Proxy; - proxyman->GetProxyForObject( NS_UI_THREAD_EVENTQ, - nsIX509Cert::GetIID(), - NS_STATIC_CAST(nsIX509Cert*, this), - PROXY_SYNC | PROXY_ALWAYS, - getter_AddRefs(x509Proxy)); + NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + nsIX509Cert::GetIID(), + NS_STATIC_CAST(nsIX509Cert*, this), + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs(x509Proxy)); if (!x509Proxy) { rv = NS_ERROR_OUT_OF_MEMORY; @@ -269,11 +264,11 @@ nsNSSCertificate::FormatUIStrings(const nsAutoString &nickname, nsAutoString &ni nsCOMPtr originalValidity; rv = x509Proxy->GetValidity(getter_AddRefs(originalValidity)); if (NS_SUCCEEDED(rv) && originalValidity) { - proxyman->GetProxyForObject( NS_UI_THREAD_EVENTQ, - nsIX509CertValidity::GetIID(), - originalValidity, - PROXY_SYNC | PROXY_ALWAYS, - getter_AddRefs(validity)); + NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + nsIX509CertValidity::GetIID(), + originalValidity, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs(validity)); } if (validity) { diff --git a/mozilla/security/manager/ssl/src/nsNSSComponent.cpp b/mozilla/security/manager/ssl/src/nsNSSComponent.cpp index 5d1850dc7a0..f386fd1a6be 100644 --- a/mozilla/security/manager/ssl/src/nsNSSComponent.cpp +++ b/mozilla/security/manager/ssl/src/nsNSSComponent.cpp @@ -47,7 +47,6 @@ #include "nsNSSIOLayer.h" #include "nsSSLThread.h" #include "nsCertVerificationThread.h" -#include "nsNSSEvent.h" #include "nsNetUtil.h" #include "nsAppDirectoryServiceDefs.h" @@ -72,7 +71,6 @@ #include "nsIDateTimeFormat.h" #include "nsDateTimeFormatCID.h" #include "nsAutoLock.h" -#include "nsIEventQueue.h" #include "nsIDOMEvent.h" #include "nsIDOMDocument.h" #include "nsIDOMDocumentEvent.h" @@ -81,8 +79,8 @@ #include "nsIDOMWindowInternal.h" #include "nsIDOMSmartCardEvent.h" #include "nsIDOMCrypto.h" -#include "nsIRunnable.h" -#include "plevent.h" +#include "nsThreadUtils.h" +#include "nsAutoPtr.h" #include "nsCRT.h" #include "nsCRLInfo.h" @@ -207,39 +205,34 @@ static PRIntn PR_CALLBACK certHashtable_clearEntry(PLHashEntry *he, PRIntn /*ind return HT_ENUMERATE_NEXT; } -struct CRLDownloadEvent : PLEvent { - nsCAutoString *urlString; - nsIStreamListener *psmDownloader; -}; +class CRLDownloadEvent : public nsRunnable { +public: + CRLDownloadEvent(const nsCSubstring &urlString, nsIStreamListener *listener) + : mURLString(urlString) + , mListener(listener) + {} -// Note that nsNSSComponent is a singleton object across all threads, -// and automatic downloads are always scheduled sequentially - that is, -// once one crl download is complete, the next one is scheduled -static void* PR_CALLBACK HandleCRLImportPLEvent(PLEvent *aEvent) -{ - CRLDownloadEvent *event = NS_STATIC_CAST(CRLDownloadEvent*, aEvent); + // Note that nsNSSComponent is a singleton object across all threads, + // and automatic downloads are always scheduled sequentially - that is, + // once one crl download is complete, the next one is scheduled + NS_IMETHOD Run() + { + if (!mListener || mURLString.IsEmpty()) + return NS_OK; - nsresult rv; - nsIURI *pURL; - - if((event->psmDownloader==nsnull) || (event->urlString==nsnull) ) - return nsnull; + nsCOMPtr uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), mURLString); + if (NS_SUCCEEDED(rv)){ + NS_OpenURI(mListener, nsnull, uri); + } - rv = NS_NewURI(&pURL, event->urlString->get()); - if(NS_SUCCEEDED(rv)){ - NS_OpenURI(event->psmDownloader, nsnull, pURL); + return NS_OK; } - return nsnull; -} - -static void PR_CALLBACK DestroyCRLImportPLEvent(PLEvent* aEvent) -{ - CRLDownloadEvent *event = NS_STATIC_CAST(CRLDownloadEvent*, aEvent); - - delete event->urlString; - delete event; -} +private: + nsCString mURLString; + nsCOMPtr mListener; +}; //This class is used to run the callback code //passed to the event handlers for smart card notification @@ -361,18 +354,13 @@ NS_IMETHODIMP nsNSSComponent::PostEvent(const nsAString &eventType, const nsAString &tokenName) { - nsresult rv; - nsTokenEventRunnable *runnable = + nsCOMPtr runnable = new nsTokenEventRunnable(eventType, tokenName); if (!runnable) { return NS_ERROR_OUT_OF_MEMORY; } - rv = nsNSSEventPostToUIEventQueue(runnable); - if (NS_FAILED(rv)) - delete runnable; - - return rv; + return NS_DispatchToMainThread(runnable); } @@ -927,24 +915,16 @@ static void setOCSPOptions(nsIPrefBranch * pref) } nsresult -nsNSSComponent::PostCRLImportEvent(nsCAutoString *urlString, PSMContentDownloader *psmDownloader) +nsNSSComponent::PostCRLImportEvent(const nsCSubstring &urlString, + nsIStreamListener *listener) { //Create the event - CRLDownloadEvent *event = new CRLDownloadEvent; - PL_InitEvent(event, this, HandleCRLImportPLEvent, DestroyCRLImportPLEvent); - event->urlString = urlString; - event->psmDownloader = (nsIStreamListener *)psmDownloader; - - //Get a handle to the ui event queue - - nsCOMPtruiQueue = nsNSSEventGetUIEventQueue(); + nsCOMPtr event = new CRLDownloadEvent(urlString, listener); + if (!event) + return NS_ERROR_OUT_OF_MEMORY; - if (!uiQueue) { - return NS_ERROR_FAILURE; - } - - //Post the event - return uiQueue->PostEvent(event); + //Get a handle to the ui thread + return NS_DispatchToMainThread(event); } nsresult @@ -952,12 +932,11 @@ nsNSSComponent::DownloadCRLDirectly(nsAutoString url, nsAutoString key) { //This api is meant to support direct interactive update of crl from the crl manager //or other such ui. - PSMContentDownloader *psmDownloader = new PSMContentDownloader(PSMContentDownloader::PKCS7_CRL); + nsCOMPtr listener = + new PSMContentDownloader(PSMContentDownloader::PKCS7_CRL); - nsCAutoString *urlString = new nsCAutoString(); - urlString->AssignWithConversion(url.get()); - - return PostCRLImportEvent(urlString, psmDownloader); + NS_ConvertUTF16toUTF8 url8(url); + return PostCRLImportEvent(url8, listener); } nsresult nsNSSComponent::DownloadCrlSilently() @@ -967,15 +946,14 @@ nsresult nsNSSComponent::DownloadCrlSilently() crlsScheduledForDownload->Put(&hashKey,(void *)nsnull); //Set up the download handler - PSMContentDownloader *psmDownloader = new PSMContentDownloader(PSMContentDownloader::PKCS7_CRL); + nsRefPtr psmDownloader = + new PSMContentDownloader(PSMContentDownloader::PKCS7_CRL); psmDownloader->setSilentDownload(PR_TRUE); psmDownloader->setCrlAutodownloadKey(mCrlUpdateKey); //Now get the url string - nsCAutoString *urlString = new nsCAutoString(); - urlString->AssignWithConversion(mDownloadURL); - - return PostCRLImportEvent(urlString, psmDownloader); + NS_ConvertUTF16toUTF8 url8(mDownloadURL); + return PostCRLImportEvent(url8, psmDownloader); } nsresult nsNSSComponent::getParamsForNextCrlToDownload(nsAutoString *url, PRTime *time, nsAutoString *key) @@ -2005,20 +1983,16 @@ void nsNSSComponent::ShowAlert(AlertIdentifier ai) PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can't get window prompter\n")); } else { - nsCOMPtr proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID)); - if (!proxyman) { - PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can't get proxy manager\n")); + nsCOMPtr proxyPrompt; + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIPrompt), + prompter, NS_PROXY_SYNC, + getter_AddRefs(proxyPrompt)); + if (!proxyPrompt) { + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can't get proxy for nsIPrompt\n")); } else { - nsCOMPtr proxyPrompt; - proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIPrompt), - prompter, PROXY_SYNC, getter_AddRefs(proxyPrompt)); - if (!proxyPrompt) { - PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can't get proxy for nsIPrompt\n")); - } - else { - proxyPrompt->Alert(nsnull, message.get()); - } + proxyPrompt->Alert(nsnull, message.get()); } } } @@ -2251,17 +2225,16 @@ NS_IMETHODIMP PipUIContext::GetInterface(const nsIID & uuid, void * *result) nsresult rv = NS_OK; if (uuid.Equals(NS_GET_IID(nsIPrompt))) { - nsCOMPtr proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID)); - if (!proxyman) return NS_ERROR_FAILURE; - nsCOMPtr prompter; nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); if (wwatch) { wwatch->GetNewPrompter(0, getter_AddRefs(prompter)); if (prompter) { nsCOMPtr proxyPrompt; - proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIPrompt), - prompter, PROXY_SYNC, getter_AddRefs(proxyPrompt)); + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIPrompt), + prompter, NS_PROXY_SYNC, + getter_AddRefs(proxyPrompt)); if (!proxyPrompt) return NS_ERROR_FAILURE; *result = proxyPrompt; NS_ADDREF((nsIPrompt*)*result); @@ -2283,14 +2256,9 @@ getNSSDialogs(void **_result, REFNSIID aIID, const char *contract) if (NS_FAILED(rv)) return rv; - nsCOMPtr proxyman = - do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return rv; - - rv = proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, - aIID, svc, PROXY_SYNC, - _result); + rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + aIID, svc, NS_PROXY_SYNC, + _result); return rv; } @@ -2345,8 +2313,7 @@ PSMContentDownloader::~PSMContentDownloader() nsMemory::Free(mByteData); } -/*NS_IMPL_ISUPPORTS1(CertDownloader, nsIStreamListener)*/ -NS_IMPL_ISUPPORTS1(PSMContentDownloader,nsIStreamListener) +NS_IMPL_ISUPPORTS2(PSMContentDownloader, nsIStreamListener, nsIRequestObserver) const PRInt32 kDefaultCertAllocLength = 2048; diff --git a/mozilla/security/manager/ssl/src/nsNSSComponent.h b/mozilla/security/manager/ssl/src/nsNSSComponent.h index 39eb65ed98e..545ed748a4b 100644 --- a/mozilla/security/manager/ssl/src/nsNSSComponent.h +++ b/mozilla/security/manager/ssl/src/nsNSSComponent.h @@ -251,7 +251,7 @@ private: nsresult RegisterPSMContentListener(); nsresult RegisterObservers(); nsresult DownloadCrlSilently(); - nsresult PostCRLImportEvent(nsCAutoString *urlString, PSMContentDownloader *psmDownloader); + nsresult PostCRLImportEvent(const nsCSubstring &urlString, nsIStreamListener *psmDownloader); nsresult getParamsForNextCrlToDownload(nsAutoString *url, PRTime *time, nsAutoString *key); nsresult DispatchEventToWindow(nsIDOMWindow *domWin, const nsAString &eventType, const nsAString &token); PRLock *mutex; diff --git a/mozilla/security/manager/ssl/src/nsNSSEvent.cpp b/mozilla/security/manager/ssl/src/nsNSSEvent.cpp deleted file mode 100644 index 1f63c6c6d14..00000000000 --- a/mozilla/security/manager/ssl/src/nsNSSEvent.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the mozilla.org. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 2001 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * Javier Delgadillo - * Robert Relyea - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "nsCOMPtr.h" -#include "nsIServiceManager.h" -#include "nsNSSEvent.h" -#include "plevent.h" -#include "nsIRunnable.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" - -// -// This is the class we'll use to post ui events -// -struct nsNSSEventRunnable : PLEvent { - nsNSSEventRunnable(nsIRunnable* runnable); - ~nsNSSEventRunnable(); - - nsCOMPtr mRunnable; -}; - -//Grab the UI event queue so that we can post some events to it. -already_AddRefed -nsNSSEventGetUIEventQueue() -{ - nsresult rv; - nsCOMPtr service = - do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return nsnull; - - nsIEventQueue* result = nsnull; - rv = service->GetThreadEventQueue(NS_UI_THREAD, &result); - if (NS_FAILED(rv)) - return nsnull; - - return result; -} - -// post something to it -nsresult -nsNSSEventPostToUIEventQueue(nsIRunnable *event) -{ - nsNSSEventRunnable *runnable = new nsNSSEventRunnable(event); - if (!runnable) { - return NS_ERROR_OUT_OF_MEMORY; - } - nsCOMPtruiQueue = nsNSSEventGetUIEventQueue(); - uiQueue->PostEvent(runnable); - return NS_OK; -} - -//A wrapper for PLEvent that we can use to post -//our nsIRunnable Events. -static void PR_CALLBACK -handleNSSEventRunnable(nsNSSEventRunnable* aEvent) -{ - aEvent->mRunnable->Run(); -} - -static void PR_CALLBACK -destroyNSSEventRunnable(nsNSSEventRunnable* aEvent) -{ - delete aEvent; -} - -nsNSSEventRunnable::nsNSSEventRunnable(nsIRunnable* runnable) - : mRunnable(runnable) -{ - PL_InitEvent(this, nsnull, PLHandleEventProc(handleNSSEventRunnable), - PLDestroyEventProc(&destroyNSSEventRunnable)); -} - -nsNSSEventRunnable::~nsNSSEventRunnable() -{ -} - diff --git a/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp b/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp index 085a6599581..3691c27472f 100644 --- a/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -63,11 +63,13 @@ #include "nsReadableUtils.h" #include "nsHashSets.h" #include "nsCRT.h" +#include "nsAutoPtr.h" #include "nsPrintfCString.h" #include "nsAutoLock.h" #include "nsSSLThread.h" #include "nsNSSShutDown.h" #include "nsNSSCertHelper.h" +#include "nsThreadUtils.h" #include "ssl.h" #include "secerr.h" @@ -298,16 +300,12 @@ nsNSSSocketInfo::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) return NS_OK; } - nsCOMPtr proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID)); - if (!proxyman) - return NS_ERROR_FAILURE; - nsCOMPtr proxiedCallbacks; - proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIInterfaceRequestor), - NS_STATIC_CAST(nsIInterfaceRequestor*,aCallbacks), - PROXY_SYNC, - getter_AddRefs(proxiedCallbacks)); + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIInterfaceRequestor), + NS_STATIC_CAST(nsIInterfaceRequestor*,aCallbacks), + NS_PROXY_SYNC, + getter_AddRefs(proxiedCallbacks)); mCallbacks = proxiedCallbacks; return NS_OK; @@ -478,36 +476,31 @@ void nsSSLIOLayerHelpers::Cleanup() static nsresult displayAlert(nsAFlatString &formattedString, nsNSSSocketInfo *infoObject) { - - // The interface requestor object may not be safe, so - // proxy the call to get the nsIPrompt. + // The interface requestor object may not be safe, so proxy the call to get + // the nsIPrompt. - nsCOMPtr proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID)); - if (!proxyman) - return NS_ERROR_FAILURE; - - nsCOMPtr proxiedCallbacks; - proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIInterfaceRequestor), - NS_STATIC_CAST(nsIInterfaceRequestor*,infoObject), - PROXY_SYNC, - getter_AddRefs(proxiedCallbacks)); + nsCOMPtr proxiedCallbacks; + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIInterfaceRequestor), + NS_STATIC_CAST(nsIInterfaceRequestor*, infoObject), + NS_PROXY_SYNC, + getter_AddRefs(proxiedCallbacks)); - nsCOMPtr prompt (do_GetInterface(proxiedCallbacks)); - - if (!prompt) - return NS_ERROR_NO_INTERFACE; + nsCOMPtr prompt (do_GetInterface(proxiedCallbacks)); + if (!prompt) + return NS_ERROR_NO_INTERFACE; - nsCOMPtr proxyPrompt; - // Finally, get a proxy for the nsIPrompt - proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIPrompt), - prompt, - PROXY_SYNC, - getter_AddRefs(proxyPrompt)); - proxyPrompt->Alert(nsnull, formattedString.get()); - return NS_OK; - + // Finally, get a proxy for the nsIPrompt + + nsCOMPtr proxyPrompt; + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIPrompt), + prompt, + NS_PROXY_SYNC, + getter_AddRefs(proxyPrompt)); + + proxyPrompt->Alert(nsnull, formattedString.get()); + return NS_OK; } static nsresult @@ -1484,12 +1477,13 @@ nsContinueDespiteCertError(nsNSSSocketInfo *infoObject, infoObject->GetNotificationCallbacks(getter_AddRefs(callbacks)); if (callbacks) { nsCOMPtr handler = do_GetInterface(callbacks); - if (handler) - NS_GetProxyForObject(NS_UI_THREAD_EVENTQ, + if (handler) { + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIBadCertListener), handler, - PROXY_SYNC, + NS_PROXY_SYNC, (void**)&badCertHandler); + } } if (!badCertHandler) { rv = getNSSDialogs((void**)&badCertHandler, @@ -2093,7 +2087,7 @@ SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket, char* extracted = NULL; PRIntn keyError = 0; /* used for private key retrieval error */ SSM_UserCertChoice certChoice; - PRUint32 NumberOfCerts = 0; + PRInt32 NumberOfCerts = 0; /* do some argument checking */ if (socket == NULL || caNames == NULL || pRetCert == NULL || diff --git a/mozilla/security/manager/ssl/src/nsPKCS12Blob.cpp b/mozilla/security/manager/ssl/src/nsPKCS12Blob.cpp index 504dcd23e14..5cd4f0851bb 100644 --- a/mozilla/security/manager/ssl/src/nsPKCS12Blob.cpp +++ b/mozilla/security/manager/ssl/src/nsPKCS12Blob.cpp @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -/* $Id: nsPKCS12Blob.cpp,v 1.46 2006-02-03 14:18:28 cbiesinger%web.de Exp $ */ +/* $Id: nsPKCS12Blob.cpp,v 1.47 2006-05-10 17:29:56 darin%meer.net Exp $ */ #include "prmem.h" #include "prprf.h" @@ -47,6 +47,7 @@ #include "nsIWindowWatcher.h" #include "nsIPrompt.h" #include "nsProxiedService.h" +#include "nsThreadUtils.h" #include "nsNSSComponent.h" #include "nsNSSHelper.h" @@ -843,18 +844,15 @@ nsPKCS12Blob::handleError(int myerr) PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("PKCS12: I called(%d)", myerr)); nsCOMPtr nssComponent(do_GetService(kNSSComponentCID, &rv)); if (NS_FAILED(rv)) return PR_FALSE; - nsCOMPtr proxyman( - do_GetService(NS_XPCOMPROXY_CONTRACTID)); - if (!proxyman) return PR_FALSE; nsCOMPtr errPrompt; nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); if (wwatch) { wwatch->GetNewPrompter(0, getter_AddRefs(errPrompt)); if (errPrompt) { nsCOMPtr proxyPrompt; - proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIPrompt), - errPrompt, PROXY_SYNC, - getter_AddRefs(proxyPrompt)); + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIPrompt), errPrompt, + NS_PROXY_SYNC, getter_AddRefs(proxyPrompt)); if (!proxyPrompt) return PR_FALSE; } else { return PR_FALSE; diff --git a/mozilla/security/manager/ssl/src/nsSDR.cpp b/mozilla/security/manager/ssl/src/nsSDR.cpp index 1b96c5e4d63..8491d025ecf 100644 --- a/mozilla/security/manager/ssl/src/nsSDR.cpp +++ b/mozilla/security/manager/ssl/src/nsSDR.cpp @@ -44,7 +44,7 @@ #include "nsMemory.h" #include "nsString.h" #include "nsCOMPtr.h" -#include "nsISupports.h" +#include "nsThreadUtils.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIServiceManager.h" @@ -95,17 +95,16 @@ nsSDRContext::~nsSDRContext() NS_IMETHODIMP nsSDRContext::GetInterface(const nsIID & uuid, void * *result) { if (uuid.Equals(NS_GET_IID(nsIPrompt))) { - nsCOMPtr proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID)); - if (!proxyman) return NS_ERROR_FAILURE; - nsCOMPtr prompter; nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); if (wwatch) { wwatch->GetNewPrompter(0, getter_AddRefs(prompter)); if (prompter) { nsCOMPtr proxyPrompt; - proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIPrompt), - prompter, PROXY_SYNC, getter_AddRefs(proxyPrompt)); + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIPrompt), + prompter, NS_PROXY_SYNC, + getter_AddRefs(proxyPrompt)); if (!proxyPrompt) return NS_ERROR_FAILURE; *result = proxyPrompt; NS_ADDREF((nsIPrompt*)*result); diff --git a/mozilla/security/manager/ssl/src/nsSSLThread.cpp b/mozilla/security/manager/ssl/src/nsSSLThread.cpp index 06d543ffde0..990fb4d42f9 100644 --- a/mozilla/security/manager/ssl/src/nsSSLThread.cpp +++ b/mozilla/security/manager/ssl/src/nsSSLThread.cpp @@ -35,7 +35,7 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsIThread.h" +#include "nsThreadUtils.h" #include "nsSSLThread.h" #include "nsAutoLock.h" #include "nsNSSIOLayer.h" @@ -300,7 +300,7 @@ PRStatus nsSSLThread::requestClose(nsNSSSocketInfo *si) if (requestToCancel) { - if (nsIThread::IsMainThread()) + if (NS_IsMainThread()) { requestToCancel->Cancel(NS_ERROR_ABORT); } diff --git a/mozilla/storage/src/mozStorageAsyncIO.cpp b/mozilla/storage/src/mozStorageAsyncIO.cpp index abcb071d93c..5753ffc7d94 100644 --- a/mozilla/storage/src/mozStorageAsyncIO.cpp +++ b/mozilla/storage/src/mozStorageAsyncIO.cpp @@ -232,7 +232,7 @@ #include "mozStorageService.h" #include "nsAutoLock.h" -#include "nsEventQueueUtils.h" +#include "nsThreadUtils.h" #include "nsIRunnable.h" #include "nsIThread.h" #include "nsMemory.h" @@ -447,12 +447,12 @@ public: // this will delay processing the release of the storage service until we // get to the main thread. - nsCOMPtr eventQueue; - nsresult rv = NS_GetMainEventQ(getter_AddRefs(eventQueue)); + nsCOMPtr mainThread; + nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread)); if (NS_SUCCEEDED(rv)) { mozIStorageService* service = nsnull; mStorageService.swap(service); - NS_ProxyRelease(eventQueue, service); + NS_ProxyRelease(mainThread, service); } else { NS_NOTREACHED("No event queue"); } @@ -511,10 +511,7 @@ mozStorageService::InitStorageAsyncIO() if (! thread) return NS_ERROR_OUT_OF_MEMORY; - nsresult rv = NS_NewThread(&AsyncWriteThreadInstance, - thread, - 0, - PR_JOINABLE_THREAD); + nsresult rv = NS_NewThread(&AsyncWriteThreadInstance, thread); if (NS_FAILED(rv)) { AsyncWriteThreadInstance = nsnull; return rv; @@ -552,7 +549,7 @@ mozStorageService::FinishAsyncIO() } // now we join with the writer thread - AsyncWriteThreadInstance->Join(); + AsyncWriteThreadInstance->Shutdown(); // release the thread and enter single-threaded mode NS_RELEASE(AsyncWriteThreadInstance); diff --git a/mozilla/storage/src/mozStorageService.cpp b/mozilla/storage/src/mozStorageService.cpp index 408bc47bd3e..a06f4fce551 100644 --- a/mozilla/storage/src/mozStorageService.cpp +++ b/mozilla/storage/src/mozStorageService.cpp @@ -40,8 +40,8 @@ #include "mozStorageService.h" #include "mozStorageConnection.h" +#include "nsThreadUtils.h" #include "nsCRT.h" -#include "nsIThread.h" #include "plstr.h" #include "sqlite3.h" @@ -52,7 +52,7 @@ NS_IMPL_THREADSAFE_ISUPPORTS2(mozStorageService, mozIStorageService, nsIObserver // XXX this sucks that we have to pull in nsIFile and all that // just to use NS_GetSpecialDirectory -static const char* gQuitApplicationMessage = "quit-application"; +static const char kShutdownMessage[] = "xpcom-shutdown-threads"; mozStorageService::mozStorageService() { @@ -71,7 +71,7 @@ mozStorageService::Init() // InitStorageAsyncIO function creates a thread which is joined with the // main thread during shutdown. If the thread is created from a random // thread, we'll join to the wrong parent. - NS_ENSURE_STATE(nsIThread::IsMainThread()); + NS_ENSURE_STATE(NS_IsMainThread()); // this makes multiple connections to the same database share the same pager // cache. @@ -85,7 +85,7 @@ mozStorageService::Init() rv = InitStorageAsyncIO(); NS_ENSURE_SUCCESS(rv, rv); - rv = observerService->AddObserver(this, gQuitApplicationMessage, PR_FALSE); + rv = observerService->AddObserver(this, kShutdownMessage, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; @@ -156,7 +156,7 @@ mozStorageService::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { nsresult rv; - if (nsCRT::strcmp(aTopic, gQuitApplicationMessage) == 0) { + if (nsCRT::strcmp(aTopic, kShutdownMessage) == 0) { rv = FinishAsyncIO(); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/mozilla/toolkit/components/downloads/src/nsDownloadManager.cpp b/mozilla/toolkit/components/downloads/src/nsDownloadManager.cpp index a00413d2f07..c2f65a9c1c8 100644 --- a/mozilla/toolkit/components/downloads/src/nsDownloadManager.cpp +++ b/mozilla/toolkit/components/downloads/src/nsDownloadManager.cpp @@ -239,6 +239,11 @@ nsDownloadManager::Init() // completely initialized), but the observerservice would still keep a reference // to us and notify us about shutdown, which may cause crashes. // failure to add an observer is not critical + // + // These observers will be cleaned up automatically at app shutdown. We do + // not bother explicitly breaking the observers because we are a singleton + // that lives for the duration of the app. + // gObserverService->AddObserver(this, "quit-application", PR_FALSE); gObserverService->AddObserver(this, "quit-application-requested", PR_FALSE); gObserverService->AddObserver(this, "offline-requested", PR_FALSE); diff --git a/mozilla/toolkit/components/startup/src/nsAppStartup.cpp b/mozilla/toolkit/components/startup/src/nsAppStartup.cpp index 7f8cff46470..ae39b2353a4 100644 --- a/mozilla/toolkit/components/startup/src/nsAppStartup.cpp +++ b/mozilla/toolkit/components/startup/src/nsAppStartup.cpp @@ -44,8 +44,6 @@ #include "nsIAppShellService.h" #include "nsICloseAllWindows.h" #include "nsIDOMWindowInternal.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" #include "nsIInterfaceRequestor.h" #include "nsILocalFile.h" #include "nsIObserverService.h" @@ -61,16 +59,35 @@ #include "nsIWindowWatcher.h" #include "nsIXULWindow.h" #include "nsNativeCharsetUtils.h" +#include "nsThreadUtils.h" +#include "nsAutoPtr.h" #include "prprf.h" #include "nsCRT.h" -#include "nsEventQueueUtils.h" #include "nsIInterfaceRequestorUtils.h" #include "nsWidgetsCID.h" #include "nsAppShellCID.h" #include "nsXPFEComponentsCID.h" -NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); +static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); + +class nsAppExitEvent : public nsRunnable { +private: + nsRefPtr mService; + +public: + nsAppExitEvent(nsAppStartup *service) : mService(service) {} + + NS_IMETHOD Run() { + // Tell the appshell to exit + mService->mAppShell->Exit(); + + // We're done "shutting down". + mService->mShuttingDown = PR_FALSE; + mService->mRunning = PR_FALSE; + return NS_OK; + } +}; // // nsAppStartup @@ -91,21 +108,13 @@ nsAppStartup::Init() nsresult rv; // Create widget application shell - mAppShell = do_CreateInstance(kAppShellCID, &rv); + mAppShell = do_GetService(kAppShellCID, &rv); NS_ENSURE_SUCCESS(rv, rv); - rv = mAppShell->Create(nsnull, nsnull); - NS_ENSURE_SUCCESS(rv, rv); - - // listen to EventQueues' comings and goings. do this after the appshell - // has been created, but after the event queue has been created. that - // latter bit is unfortunate, but we deal with it. nsCOMPtr os (do_GetService("@mozilla.org/observer-service;1", &rv)); NS_ENSURE_SUCCESS(rv, rv); - os->AddObserver(this, "nsIEventQueueActivated", PR_TRUE); - os->AddObserver(this, "nsIEventQueueDestroyed", PR_TRUE); os->AddObserver(this, "profile-change-teardown", PR_TRUE); os->AddObserver(this, "xul-window-registered", PR_TRUE); os->AddObserver(this, "xul-window-destroyed", PR_TRUE); @@ -173,7 +182,7 @@ nsAppStartup::Quit(PRUint32 aMode) PRUint32 ferocity = (aMode & 0xF); // Quit the application. We will asynchronously call the appshell's - // Exit() method via HandleExitEvent() to allow one last pass + // Exit() method via nsAppExitEvent to allow one last pass // through any events in the queue. This guarantees a tidy cleanup. nsresult rv = NS_OK; PRBool postedExitEvent = PR_FALSE; @@ -296,28 +305,13 @@ nsAppStartup::Quit(PRUint32 aMode) // no matter what, make sure we send the exit event. If // worst comes to worst, we'll do a leaky shutdown but we WILL // shut down. Well, assuming that all *this* stuff works ;-). - nsCOMPtr queue; - rv = NS_GetMainEventQ(getter_AddRefs(queue)); + nsCOMPtr event = new nsAppExitEvent(this); + rv = NS_DispatchToCurrentThread(event); if (NS_SUCCEEDED(rv)) { - PLEvent* event = new PLEvent; - if (event) { - NS_ADDREF_THIS(); - PL_InitEvent(event, - this, - HandleExitEvent, - DestroyExitEvent); - - rv = queue->PostEvent(event); - if (NS_SUCCEEDED(rv)) { - postedExitEvent = PR_TRUE; - } - else { - PL_DestroyEvent(event); - } - } - else { - rv = NS_ERROR_OUT_OF_MEMORY; - } + postedExitEvent = PR_TRUE; + } + else { + NS_WARNING("failed to dispatch nsAppExitEvent"); } } } @@ -371,33 +365,6 @@ nsAppStartup::ExitLastWindowClosingSurvivalArea(void) return NS_OK; } - -void* PR_CALLBACK -nsAppStartup::HandleExitEvent(PLEvent* aEvent) -{ - nsAppStartup *service = - NS_REINTERPRET_CAST(nsAppStartup*, aEvent->owner); - - // Tell the appshell to exit - service->mAppShell->Exit(); - - // We're done "shutting down". - service->mShuttingDown = PR_FALSE; - service->mRunning = PR_FALSE; - - return nsnull; -} - -void PR_CALLBACK -nsAppStartup::DestroyExitEvent(PLEvent* aEvent) -{ - nsAppStartup *service = - NS_REINTERPRET_CAST(nsAppStartup*, aEvent->owner); - NS_RELEASE(service); - delete aEvent; -} - - // // nsAppStartup->nsIWindowCreator // @@ -477,25 +444,7 @@ nsAppStartup::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { NS_ASSERTION(mAppShell, "appshell service notified before appshell built"); - if (!strcmp(aTopic, "nsIEventQueueActivated")) { - nsCOMPtr eq(do_QueryInterface(aSubject)); - if (eq) { - PRBool isNative = PR_TRUE; - // we only add native event queues to the appshell - eq->IsQueueNative(&isNative); - if (isNative) - mAppShell->ListenToEventQueue(eq, PR_TRUE); - } - } else if (!strcmp(aTopic, "nsIEventQueueDestroyed")) { - nsCOMPtr eq(do_QueryInterface(aSubject)); - if (eq) { - PRBool isNative = PR_TRUE; - // we only remove native event queues from the appshell - eq->IsQueueNative(&isNative); - if (isNative) - mAppShell->ListenToEventQueue(eq, PR_FALSE); - } - } else if (!strcmp(aTopic, "profile-change-teardown")) { + if (!strcmp(aTopic, "profile-change-teardown")) { nsresult rv; EnterLastWindowClosingSurvivalArea(); // NOTE: No early error exits because we need to execute the diff --git a/mozilla/toolkit/components/startup/src/nsAppStartup.h b/mozilla/toolkit/components/startup/src/nsAppStartup.h index e6c4bd86908..53a1c852351 100644 --- a/mozilla/toolkit/components/startup/src/nsAppStartup.h +++ b/mozilla/toolkit/components/startup/src/nsAppStartup.h @@ -75,9 +75,7 @@ private: void AttemptingQuit(PRBool aAttempt); - // A "last event" that is used to flush the appshell's event queue. - PR_STATIC_CALLBACK(void*) HandleExitEvent(PLEvent* aEvent); - PR_STATIC_CALLBACK(void) DestroyExitEvent(PLEvent* aEvent); + friend class nsAppExitEvent; nsCOMPtr mAppShell; diff --git a/mozilla/toolkit/xre/nsAppRunner.cpp b/mozilla/toolkit/xre/nsAppRunner.cpp index 21bb7070b0a..50609dcd8ab 100644 --- a/mozilla/toolkit/xre/nsAppRunner.cpp +++ b/mozilla/toolkit/xre/nsAppRunner.cpp @@ -54,7 +54,6 @@ #ifdef XP_OS2 #include "private/pprthred.h" #endif -#include "plevent.h" #include "prmem.h" #include "prnetdb.h" #include "prprf.h" @@ -73,7 +72,6 @@ #include "nsIContentHandler.h" #include "nsIDialogParamBlock.h" #include "nsIDOMWindow.h" -#include "nsIEventQueueService.h" #include "nsIExtensionManager.h" #include "nsIFastLoadService.h" // for PLATFORM_FASL_SUFFIX #include "nsIGenericFactory.h" @@ -539,7 +537,6 @@ public: nsresult Initialize(); nsresult DoAutoreg(); nsresult RegisterProfileService(nsIToolkitProfileService* aProfileService); - nsresult InitEventQueue(); nsresult SetWindowCreator(nsINativeAppSupport* native); private: @@ -634,21 +631,6 @@ ScopedXPCOMStartup::RegisterProfileService(nsIToolkitProfileService* aProfileSer factory); } -nsresult -ScopedXPCOMStartup::InitEventQueue() -{ - NS_TIMELINE_ENTER("init event service"); - nsresult rv; - - nsCOMPtr eventQService(do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = eventQService->CreateThreadEventQueue(); - NS_TIMELINE_LEAVE("init event service"); - - return rv; -} - nsresult ScopedXPCOMStartup::DoAutoreg() { @@ -1251,7 +1233,6 @@ ProfileLockedDialog(nsILocalFile* aProfileDir, nsILocalFile* aProfileLocalDir, NS_ENSURE_SUCCESS(rv, rv); rv = xpcom.DoAutoreg(); - rv |= xpcom.InitEventQueue(); rv |= xpcom.SetWindowCreator(aNative); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); @@ -1328,7 +1309,6 @@ ShowProfileManager(nsIToolkitProfileService* aProfileSvc, rv = xpcom.RegisterProfileService(aProfileSvc); rv |= xpcom.DoAutoreg(); - rv |= xpcom.InitEventQueue(); rv |= xpcom.SetWindowCreator(aNative); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); @@ -2203,7 +2183,6 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) rv = xpcom.Initialize(); NS_ENSURE_SUCCESS(rv, 1); rv = xpcom.DoAutoreg(); - rv |= xpcom.InitEventQueue(); rv |= xpcom.SetWindowCreator(nativeApp); NS_ENSURE_SUCCESS(rv, 1); diff --git a/mozilla/toolkit/xre/nsEmbedFunctions.cpp b/mozilla/toolkit/xre/nsEmbedFunctions.cpp index 4725d8815e6..2cd9f4f60bf 100644 --- a/mozilla/toolkit/xre/nsEmbedFunctions.cpp +++ b/mozilla/toolkit/xre/nsEmbedFunctions.cpp @@ -41,7 +41,6 @@ #include "nsIAppStartupNotifier.h" #include "nsIDirectoryService.h" -#include "nsIEventQueueService.h" #include "nsILocalFile.h" #include "nsIToolkitChromeRegistry.h" @@ -131,15 +130,6 @@ XRE_InitEmbedding(nsILocalFile *aLibXULDirectory, // to autoregister every time (for instance, if it's debug), it can do // so after we return from this function. - nsCOMPtr eventQService - (do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv)); - if (NS_FAILED(rv)) - return rv; - - rv = eventQService->CreateThreadEventQueue(); - if (NS_FAILED(rv)) - return rv; - nsCOMPtr startupNotifier (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID)); if (!startupNotifier) diff --git a/mozilla/tools/test-harness/xpcshell-simple/head.js b/mozilla/tools/test-harness/xpcshell-simple/head.js index 6342570a945..a34938b1c4f 100644 --- a/mozilla/tools/test-harness/xpcshell-simple/head.js +++ b/mozilla/tools/test-harness/xpcshell-simple/head.js @@ -39,13 +39,8 @@ // This file contains common code that is loaded with each test file. -const nsIEventQueueService = Components.interfaces.nsIEventQueueService; -const nsIEventQueue = Components.interfaces.nsIEventQueue; - -var _eqs; var _quit = false; var _fail = false; -var _running_event_loop = false; var _tests_pending = 0; function _TimerCallback(expr) { @@ -75,29 +70,20 @@ function do_main() { return; dump("*** running event loop\n"); - var eq = _eqs.getSpecialEventQueue(_eqs.CURRENT_THREAD_EVENT_QUEUE); + var thr = Components.classes["@mozilla.org/thread-manager;1"] + .getService().currentThread; - _running_event_loop = true; - eq.eventLoop(); // unblocked via interrupt from do_quit() - _running_event_loop = false; + while (!_quit) + thr.processNextEvent(); - // process any remaining events before exiting - eq.processPendingEvents(); - eq.stopAcceptingEvents(); - eq.processPendingEvents(); + while (thr.hasPendingEvents()) + thr.processNextEvent(); } function do_quit() { dump("*** exiting\n"); _quit = true; - - if (_running_event_loop) { - // interrupt the current thread to make eventLoop return. - var thr = Components.classes["@mozilla.org/thread;1"] - .createInstance(Components.interfaces.nsIThread); - thr.currentThread.interrupt(); - } } function do_throw(text) { @@ -132,8 +118,3 @@ function do_test_finished() { if (--_tests_pending == 0) do_quit(); } - -// setup the main thread event queue -_eqs = Components.classes["@mozilla.org/event-queue-service;1"] - .getService(nsIEventQueueService); -_eqs.createMonitoredThreadEventQueue(); diff --git a/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp b/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp index 475c4f65ebd..9a9b20dcc48 100644 --- a/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -61,6 +61,7 @@ #include "nsIRequest.h" #include "nsDirectoryServiceDefs.h" #include "nsIInterfaceRequestor.h" +#include "nsThreadUtils.h" #include "nsAutoPtr.h" // used to manage our in memory data source of helper applications @@ -1075,47 +1076,26 @@ NS_IMETHODIMP nsExternalHelperAppService::LoadUrl(nsIURI * aURL) // that existing callers aren't expecting. We must do it on an event // callback to make sure we don't hang someone up. -struct extLoadRequest : PLEvent { - nsCOMPtr uri; - nsCOMPtr prompt; +class nsExternalLoadRequest : public nsRunnable { + public: + nsExternalLoadRequest(nsIURI *uri, nsIPrompt *prompt) + : mURI(uri), mPrompt(prompt) {} + + NS_IMETHOD Run() { + if (sSrv && sSrv->isExternalLoadOK(mURI, mPrompt)) + sSrv->LoadUriInternal(mURI); + return NS_OK; + } + + private: + nsCOMPtr mURI; + nsCOMPtr mPrompt; }; -void *PR_CALLBACK -nsExternalHelperAppService::handleExternalLoadEvent(PLEvent *event) -{ - extLoadRequest* req = NS_STATIC_CAST(extLoadRequest*, event); - if (req && sSrv && sSrv->isExternalLoadOK(req->uri, req->prompt)) - sSrv->LoadUriInternal(req->uri); - - return nsnull; -} - -static void PR_CALLBACK destroyExternalLoadEvent(PLEvent *event) -{ - delete NS_STATIC_CAST(extLoadRequest*, event); -} - NS_IMETHODIMP nsExternalHelperAppService::LoadURI(nsIURI * aURL, nsIPrompt * aPrompt) { - // post external load event - nsCOMPtr eventQ; - nsresult rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ)); - if (NS_FAILED(rv)) - return rv; - - extLoadRequest *event = new extLoadRequest; - if (!event) - return NS_ERROR_OUT_OF_MEMORY; - - event->uri = aURL; - event->prompt = aPrompt; - PL_InitEvent(event, nsnull, handleExternalLoadEvent, destroyExternalLoadEvent); - - rv = eventQ->PostEvent(event); - if (NS_FAILED(rv)) - PL_DestroyEvent(event); - - return rv; + nsCOMPtr event = new nsExternalLoadRequest(aURL, aPrompt); + return NS_DispatchToCurrentThread(event); } // helper routines used by LoadURI to check whether we're allowed diff --git a/mozilla/uriloader/exthandler/nsExternalHelperAppService.h b/mozilla/uriloader/exthandler/nsExternalHelperAppService.h index bbf2fbdfa70..803fecb1db1 100644 --- a/mozilla/uriloader/exthandler/nsExternalHelperAppService.h +++ b/mozilla/uriloader/exthandler/nsExternalHelperAppService.h @@ -73,7 +73,6 @@ #include "nsCOMArray.h" #include "nsWeakReference.h" #include "nsIPrompt.h" -#include "nsEventQueueUtils.h" class nsExternalAppHandler; class nsIMIMEInfo; @@ -283,6 +282,7 @@ protected: #endif // friend, so that it can access the nspr log module and FixFilePermissions friend class nsExternalAppHandler; + friend class nsExternalLoadRequest; /** * Functions related to the tempory file cleanup service provided by @@ -300,9 +300,6 @@ protected: virtual NS_HIDDEN_(nsresult) LoadUriInternal(nsIURI * aURL) = 0; NS_HIDDEN_(PRBool) isExternalLoadOK(nsIURI* aURI, nsIPrompt* aPrompt); NS_HIDDEN_(PRBool) promptForScheme(nsIURI* aURI, nsIPrompt* aPrompt, PRBool *aRemember); - - // friend event handler that accesses the external loading functions - static void *PR_CALLBACK handleExternalLoadEvent(PLEvent *event); }; /** diff --git a/mozilla/uriloader/exthandler/nsExternalProtocolHandler.cpp b/mozilla/uriloader/exthandler/nsExternalProtocolHandler.cpp index 31ede59d686..359e83c4733 100644 --- a/mozilla/uriloader/exthandler/nsExternalProtocolHandler.cpp +++ b/mozilla/uriloader/exthandler/nsExternalProtocolHandler.cpp @@ -51,7 +51,6 @@ #include "nsIStringBundle.h" #include "nsIPrefService.h" #include "nsIPrompt.h" -#include "nsEventQueueUtils.h" #include "nsNetUtil.h" // used to dispatch urls to default protocol handlers diff --git a/mozilla/view/src/nsViewManager.cpp b/mozilla/view/src/nsViewManager.cpp index 0463720c8bf..dd88bca6938 100644 --- a/mozilla/view/src/nsViewManager.cpp +++ b/mozilla/view/src/nsViewManager.cpp @@ -53,8 +53,6 @@ #include "nsISupportsArray.h" #include "nsICompositeListener.h" #include "nsCOMPtr.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" #include "nsIServiceManager.h" #include "nsGUIEvent.h" #include "nsIPrefBranch.h" @@ -64,6 +62,7 @@ #include "nsScrollPortView.h" #include "nsHashtable.h" #include "nsCOMArray.h" +#include "nsThreadUtils.h" #ifdef MOZ_CAIRO_GFX #include "gfxContext.h" @@ -72,7 +71,6 @@ static NS_DEFINE_IID(kBlenderCID, NS_BLENDER_CID); static NS_DEFINE_IID(kRegionCID, NS_REGION_CID); static NS_DEFINE_IID(kRenderingContextCID, NS_RENDERING_CONTEXT_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); #define ARENA_ALLOCATE(var, pool, type) \ {void *_tmp_; PL_ARENA_ALLOCATE(_tmp_, pool, sizeof(type)); \ @@ -103,46 +101,14 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); //-------------- Begin Invalidate Event Definition ------------------------ -struct nsViewManagerEvent : public PLEvent { - nsViewManagerEvent(nsViewManager* aViewManager); - - virtual void HandleEvent() = 0; - - nsViewManager* ViewManager() { - // |owner| is a weak pointer, but the view manager will destroy any - // pending invalidate events in it's destructor. - return NS_STATIC_CAST(nsViewManager*, owner); - } -}; +class nsInvalidateEvent : public nsViewManagerEvent { +public: + nsInvalidateEvent(nsViewManager *vm) : nsViewManagerEvent(vm) {} -static void* PR_CALLBACK HandlePLEvent(PLEvent* aEvent) -{ - NS_ASSERTION(nsnull != aEvent,"Event is null"); - nsViewManagerEvent *event = NS_STATIC_CAST(nsViewManagerEvent*, aEvent); - - event->HandleEvent(); - return nsnull; -} - -static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent) -{ - NS_ASSERTION(nsnull != aEvent,"Event is null"); - nsViewManagerEvent *event = NS_STATIC_CAST(nsViewManagerEvent*, aEvent); - delete event; -} - -nsViewManagerEvent::nsViewManagerEvent(nsViewManager* aViewManager) -{ - NS_ASSERTION(aViewManager, "null parameter"); - PL_InitEvent(this, aViewManager, ::HandlePLEvent, ::DestroyPLEvent); -} - -struct nsInvalidateEvent : public nsViewManagerEvent { - nsInvalidateEvent(nsViewManager* aViewManager) - : nsViewManagerEvent(aViewManager) { } - - virtual void HandleEvent() { - ViewManager()->ProcessInvalidateEvent(); + NS_IMETHOD Run() { + if (mViewManager) + mViewManager->ProcessInvalidateEvent(); + return NS_OK; } }; @@ -169,16 +135,14 @@ void nsViewManager::PostInvalidateEvent() { NS_ASSERTION(IsRootVM(), "Caller screwed up"); - - nsCOMPtr eventQueue; - mEventQueueService->GetSpecialEventQueue( - nsIEventQueueService::UI_THREAD_EVENT_QUEUE, getter_AddRefs(eventQueue)); - NS_ASSERTION(nsnull != eventQueue, "Event queue is null"); - if (eventQueue != mInvalidateEventQueue) { - nsInvalidateEvent* ev = new nsInvalidateEvent(this); - eventQueue->PostEvent(ev); - mInvalidateEventQueue = eventQueue; + if (!mInvalidateEvent.IsPending()) { + nsRefPtr ev = new nsInvalidateEvent(this); + if (NS_FAILED(NS_DispatchToCurrentThread(ev))) { + NS_WARNING("failed to dispatch nsInvalidateEvent"); + } else { + mInvalidateEvent = ev; + } } } @@ -229,16 +193,10 @@ nsViewManager::~nsViewManager() mRootView = nsnull; } - // Make sure to RevokeEvents for all viewmanagers, since some events + // Make sure to revoke pending events for all viewmanagers, since some events // are posted by a non-root viewmanager. - if (mInvalidateEventQueue) { - mInvalidateEventQueue->RevokeEvents(this); - mInvalidateEventQueue = nsnull; - } - if (mSynthMouseMoveEventQueue) { - mSynthMouseMoveEventQueue->RevokeEvents(this); - mSynthMouseMoveEventQueue = nsnull; - } + mInvalidateEvent.Revoke(); + mSynthMouseMoveEvent.Revoke(); if (!IsRootVM()) { // We have a strong ref to mRootViewManager @@ -335,11 +293,6 @@ NS_IMETHODIMP nsViewManager::Init(nsIDeviceContext* aContext) mMouseGrabber = nsnull; mKeyGrabber = nsnull; - if (nsnull == mEventQueueService) { - mEventQueueService = do_GetService(kEventQueueServiceCID); - NS_ASSERTION(mEventQueueService, "couldn't get event queue service"); - } - return NS_OK; } @@ -2856,7 +2809,7 @@ nsViewManager::ProcessInvalidateEvent() if (processEvent) { FlushPendingInvalidates(); } - mInvalidateEventQueue = nsnull; + mInvalidateEvent.Forget(); if (!processEvent) { // We didn't actually process this event... post a new one PostInvalidateEvent(); @@ -2885,17 +2838,21 @@ nsViewManager::GetLastUserEventTime(PRUint32& aTime) return NS_OK; } -struct nsSynthMouseMoveEvent : public nsViewManagerEvent { - nsSynthMouseMoveEvent(nsViewManager *aViewManager, PRBool aFromScroll) +class nsSynthMouseMoveEvent : public nsViewManagerEvent { +public: + nsSynthMouseMoveEvent(nsViewManager *aViewManager, + PRBool aFromScroll) : nsViewManagerEvent(aViewManager), - mFromScroll(aFromScroll) - { + mFromScroll(aFromScroll) { } - virtual void HandleEvent() { - ViewManager()->ProcessSynthMouseMoveEvent(mFromScroll); + NS_IMETHOD Run() { + if (mViewManager) + mViewManager->ProcessSynthMouseMoveEvent(mFromScroll); + return NS_OK; } +private: PRBool mFromScroll; }; @@ -2905,15 +2862,16 @@ nsViewManager::SynthesizeMouseMove(PRBool aFromScroll) if (mMouseLocation == nsPoint(NSCOORD_NONE, NSCOORD_NONE)) return NS_OK; - nsCOMPtr eventQueue; - mEventQueueService->GetSpecialEventQueue( - nsIEventQueueService::UI_THREAD_EVENT_QUEUE, getter_AddRefs(eventQueue)); - NS_ASSERTION(nsnull != eventQueue, "Event queue is null"); + if (!mSynthMouseMoveEvent.IsPending()) { + nsRefPtr ev = + new nsSynthMouseMoveEvent(this, aFromScroll); - if (eventQueue != mSynthMouseMoveEventQueue) { - nsSynthMouseMoveEvent *ev = new nsSynthMouseMoveEvent(this, aFromScroll); - eventQueue->PostEvent(ev); - mSynthMouseMoveEventQueue = eventQueue; + if (NS_FAILED(NS_DispatchToCurrentThread(ev))) { + NS_WARNING("failed to dispatch nsSynthMouseMoveEvent"); + return NS_ERROR_UNEXPECTED; + } + + mSynthMouseMoveEvent = ev; } return NS_OK; @@ -2952,10 +2910,10 @@ nsViewManager::ProcessSynthMouseMoveEvent(PRBool aFromScroll) // allow new event to be posted while handling this one only if the // source of the event is a scroll (to prevent infinite reflow loops) if (aFromScroll) - mSynthMouseMoveEventQueue = nsnull; + mSynthMouseMoveEvent.Forget(); if (mMouseLocation == nsPoint(NSCOORD_NONE, NSCOORD_NONE) || !mRootView) { - mSynthMouseMoveEventQueue = nsnull; + mSynthMouseMoveEvent.Forget(); return; } @@ -2992,7 +2950,7 @@ nsViewManager::ProcessSynthMouseMoveEvent(PRBool aFromScroll) view->GetViewManager()->DispatchEvent(&event, &status); if (!aFromScroll) - mSynthMouseMoveEventQueue = nsnull; + mSynthMouseMoveEvent.Forget(); } void diff --git a/mozilla/view/src/nsViewManager.h b/mozilla/view/src/nsViewManager.h index 6491876bcf3..a6b04db4187 100644 --- a/mozilla/view/src/nsViewManager.h +++ b/mozilla/view/src/nsViewManager.h @@ -45,11 +45,10 @@ #include "prtime.h" #include "prinrval.h" #include "nsVoidArray.h" +#include "nsThreadUtils.h" #include "nsIScrollableView.h" #include "nsIRegion.h" #include "nsIBlender.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" #include "nsView.h" class nsIRegion; @@ -145,6 +144,16 @@ protected: nsView *mReparentedView; }; +class nsViewManagerEvent : public nsRunnable { +public: + nsViewManagerEvent(class nsViewManager *vm) : mViewManager(vm) { + NS_ASSERTION(mViewManager, "null parameter"); + } + void Revoke() { mViewManager = nsnull; } +protected: + class nsViewManager *mViewManager; +}; + class nsViewManager : public nsIViewManager { public: nsViewManager(); @@ -541,10 +550,11 @@ private: // mRootViewManager is a strong ref unless it equals |this|. It's // never null (if we have no ancestors, it will be |this|). nsViewManager *mRootViewManager; - nsCOMPtr mEventQueueService; - nsCOMPtr mSynthMouseMoveEventQueue; PRPackedBool mAllowDoubleBuffering; + nsRevocableEventPtr mSynthMouseMoveEvent; + nsRevocableEventPtr mInvalidateEvent; + // The following members should not be accessed directly except by // the root view manager. Some have accessor functions to enforce // this, as noted. @@ -557,7 +567,6 @@ private: PRInt32 mUpdateBatchCnt; PRUint32 mUpdateBatchFlags; PRInt32 mScrollCnt; - nsCOMPtr mInvalidateEventQueue; // Use IsRefreshEnabled() to check the value of mRefreshEnabled. PRPackedBool mRefreshEnabled; // Use IsPainting() and SetPainting() to access mPainting. diff --git a/mozilla/widget/public/nsIAppShell.idl b/mozilla/widget/public/nsIAppShell.idl index b6a2c10b3f4..b63e3a4862a 100644 --- a/mozilla/widget/public/nsIAppShell.idl +++ b/mozilla/widget/public/nsIAppShell.idl @@ -39,78 +39,38 @@ #include "nsISupports.idl" -native int(int); -[ptr] native nsIEventQueue(nsIEventQueue); -[ptr] native UndefinednsIWidget(nsIWidget); -[ref] native PRBoolRef(PRBool); -[ref] native voidPtrRef(void *); - -%{ C++ -class nsIEventQueue; - /** - * Flags for the getNativeData function. - * See GetNativeData() + * Interface for the native event system layer. This interface is designed + * to be used on the main application thread only. */ -#define NS_NATIVE_SHELL 0 - -class nsIWidget; -%} - - -[uuid(a0757c31-eeac-11d1-9ec1-00aa002fb821)] +[uuid(3785230a-da91-4eaa-8a25-56acc7ff35d0)] interface nsIAppShell : nsISupports { - /** - * Creates an application shell - */ + /** + * Enter an event loop. Don't leave until exit() is called. + */ + void run(); - void Create(inout int argc, inout string argv); - - /** - * Enter an event loop. - * Don't leave until application exits. - */ - - void Run(); - - /** - * Prepare to process events. - */ - - void Spinup(); - - /** - * Prepare to stop processing events. - */ - - void Spindown(); - - /** - * An event queue has been created or destroyed. Hook or unhook it from - * your system, as necessary. - * @param aQueue the queue in question - * @param aListen PR_TRUE for a new queue wanting hooking up. PR_FALSE - * for a queue wanting to be unhooked. - */ - void ListenToEventQueue(in nsIEventQueue aQueue, in PRBool aListen); - - /** - * After event dispatch execute app specific code - */ - - void GetNativeEvent(in PRBoolRef aRealEvent, in voidPtrRef aEvent); - - /** - * After event dispatch execute app specific code - */ - - void DispatchNativeEvent(in PRBool aRealEvent, in voidPtr aEvent); - - /** - * Exit the handle event loop - */ - - void Exit(); + /** + * Exit the handle event loop + */ + void exit(); + /** + * Give hint to native event queue notification mechanism. If the native + * platform needs to tradeoff performance vs. native event starvation this + * hint tells the native dispatch code which to favor. The default is to + * prevent native event starvation. + * + * Calls to this function may be nested. When the number of calls that pass + * PR_TRUE is subtracted from the number of calls that pass PR_FALSE is + * greater than 0, performance is given precedence over preventing event + * starvation. + * + * The starvationDelay arg is only used when favorPerfOverStarvation is + * PR_FALSE. It is the amount of time in milliseconds to wait before the + * PR_FALSE actually takes effect. + */ + void favorPerformanceHint(in boolean favorPerfOverStarvation, + in unsigned long starvationDelay); }; diff --git a/mozilla/widget/public/nsIWidget.h b/mozilla/widget/public/nsIWidget.h index 09d507dbf93..951355555eb 100644 --- a/mozilla/widget/public/nsIWidget.h +++ b/mozilla/widget/public/nsIWidget.h @@ -96,10 +96,10 @@ typedef nsEventStatus (*PR_CALLBACK EVENT_CALLBACK)(nsGUIEvent *event); #define NS_NATIVE_SCREEN 9 #define NS_NATIVE_SHELLWIDGET 10 // Get the shell GtkWidget -// a7d9fe86-d7bd-4c59-9857-f396f7c92818 +// d6fec391-e2d8-4841-9d8f-43423b953884 #define NS_IWIDGET_IID \ -{ 0xa7d9fe86, 0xd7bd, 0x4c59, \ - { 0x98, 0x57, 0xf3, 0x96, 0xf7, 0xc9, 0x28, 0x18 } } +{ 0xd6fec391, 0xe2d8, 0x4841, \ + { 0x9d, 0x8f, 0x43, 0x42, 0x3b, 0x95, 0x38, 0x84 } } // Hide the native window systems real window type so as to avoid @@ -854,7 +854,6 @@ class nsIWidget : public nsISupports { virtual void FreeNativeData(void * data, PRUint32 aDataType) = 0;//~~~ virtual nsIRenderingContext* GetRenderingContext() = 0; virtual nsIDeviceContext* GetDeviceContext() = 0; - virtual nsIAppShell *GetAppShell() = 0; //@} /** diff --git a/mozilla/widget/src/build/nsWinWidgetFactory.cpp b/mozilla/widget/src/build/nsWinWidgetFactory.cpp index b4ca5528c57..f4109514394 100644 --- a/mozilla/widget/src/build/nsWinWidgetFactory.cpp +++ b/mozilla/widget/src/build/nsWinWidgetFactory.cpp @@ -47,6 +47,7 @@ #include "nsToolkit.h" #include "nsWindow.h" #include "nsAppShell.h" +#include "nsAppShellSingleton.h" #include "nsIServiceManager.h" #include "nsSound.h" @@ -81,7 +82,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService) NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard) #endif -NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppShell) NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel) NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) @@ -95,7 +95,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecWin) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecFactoryWin) - static const nsModuleComponentInfo components[] = { { "nsWindow", @@ -108,7 +107,6 @@ static const nsModuleComponentInfo components[] = ChildWindowConstructor }, { "Clipboard", NS_CLIPBOARD_CID, - // "@mozilla.org/widget/clipboard/win;1", "@mozilla.org/widget/clipboard;1", nsClipboardConstructor }, { "Clipboard Helper", @@ -122,12 +120,10 @@ static const nsModuleComponentInfo components[] = #ifndef WINCE { "Sound", NS_SOUND_CID, - // "@mozilla.org/widget/sound/win;1" "@mozilla.org/sound;1", nsSoundConstructor }, { "Drag Service", NS_DRAGSERVICE_CID, - // "@mozilla.org/widget/dragservice/win;1", "@mozilla.org/widget/dragservice;1", nsDragServiceConstructor }, { "Bidi Keyboard", @@ -154,7 +150,6 @@ static const nsModuleComponentInfo components[] = nsLookAndFeelConstructor }, { "Transferable", NS_TRANSFERABLE_CID, - // "@mozilla.org/widget/transferable/win;1", "@mozilla.org/widget/transferable;1", nsTransferableConstructor }, { "HTML Format Converter", @@ -187,5 +182,5 @@ static const nsModuleComponentInfo components[] = nsDeviceContextSpecFactoryWinConstructor }, }; - -NS_IMPL_NSGETMODULE(nsWidgetModule, components) +NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(nsWidgetModule, components, + nsAppShellInit, nsAppShellShutdown) diff --git a/mozilla/widget/src/cocoa/Makefile.in b/mozilla/widget/src/cocoa/Makefile.in index cf8b1a0b91a..52adc8bbf81 100644 --- a/mozilla/widget/src/cocoa/Makefile.in +++ b/mozilla/widget/src/cocoa/Makefile.in @@ -124,7 +124,7 @@ CMMSRCS = \ nsMenuItemX.mm \ nsFilePicker.mm \ nsToolkit.mm \ - nsAppShellCocoa.mm \ + nsAppShell.mm \ nsCocoaWindow.mm \ nsChildView.mm \ nsWindowMap.mm \ diff --git a/mozilla/security/manager/ssl/src/nsNSSEvent.h b/mozilla/widget/src/cocoa/nsAppShell.h similarity index 58% rename from mozilla/security/manager/ssl/src/nsNSSEvent.h rename to mozilla/widget/src/cocoa/nsAppShell.h index 68780eb6633..af7a20f7f3b 100644 --- a/mozilla/security/manager/ssl/src/nsNSSEvent.h +++ b/mozilla/widget/src/cocoa/nsAppShell.h @@ -1,3 +1,4 @@ +/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -11,16 +12,14 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is mozilla.org code. + * The Original Code is a Cocoa widget run loop and event implementation. * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All - * Rights Reserved. + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Javier Delgadillo - * Robert Relyea + * Mark Mentovai (Original Author) * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -36,19 +35,39 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef NSS_EVENT_ -#define NSS_EVENT_ +/* + * Runs the main native Cocoa run loop, interrupting it as needed to process + * Gecko events. + */ -#include "nsIRunnable.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" +#ifndef nsAppShell_h__ +#define nsAppShell_h__ +#include "nsBaseAppShell.h" -//Grab the UI event queue so that we can post some events to it. -already_AddRefed nsNSSEventGetUIEventQueue(); +@class AppShellDelegate; -// post something to it -nsresult nsNSSEventPostToUIEventQueue(nsIRunnable *event); +class nsAppShell : public nsBaseAppShell +{ +public: + nsAppShell(); -#endif + nsresult Init(); + // public only to be visible to Objective-C code that must call it + void ProcessGeckoEvents(); + +protected: + virtual ~nsAppShell(); + + virtual void ScheduleNativeEventCallback(); + virtual PRBool ProcessNextNativeEvent(PRBool aMayWait); + +protected: + NSAutoreleasePool* mMainPool; + + NSPort* mPort; + AppShellDelegate* mDelegate; +}; + +#endif // nsAppShell_h__ diff --git a/mozilla/widget/src/cocoa/nsAppShell.mm b/mozilla/widget/src/cocoa/nsAppShell.mm new file mode 100644 index 00000000000..0d6a9497471 --- /dev/null +++ b/mozilla/widget/src/cocoa/nsAppShell.mm @@ -0,0 +1,264 @@ +/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is a Cocoa widget run loop and event implementation. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Mentovai (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Runs the main native Cocoa run loop, interrupting it as needed to process + * Gecko events. + */ + +#import + +#include "nsAppShell.h" +#include "nsCOMPtr.h" +#include "nsIFile.h" +#include "nsDirectoryServiceDefs.h" +#include "nsString.h" + +// AppShellDelegate +// +// Cocoa bridge class. An object of this class is used as an NSPort +// delegate called on the main thread when Gecko wants to interrupt +// the native run loop. +// +@interface AppShellDelegate : NSObject +- (void)handlePortMessage:(NSPortMessage*)aPortMessage; +@end + +// nsAppShell implementation + +nsAppShell::nsAppShell() +: mPort(nil) +, mDelegate(nil) +{ + // mMainPool sits low on the autorelease pool stack to serve as a catch-all + // for autoreleased objects on this thread. Because it won't be popped + // until the appshell is destroyed, objects attached to this pool will + // be leaked until app shutdown. You probably don't want this! + // + // Objects autoreleased to this pool may result in warnings in the future. + mMainPool = [[NSAutoreleasePool alloc] init]; +} + +nsAppShell::~nsAppShell() +{ + if (mPort) { + [[NSRunLoop currentRunLoop] removePort:mPort forMode:NSDefaultRunLoopMode]; + [mPort release]; + } + + [mDelegate release]; + [mMainPool release]; +} + +// Init +// +// Loads the nib (see bug 316076c21) and sets up the NSPort used to +// interrupt the main Cocoa event loop. +// +// public +nsresult +nsAppShell::Init() +{ + // No event loop is running yet. Avoid autoreleasing objects to + // mMainPool. The appshell retains objects it needs to be long-lived + // and will release them as appropriate. + NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init]; + + // Get the path of the nib file, which lives in the GRE location + nsCOMPtr nibFile; + nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(nibFile)); + NS_ENSURE_SUCCESS(rv, rv); + + nibFile->AppendNative(NS_LITERAL_CSTRING("res")); + nibFile->AppendNative(NS_LITERAL_CSTRING("MainMenu.nib")); + + nsCAutoString nibPath; + rv = nibFile->GetNativePath(nibPath); + NS_ENSURE_SUCCESS(rv, rv); + + // This call initializes NSApplication. + [NSBundle loadNibFile: + [NSString stringWithUTF8String:(const char*)nibPath.get()] + externalNameTable: + [NSDictionary dictionaryWithObject:[NSApplication sharedApplication] + forKey:@"NSOwner"] + withZone:NSDefaultMallocZone()]; + + + // A message will be sent through mPort to mDelegate on the main thread + // to interrupt the run loop while it is running. + mDelegate = [[AppShellDelegate alloc] init]; + NS_ENSURE_STATE(mDelegate); + + mPort = [[NSPort port] retain]; + NS_ENSURE_STATE(mPort); + + [mPort setDelegate:mDelegate]; + [[NSRunLoop currentRunLoop] addPort:mPort forMode:NSDefaultRunLoopMode]; + + rv = nsBaseAppShell::Init(); + + [localPool release]; + + return rv; +} + +// ProcessGeckoEvents +// +// Arrange for Gecko events to be processed. They will either be processed +// after the main run loop returns (if we own the run loop) or on +// NativeEventCallback (if an embedder owns the loop). +// +// Called by -[AppShellDelegate handlePortMessage:] after mPort signals as a +// result of a ScheduleNativeEventCallback call. This method is public only +// because it needs to be called by that Objective-C fragment, and C++ can't +// make |friend|s with Objective-C. +// +// public +void +nsAppShell::ProcessGeckoEvents() +{ + if (mRunWasCalled) { + // We own the run loop. Interrupt it. It will be started again later + // (unless exiting) by nsBaseAppShell. Trust me, I'm a doctor. + [NSApp stop:nil]; + + // The run loop is sleeping. [NSApp run] won't return until it's given + // a reason to wake up. Awaken it by posting a bogus event. + // There's no need to make the event presentable (by setting a subtype, + // for example) because we own the run loop. + [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined + location:NSMakePoint(0,0) + modifierFlags:0 + timestamp:0 + windowNumber:-1 + context:NULL + subtype:0 + data1:0 + data2:0] + atStart:NO]; + } + + NativeEventCallback(); +} + +// ScheduleNativeEventCallback +// +// Called (possibly on a non-main thread) when Gecko has an event that +// needs to be processed. The Gecko event needs to be processed on the +// main thread, so the native run loop must be interrupted. +// +// protected virtual +void +nsAppShell::ScheduleNativeEventCallback() +{ + NS_ADDREF(this); + + void* self = NS_STATIC_CAST(void*, this); + NSData* data = [[NSData alloc] initWithBytes:&self length:sizeof(this)]; + NSArray* components = [[NSArray alloc] initWithObjects:&data count:1]; + + // This will invoke [mDelegate handlePortMessage:message] on the main thread. + + NSPortMessage* message = [[NSPortMessage alloc] initWithSendPort:mPort + receivePort:nil + components:components]; + [message sendBeforeDate:[NSDate distantFuture]]; + + [message release]; + [components release]; + [data release]; +} + +// ProcessNextNativeEvent +// +// If aMayWait is false, process a single native event. If it is true, run +// the native run loop until stopped by ProcessGeckoEvents. +// +// Returns true if more events are waiting in the native event queue. +// +// protected virtual +PRBool +nsAppShell::ProcessNextNativeEvent(PRBool aMayWait) +{ + if (!aMayWait) { + // Only process a single event. + if (NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:nil + inMode:NSDefaultRunLoopMode + dequeue:YES]) { + // Handle the event on its own autorelease pool. + // Ordinarily, each event gets a new pool when dispatched by + // [NSApp run]. + NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init]; + [NSApp sendEvent:event]; + [localPool release]; + } + } + else { + // Run the run loop until interrupted by a stop: message. + [NSApp run]; + } + + if ([NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:nil + inMode:NSDefaultRunLoopMode + dequeue:NO]) { + return PR_TRUE; + } + + return PR_FALSE; +} + +// AppShellDelegate implementation + +@implementation AppShellDelegate +// handlePortMessage: +// +// The selector called on the delegate object when nsAppShell::mPort is sent an +// NSPortMessage by ScheduleNativeEventCallback. Call into the nsAppShell +// object for access to mRunWasCalled and NativeEventCallback. +// +- (void)handlePortMessage:(NSPortMessage*)aPortMessage +{ + NSData* data = [[aPortMessage components] objectAtIndex:0]; + nsAppShell* appShell = *NS_STATIC_CAST(nsAppShell* const*,[data bytes]); + appShell->ProcessGeckoEvents(); + + NS_RELEASE(appShell); +} +@end diff --git a/mozilla/widget/src/cocoa/nsAppShellCocoa.h b/mozilla/widget/src/cocoa/nsAppShellCocoa.h index f050a8e7f27..e69de29bb2d 100644 --- a/mozilla/widget/src/cocoa/nsAppShellCocoa.h +++ b/mozilla/widget/src/cocoa/nsAppShellCocoa.h @@ -1,69 +0,0 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -// -// nsAppShellCocoa -// -// This file contains the default interface of the application shell. Clients -// may either use this implementation or write their own. If you write your -// own, you must create a message sink to route events to. (The message sink -// interface may change, so this comment must be updated accordingly.) -// - -#ifndef nsAppShellCocoa_h__ -#define nsAppShellCocoa_h__ - -#include "nsIAppShell.h" - - -class nsAppShellCocoa : public nsIAppShell -{ - public: - nsAppShellCocoa(); - virtual ~nsAppShellCocoa(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIAPPSHELL - - private: - NSAutoreleasePool *mainPool; -}; - - - -#endif // nsAppShellCocoa_h__ - diff --git a/mozilla/widget/src/cocoa/nsAppShellCocoa.mm b/mozilla/widget/src/cocoa/nsAppShellCocoa.mm index 7bf7a9badd0..e69de29bb2d 100644 --- a/mozilla/widget/src/cocoa/nsAppShellCocoa.mm +++ b/mozilla/widget/src/cocoa/nsAppShellCocoa.mm @@ -1,206 +0,0 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -// -// nsAppShellCocoa -// -// This file contains the default implementation of the application shell. Clients -// may either use this implementation or write their own. If you write your -// own, you must create a message sink to route events to. (The message sink -// interface may change, so this comment must be updated accordingly.) -// - -#undef DARWIN -#import - -#include "nsAppShellCocoa.h" -#include "nsCOMPtr.h" -#include "nsDirectoryServiceUtils.h" -#include "nsIFile.h" -#include "nsDirectoryServiceDefs.h" -#include "nsString.h" - -NS_IMPL_THREADSAFE_ISUPPORTS1(nsAppShellCocoa, nsIAppShell) - - -//------------------------------------------------------------------------- -// -// nsAppShellCocoa constructor -// -//------------------------------------------------------------------------- -nsAppShellCocoa::nsAppShellCocoa() -{ - mainPool = [[NSAutoreleasePool alloc] init]; -} - -//------------------------------------------------------------------------- -// -// nsAppShellCocoa destructor -// -//------------------------------------------------------------------------- -nsAppShellCocoa::~nsAppShellCocoa() -{ - [mainPool release]; -} - - -//------------------------------------------------------------------------- -// -// Create the application shell -// -// There's reallly not a whole lot that needs to be done here. The -// window will register its own interest in the necessary events -// so there's no need for us to create a pump or a sink. -// -//------------------------------------------------------------------------- - -NS_IMETHODIMP -nsAppShellCocoa::Create(int* argc, char ** argv) -{ - // Get the path of the NIB file, which lives in the GRE location - nsCOMPtr nibFile; - nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(nibFile)); - NS_ENSURE_SUCCESS(rv, rv); - - nibFile->AppendNative(NS_LITERAL_CSTRING("res")); - nibFile->AppendNative(NS_LITERAL_CSTRING("MainMenu.nib")); - - nsCAutoString nibPath; - rv = nibFile->GetNativePath(nibPath); - NS_ENSURE_SUCCESS(rv, rv); - - // this call initializes NSApplication - [NSBundle loadNibFile: - [NSString stringWithUTF8String:(const char*)nibPath.get()] - externalNameTable: - [NSDictionary dictionaryWithObject: - [NSApplication sharedApplication] - forKey:@"NSOwner" - ] - withZone:NSDefaultMallocZone() - ]; - return NS_OK; -} - - -//------------------------------------------------------------------------- -// -// Enter a message handler loop -// -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsAppShellCocoa::Run(void) -{ - [NSApp run]; - return NS_OK; -} - - -//------------------------------------------------------------------------- -// -// Exit appshell -// -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsAppShellCocoa::Exit(void) -{ - [NSApp stop:nil]; - return NS_OK; -} - - -//------------------------------------------------------------------------- -// -// respond to notifications that an event queue has come or gone -// -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsAppShellCocoa::ListenToEventQueue(nsIEventQueue * aQueue, PRBool aListen) -{ - // unnecessary; handled elsewhere - return NS_OK; -} - - -//------------------------------------------------------------------------- -// -// Prepare to process events -// -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsAppShellCocoa::Spinup(void) -{ - return NS_OK; -} - - -//------------------------------------------------------------------------- -// -// Stop being prepared to process events. -// -//------------------------------------------------------------------------- -NS_IMETHODIMP -nsAppShellCocoa::Spindown(void) -{ - return NS_OK; -} - - -// -// GetNativeEvent -// DispatchNativeEvent -// -// These are generally used in the tight loop of a modal event loop. Cocoa -// has other ways of dealing with this, perhaps those should be investigated -// here. -// - -NS_METHOD -nsAppShellCocoa::GetNativeEvent(PRBool &aRealEvent, void *&aEvent) -{ - aEvent = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSEventTrackingRunLoopMode dequeue:YES]; - aRealEvent = (aEvent != nil); - return NS_OK; -} - -NS_METHOD -nsAppShellCocoa::DispatchNativeEvent(PRBool aRealEvent, void *aEvent) -{ - if (aRealEvent) - [NSApp sendEvent:(NSEvent*)aEvent]; - return NS_OK; -} diff --git a/mozilla/widget/src/cocoa/nsCocoaWindow.mm b/mozilla/widget/src/cocoa/nsCocoaWindow.mm index d62fddc78e5..ca37245e4f8 100644 --- a/mozilla/widget/src/cocoa/nsCocoaWindow.mm +++ b/mozilla/widget/src/cocoa/nsCocoaWindow.mm @@ -56,8 +56,6 @@ #include "nsIInterfaceRequestorUtils.h" #include "nsIXULWindow.h" -#include "nsIEventQueueService.h" - // Define Class IDs -- i hate having to do this static NS_DEFINE_CID(kCDragServiceCID, NS_DRAGSERVICE_CID); diff --git a/mozilla/widget/src/cocoa/nsWidgetFactory.mm b/mozilla/widget/src/cocoa/nsWidgetFactory.mm index 8a17f77812e..a8e3e594c3c 100644 --- a/mozilla/widget/src/cocoa/nsWidgetFactory.mm +++ b/mozilla/widget/src/cocoa/nsWidgetFactory.mm @@ -45,7 +45,8 @@ #include "nsToolkit.h" #include "nsChildView.h" #include "nsCocoaWindow.h" -#include "nsAppShellCocoa.h" +#include "nsAppShell.h" +#include "nsAppShellSingleton.h" #include "nsFilePicker.h" #include "nsMenuBarX.h" @@ -73,7 +74,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsCocoaWindow) NS_GENERIC_FACTORY_CONSTRUCTOR(nsChildView) NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppShellCocoa) NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMenuBarX) @@ -120,7 +120,7 @@ static const nsModuleComponentInfo gComponents[] = { "AppShell", NS_APPSHELL_CID, "@mozilla.org/widget/appshell/mac;1", - nsAppShellCocoaConstructor }, + nsAppShellConstructor }, { "Toolkit", NS_TOOLKIT_CID, "@mozilla.org/widget/toolkit/mac;1", @@ -207,4 +207,5 @@ static const nsModuleComponentInfo gComponents[] = nsPrintSessionXConstructor }, }; -NS_IMPL_NSGETMODULE(nsWidgetMacModule, gComponents) +NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(nsWidgetMacModule, gComponents, + nsAppShellInit, nsAppShellShutdown) diff --git a/mozilla/widget/src/gtk/nsAppShell.cpp b/mozilla/widget/src/gtk/nsAppShell.cpp index b5842345474..70a015ab78e 100644 --- a/mozilla/widget/src/gtk/nsAppShell.cpp +++ b/mozilla/widget/src/gtk/nsAppShell.cpp @@ -1,4 +1,6 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: + */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -14,15 +16,11 @@ * * The Original Code is mozilla.org code. * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. + * The Initial Developer of the Original Code is Christopher Blizzard + * . Portions created by the Initial Developer + * are Copyright (C) 2001 the Initial Developer. All Rights Reserved. * * Contributor(s): - * Markus G. Kuhn - * Richard Verhoeven - * Frank Tang adopt into mozilla * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -38,380 +36,92 @@ * * ***** END LICENSE BLOCK ***** */ -#include "prmon.h" -#include "plhash.h" -#include "nscore.h" -#include "nsCOMPtr.h" +#include + +#include +#include +#include +#include +#include #include "nsAppShell.h" -#include "nsIAppShell.h" -#include "nsIServiceManager.h" -#include "nsIEventQueueService.h" -#include "nsGtkEventHandler.h" -#include -#include +#include "prlog.h" +#include "prenv.h" -#include "nsIWidget.h" +#define NOTIFY_TOKEN 0xFA -#include "glib.h" -#include "nsVoidArray.h" - -static PLHashTable *sQueueHashTable = nsnull; -static PLHashTable *sCountHashTable = nsnull; -static nsVoidArray *sEventQueueList = nsnull; - -struct OurGdkIOClosure { - GdkInputFunction function; - gpointer data; -}; - -static gboolean -our_gdk_io_invoke(GIOChannel* source, GIOCondition condition, gpointer data) +/*static*/ gboolean +nsAppShell::EventProcessorCallback(GIOChannel *source, + GIOCondition condition, + gpointer data) { - OurGdkIOClosure* ioc = (OurGdkIOClosure*) data; - if (ioc) { - (*ioc->function)(ioc->data, g_io_channel_unix_get_fd(source), - GDK_INPUT_READ); - } - return TRUE; + nsAppShell *self = NS_STATIC_CAST(nsAppShell *, data); + + unsigned char c; + read(self->mPipeFDs[0], &c, 1); + NS_ASSERTION(c == (unsigned char) NOTIFY_TOKEN, "wrong token"); + + self->NativeEventCallback(); + return TRUE; } -static void -our_gdk_io_destroy(gpointer data) -{ -#ifdef DEBUG_APPSHELL - printf("our_gdk_io_destroy()\n"); -#endif - OurGdkIOClosure* ioc = (OurGdkIOClosure*) data; - if (ioc) { - g_free(ioc); - } -} - -static gint -our_gdk_input_add (gint source, - GdkInputFunction function, - gpointer data, - gint priority) -{ -#ifdef DEBUG_APPSHELL - printf("our_gdk_input_add()\n"); -#endif - guint result; - OurGdkIOClosure *closure = g_new (OurGdkIOClosure, 1); - GIOChannel *channel; - - closure->function = function; - closure->data = data; - - channel = g_io_channel_unix_new (source); - result = g_io_add_watch_full (channel, priority, G_IO_IN, - our_gdk_io_invoke, - closure, our_gdk_io_destroy); - g_io_channel_unref (channel); - - return result; -} - -// wrapper so we can call a macro -static unsigned long getNextRequest (void *aClosure) { - return NextRequest(GDK_DISPLAY()); -} - - -//------------------------------------------------------------------------- -// -// XPCOM CIDs -// -//------------------------------------------------------------------------- -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - - -//------------------------------------------------------------------------- -// -// nsAppShell constructor -// -//------------------------------------------------------------------------- -nsAppShell::nsAppShell() -{ -#ifdef DEBUG_APPSHELL - printf("nsAppShell::nsAppShell()\n"); -#endif - if (!sEventQueueList) - sEventQueueList = new nsVoidArray(); -} - -//------------------------------------------------------------------------- -// -// nsAppShell destructor -// -//------------------------------------------------------------------------- nsAppShell::~nsAppShell() { -#ifdef DEBUG_APPSHELL - printf("nsAppShell::~nsAppShell()\n"); -#endif + if (mTag) + g_source_remove(mTag); + if (mPipeFDs[0]) + close(mPipeFDs[0]); + if (mPipeFDs[1]) + close(mPipeFDs[1]); } -/* static */ void -nsAppShell::ReleaseGlobals() +nsresult +nsAppShell::Init() { - if (sQueueHashTable) { - PL_HashTableDestroy(sQueueHashTable); - sQueueHashTable = nsnull; - } - if (sCountHashTable) { - PL_HashTableDestroy(sCountHashTable); - sCountHashTable = nsnull; - } - if (sEventQueueList) { - delete sEventQueueList; - sEventQueueList = nsnull; - } -} + GIOChannel *ioc; -//------------------------------------------------------------------------- -// -// nsISupports implementation macro -// -//------------------------------------------------------------------------- + int err = pipe(mPipeFDs); + if (err) + return NS_ERROR_OUT_OF_MEMORY; -NS_IMPL_ISUPPORTS1(nsAppShell, nsIAppShell) + // make the pipe nonblocking -static void event_processor_callback(gpointer data, - gint source, - GdkInputCondition condition) -{ - nsIEventQueue *eventQueue = (nsIEventQueue*)data; - if (eventQueue) - eventQueue->ProcessPendingEvents(); - -} + int flags = fcntl(mPipeFDs[0], F_GETFL, 0); + if (flags == -1) + goto failed; + err = fcntl(mPipeFDs[0], F_SETFL, flags | O_NONBLOCK); + if (err == -1) + goto failed; + flags = fcntl(mPipeFDs[1], F_GETFL, 0); + if (flags == -1) + goto failed; + err = fcntl(mPipeFDs[1], F_SETFL, flags | O_NONBLOCK); + if (err == -1) + goto failed; -//------------------------------------------------------------------------- -// -// Create the application shell -// -//------------------------------------------------------------------------- + ioc = g_io_channel_unix_new(mPipeFDs[0]); + mTag = g_io_add_watch_full(ioc, G_PRIORITY_DEFAULT, G_IO_IN, + EventProcessorCallback, this, nsnull); + g_io_channel_unref(ioc); -NS_IMETHODIMP nsAppShell::Create(int *bac, char **bav) -{ - return NS_OK; -} - -//------------------------------------------------------------------------- -// -// Spinup - do any preparation necessary for running a message loop -// -//------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::Spinup() -{ - nsresult rv = NS_OK; - -#ifdef DEBUG_APPSHELL - printf("nsAppShell::Spinup()\n"); -#endif - - // Get the event queue service - nsCOMPtr eventQService = do_GetService(kEventQueueServiceCID, &rv); - - if (NS_FAILED(rv)) { - NS_ASSERTION("Could not obtain event queue service", PR_FALSE); - return rv; - } - - //Get the event queue for the thread. - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mEventQueue)); - - // If we got an event queue, use it. - if (mEventQueue) - goto done; - - // otherwise create a new event queue for the thread - rv = eventQService->CreateThreadEventQueue(); - if (NS_FAILED(rv)) { - NS_ASSERTION("Could not create the thread event queue", PR_FALSE); - return rv; - } - - // Ask again nicely for the event queue now that we have created one. - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mEventQueue)); - - // XXX shouldn't this be automatic? - done: - ListenToEventQueue(mEventQueue, PR_TRUE); - - return rv; -} - -//------------------------------------------------------------------------- -// -// Spindown - do any cleanup necessary for finishing a message loop -// -//------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::Spindown() -{ -#ifdef DEBUG_APPSHELL - printf("nsAppShell::Spindown()\n"); -#endif - if (mEventQueue) { - ListenToEventQueue(mEventQueue, PR_FALSE); - mEventQueue->ProcessPendingEvents(); - mEventQueue = nsnull; - } - return NS_OK; -} - -#ifdef NS_TRACE_MALLOC -#include "nsTraceMalloc.h" - -static gint -tm_flush_logfiles(gpointer data) -{ - NS_TraceMallocFlushLogfiles(); - return 1; -} -#endif - -//------------------------------------------------------------------------- -// -// Run -// -//------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::Run() -{ - if (!mEventQueue) - Spinup(); - - if (!mEventQueue) - return NS_ERROR_NOT_INITIALIZED; - -#ifdef NS_TRACE_MALLOC - gtk_idle_add(tm_flush_logfiles, nsnull); -#endif - - // kick up gtk_main. this won't return until gtk_main_quit is called - gtk_main(); - - Spindown(); - - return NS_OK; -} - -//------------------------------------------------------------------------- -// -// Exit a message handler loop -// -//------------------------------------------------------------------------- - -NS_IMETHODIMP nsAppShell::Exit() -{ - gtk_main_quit(); - return NS_OK; -} - -// does nothing. used by xp code with non-gtk expectations. -// this method will be removed once xp eventloops are working. -NS_IMETHODIMP nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *& aEvent) -{ - aRealEvent = PR_FALSE; - aEvent = 0; - - return NS_OK; -} - -// simply executes one iteration of the event loop. used by xp code with -// non-gtk expectations. -// this method will be removed once xp eventloops are working. -NS_IMETHODIMP nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent) -{ - if (!mEventQueue) - return NS_ERROR_NOT_INITIALIZED; - - g_main_iteration(PR_TRUE); - - return NS_OK; -} - -#define NUMBER_HASH_KEY(_num) ((PLHashNumber) _num) - -static PLHashNumber -IntHashKey(PRInt32 key) -{ - return NUMBER_HASH_KEY(key); -} - -NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue, - PRBool aListen) -{ -#ifdef DEBUG_APPSHELL - printf("ListenToEventQueue(%p, %d) this=%p\n", aQueue, aListen, this); -#endif - if (!sQueueHashTable) { - sQueueHashTable = PL_NewHashTable(3, (PLHashFunction)IntHashKey, - PL_CompareValues, PL_CompareValues, 0, 0); - } - if (!sCountHashTable) { - sCountHashTable = PL_NewHashTable(3, (PLHashFunction)IntHashKey, - PL_CompareValues, PL_CompareValues, 0, 0); - } - - if (aListen) { - /* add listener */ - PRInt32 key = aQueue->GetEventQueueSelectFD(); - - /* only add if we arn't already in the table */ - if (!PL_HashTableLookup(sQueueHashTable, GINT_TO_POINTER(key))) { - gint tag; - tag = our_gdk_input_add(aQueue->GetEventQueueSelectFD(), - event_processor_callback, - aQueue, - G_PRIORITY_HIGH_IDLE); - if (tag >= 0) { - PL_HashTableAdd(sQueueHashTable, GINT_TO_POINTER(key), GINT_TO_POINTER(tag)); - } - PLEventQueue *plqueue; - aQueue->GetPLEventQueue(&plqueue); - PL_RegisterEventIDFunc(plqueue, getNextRequest, 0); - sEventQueueList->AppendElement(plqueue); - } - /* bump up the count */ - gint count = GPOINTER_TO_INT(PL_HashTableLookup(sCountHashTable, GINT_TO_POINTER(key))); - PL_HashTableAdd(sCountHashTable, GINT_TO_POINTER(key), GINT_TO_POINTER(count+1)); - } else { - /* remove listener */ - PRInt32 key = aQueue->GetEventQueueSelectFD(); - - PLEventQueue *plqueue; - aQueue->GetPLEventQueue(&plqueue); - PL_UnregisterEventIDFunc(plqueue); - sEventQueueList->RemoveElement(plqueue); - - gint count = GPOINTER_TO_INT(PL_HashTableLookup(sCountHashTable, GINT_TO_POINTER(key))); - if (count - 1 == 0) { - gint tag = GPOINTER_TO_INT(PL_HashTableLookup(sQueueHashTable, GINT_TO_POINTER(key))); - if (tag > 0) { - g_source_remove(tag); - PL_HashTableRemove(sQueueHashTable, GINT_TO_POINTER(key)); - } - } - PL_HashTableAdd(sCountHashTable, GINT_TO_POINTER(key), GINT_TO_POINTER(count-1)); - - } - - return NS_OK; -} - -PRBool processQueue(void *aElement, void *aData) -{ - PLEventQueue *queue = (PLEventQueue *) aElement; - unsigned int id = NS_PTR_TO_INT32(aData); - PL_ProcessEventsBeforeID(queue, id); - return PR_TRUE; + return nsBaseAppShell::Init(); +failed: + close(mPipeFDs[0]); + close(mPipeFDs[1]); + mPipeFDs[0] = mPipeFDs[1] = 0; + return NS_ERROR_FAILURE; } void -nsAppShell::ProcessBeforeID(unsigned long aID) +nsAppShell::ScheduleNativeEventCallback() { - if (sEventQueueList) - sEventQueueList->EnumerateForwards(processQueue, (void *)aID); + unsigned char buf[] = { NOTIFY_TOKEN }; + write(mPipeFDs[1], buf, 1); +} + +PRBool +nsAppShell::ProcessNextNativeEvent(PRBool mayWait) +{ + PRBool hasEvents = gtk_events_pending(); + gtk_main_iteration_do(mayWait); + return hasEvents || mayWait; } diff --git a/mozilla/widget/src/gtk/nsAppShell.h b/mozilla/widget/src/gtk/nsAppShell.h index f71155a12d6..4ed9bedacf6 100644 --- a/mozilla/widget/src/gtk/nsAppShell.h +++ b/mozilla/widget/src/gtk/nsAppShell.h @@ -1,4 +1,6 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: + */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -14,10 +16,9 @@ * * The Original Code is mozilla.org code. * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. + * The Initial Developer of the Original Code is Christopher Blizzard + * . Portions created by the Initial Developer + * are Copyright (C) 2001 the Initial Developer. All Rights Reserved. * * Contributor(s): * @@ -38,28 +39,33 @@ #ifndef nsAppShell_h__ #define nsAppShell_h__ -#include "nsIAppShell.h" -#include "nsIEventQueue.h" -#include +#include +#include "nsBaseAppShell.h" +#include "nsCOMPtr.h" -/** - * Native GTK+ Application shell wrapper - */ -class nsAppShell : public nsIAppShell -{ +class nsAppShell : public nsBaseAppShell { public: - nsAppShell(); - virtual ~nsAppShell(); + nsAppShell() + : mTag(0), mRunningMain(0) + { + mPipeFDs[0] = mPipeFDs[1] = 0; + } - static void ReleaseGlobals(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIAPPSHELL - - static void ProcessBeforeID(unsigned long aID); + // nsBaseAppShell overrides: + nsresult Init(); + virtual void ScheduleNativeEventCallback(); + virtual PRBool ProcessNextNativeEvent(PRBool mayWait); private: - nsCOMPtr mEventQueue; + virtual ~nsAppShell(); + + static gboolean EventProcessorCallback(GIOChannel *source, + GIOCondition condition, + gpointer data); + + int mPipeFDs[2]; + PRUintn mTag; + PRInt32 mRunningMain; }; -#endif // nsAppShell_h__ +#endif /* nsAppShell_h__ */ diff --git a/mozilla/widget/src/gtk/nsGtkEventHandler.cpp b/mozilla/widget/src/gtk/nsGtkEventHandler.cpp index ad8661a86d8..02e34d33b76 100644 --- a/mozilla/widget/src/gtk/nsGtkEventHandler.cpp +++ b/mozilla/widget/src/gtk/nsGtkEventHandler.cpp @@ -800,11 +800,14 @@ handle_gdk_event (GdkEvent *event, gpointer data) } end: + ; +#if 0 // use the saved serial to process any pending events, now that all // the window events have been processed if (serial) nsAppShell::ProcessBeforeID(serial); +#endif } diff --git a/mozilla/widget/src/gtk/nsWidgetFactory.cpp b/mozilla/widget/src/gtk/nsWidgetFactory.cpp index f8403b9ba76..060b214baf2 100644 --- a/mozilla/widget/src/gtk/nsWidgetFactory.cpp +++ b/mozilla/widget/src/gtk/nsWidgetFactory.cpp @@ -45,6 +45,7 @@ #include "nsWindow.h" #include "nsAppShell.h" +#include "nsAppShellSingleton.h" #include "nsToolkit.h" #include "nsLookAndFeel.h" #include "nsTransferable.h" @@ -63,7 +64,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow) NS_GENERIC_FACTORY_CONSTRUCTOR(ChildWindow) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppShell) NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel) NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) @@ -148,10 +148,11 @@ PR_STATIC_CALLBACK(void) nsWidgetGTKModuleDtor(nsIModule *self) { nsWindow::ReleaseGlobals(); - nsAppShell::ReleaseGlobals(); nsGtkIMEHelper::Shutdown(); + nsAppShellShutdown(self); } -NS_IMPL_NSGETMODULE_WITH_DTOR(nsWidgetGTKModule, - components, - nsWidgetGTKModuleDtor) +NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(nsWidgetGTKModule, + components, + nsAppShellInit, + nsWidgetGTKModuleDtor) diff --git a/mozilla/widget/src/gtk2/nsAppShell.cpp b/mozilla/widget/src/gtk2/nsAppShell.cpp index e0b05eba345..293dd1d0cf3 100644 --- a/mozilla/widget/src/gtk2/nsAppShell.cpp +++ b/mozilla/widget/src/gtk2/nsAppShell.cpp @@ -36,20 +36,17 @@ * * ***** END LICENSE BLOCK ***** */ +#include +#include +#include +#include +#include +#include "nsCommonWidget.h" #include "nsAppShell.h" -#include "nsIEventQueueService.h" -#include "nsServiceManagerUtils.h" -#include "plhash.h" +#include "prlog.h" #include "prenv.h" -// to get the logging stuff -#include "nsCommonWidget.h" - -#include - -static PRBool sInitialized = PR_FALSE; -static PLHashTable *sQueueHashTable = nsnull; -static PLHashTable *sCountHashTable = nsnull; +#define NOTIFY_TOKEN 0xFA #ifdef PR_LOGGING PRLogModuleInfo *gWidgetLog = nsnull; @@ -58,27 +55,33 @@ PRLogModuleInfo *gWidgetIMLog = nsnull; PRLogModuleInfo *gWidgetDrawLog = nsnull; #endif -static gboolean event_processor_callback (GIOChannel *source, - GIOCondition condition, - gpointer data) +/*static*/ gboolean +nsAppShell::EventProcessorCallback(GIOChannel *source, + GIOCondition condition, + gpointer data) { - nsIEventQueue *eventQueue = (nsIEventQueue *)data; - if (eventQueue) - eventQueue->ProcessPendingEvents(); + nsAppShell *self = NS_STATIC_CAST(nsAppShell *, data); - // always remove the source event + unsigned char c; + read(self->mPipeFDs[0], &c, 1); + NS_ASSERTION(c == (unsigned char) NOTIFY_TOKEN, "wrong token"); + + self->NativeEventCallback(); return TRUE; } -#define NUMBER_HASH_KEY(_num) ((PLHashNumber) _num) - -static PLHashNumber -IntHashKey(PRInt32 key) +nsAppShell::~nsAppShell() { - return NUMBER_HASH_KEY(key); + if (mTag) + g_source_remove(mTag); + if (mPipeFDs[0]) + close(mPipeFDs[0]); + if (mPipeFDs[1]) + close(mPipeFDs[1]); } -nsAppShell::nsAppShell(void) +nsresult +nsAppShell::Init() { #ifdef PR_LOGGING if (!gWidgetLog) @@ -90,195 +93,53 @@ nsAppShell::nsAppShell(void) if (!gWidgetDrawLog) gWidgetDrawLog = PR_NewLogModule("WidgetDraw"); #endif -} -nsAppShell::~nsAppShell(void) -{ -} + GIOChannel *ioc; -/* static */ void -nsAppShell::ReleaseGlobals() -{ - if (sQueueHashTable) { - PL_HashTableDestroy(sQueueHashTable); - sQueueHashTable = nsnull; - } - if (sCountHashTable) { - PL_HashTableDestroy(sCountHashTable); - sCountHashTable = nsnull; - } -} - -NS_IMPL_ISUPPORTS1(nsAppShell, nsIAppShell) - -NS_IMETHODIMP -nsAppShell::Create(int *argc, char **argv) -{ - if (sInitialized) - return NS_OK; - - sInitialized = PR_TRUE; - - if (PR_GetEnv("MOZ_DEBUG_PAINTS")) { + if (PR_GetEnv("MOZ_DEBUG_PAINTS")) gdk_window_set_debug_updates(TRUE); - } - return NS_OK; + int err = pipe(mPipeFDs); + if (err) + return NS_ERROR_OUT_OF_MEMORY; + + // make the pipe nonblocking + + int flags = fcntl(mPipeFDs[0], F_GETFL, 0); + if (flags == -1) + goto failed; + err = fcntl(mPipeFDs[0], F_SETFL, flags | O_NONBLOCK); + if (err == -1) + goto failed; + flags = fcntl(mPipeFDs[1], F_GETFL, 0); + if (flags == -1) + goto failed; + err = fcntl(mPipeFDs[1], F_SETFL, flags | O_NONBLOCK); + if (err == -1) + goto failed; + + ioc = g_io_channel_unix_new(mPipeFDs[0]); + mTag = g_io_add_watch_full(ioc, G_PRIORITY_DEFAULT, G_IO_IN, + EventProcessorCallback, this, nsnull); + g_io_channel_unref(ioc); + + return nsBaseAppShell::Init(); +failed: + close(mPipeFDs[0]); + close(mPipeFDs[1]); + mPipeFDs[0] = mPipeFDs[1] = 0; + return NS_ERROR_FAILURE; } -NS_IMETHODIMP -nsAppShell::Run(void) +void +nsAppShell::ScheduleNativeEventCallback() { - if (!mEventQueue) - Spinup(); - - if (!mEventQueue) - return NS_ERROR_NOT_INITIALIZED; - - // go go gadget gtk2! - gtk_main(); - - Spindown(); - - return NS_OK; + unsigned char buf[] = { NOTIFY_TOKEN }; + write(mPipeFDs[1], buf, 1); } -NS_IMETHODIMP -nsAppShell::Spinup(void) +PRBool +nsAppShell::ProcessNextNativeEvent(PRBool mayWait) { - nsresult rv = NS_OK; - - // get the event queue service - nsCOMPtr eventQService = - do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - - if (NS_FAILED(rv)) { - NS_WARNING("Failed to get event queue service"); - return rv; - } - - // get the event queue for this thread - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(mEventQueue)); - - // if we got an event queue, just use it - if (mEventQueue) - goto done; - - // otherwise creaet a new event queue for the thread - rv = eventQService->CreateThreadEventQueue(); - if (NS_FAILED(rv)) { - NS_WARNING("Could not create the thread event queue"); - return rv; - } - - // ask again for the event queue now that we have create one. - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, - getter_AddRefs(mEventQueue)); - - done: - ListenToEventQueue(mEventQueue, PR_TRUE); - - return rv; -} - -NS_IMETHODIMP -nsAppShell::Spindown(void) -{ - // stop listening to the event queue - if (mEventQueue) { - ListenToEventQueue(mEventQueue, PR_FALSE); - mEventQueue->ProcessPendingEvents(); - mEventQueue = nsnull; - } - return NS_OK; -} - -NS_IMETHODIMP -nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue, PRBool aListen) -{ - LOG(("ListenToEventQueue %p %d\n", (void *)aQueue, aListen)); - // initialize our hash tables if we have to - if (!sQueueHashTable) - sQueueHashTable = PL_NewHashTable(3, (PLHashFunction)IntHashKey, - PL_CompareValues, - PL_CompareValues, 0, 0); - if (!sCountHashTable) - sCountHashTable = PL_NewHashTable(3, (PLHashFunction)IntHashKey, - PL_CompareValues, - PL_CompareValues, 0, 0); - - PRInt32 key = aQueue->GetEventQueueSelectFD(); - - /* add a listener */ - if (aListen) { - /* only add if we arn't already in the table */ - if (!PL_HashTableLookup(sQueueHashTable, GINT_TO_POINTER(key))) { - GIOChannel *ioc; - guint tag; - ioc = g_io_channel_unix_new(key); - tag = g_io_add_watch_full (ioc, G_PRIORITY_DEFAULT_IDLE, - G_IO_IN, - event_processor_callback, aQueue, NULL); - // it's owned by the mainloop now - g_io_channel_unref(ioc); - PL_HashTableAdd(sQueueHashTable, GINT_TO_POINTER(key), - GUINT_TO_POINTER(tag)); - LOG(("created tag %d from key %d\n", tag, key)); - } - /* bump up the count */ - gint count = GPOINTER_TO_INT(PL_HashTableLookup(sCountHashTable, - GINT_TO_POINTER(key))); - PL_HashTableAdd(sCountHashTable, GINT_TO_POINTER(key), - GINT_TO_POINTER(count+1)); - LOG(("key %d now has count %d\n", key, count+1)); - } else { - /* remove listener */ - gint count = GPOINTER_TO_INT(PL_HashTableLookup(sCountHashTable, - GINT_TO_POINTER(key))); - LOG(("key %d will have count %d\n", key, count-1)); - if (count - 1 == 0) { - guint tag; - tag = GPOINTER_TO_UINT(PL_HashTableLookup(sQueueHashTable, - GINT_TO_POINTER(key))); - LOG(("shutting down tag %d\n", tag)); - g_source_remove(tag); - PL_HashTableRemove(sQueueHashTable, GINT_TO_POINTER(key)); - PL_HashTableRemove(sCountHashTable, GINT_TO_POINTER(key)); - } - else { - // update the count for this key - PL_HashTableAdd(sCountHashTable, GINT_TO_POINTER(key), - GINT_TO_POINTER(count-1)); - } - } - - return NS_OK; -} - -NS_IMETHODIMP -nsAppShell::GetNativeEvent(PRBool &aRealEvent, void * &aEvent) -{ - aRealEvent = PR_FALSE; - aEvent = 0; - - return NS_OK; -} - -NS_IMETHODIMP -nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent) -{ - if (!mEventQueue) - return NS_ERROR_NOT_INITIALIZED; - - g_main_context_iteration(NULL, TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsAppShell::Exit(void) -{ - gtk_main_quit(); - return NS_OK; + return g_main_context_iteration(NULL, mayWait); } diff --git a/mozilla/widget/src/gtk2/nsAppShell.h b/mozilla/widget/src/gtk2/nsAppShell.h index ab46e8b15cf..85ed3007f0c 100644 --- a/mozilla/widget/src/gtk2/nsAppShell.h +++ b/mozilla/widget/src/gtk2/nsAppShell.h @@ -39,23 +39,30 @@ #ifndef nsAppShell_h__ #define nsAppShell_h__ -#include "nsIAppShell.h" -#include "nsIEventQueue.h" +#include +#include "nsBaseAppShell.h" #include "nsCOMPtr.h" -class nsAppShell : public nsIAppShell { +class nsAppShell : public nsBaseAppShell { public: + nsAppShell() : mTag(0) { + mPipeFDs[0] = mPipeFDs[1] = 0; + } - nsAppShell(); - virtual ~nsAppShell(); - - static void ReleaseGlobals(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIAPPSHELL + // nsBaseAppShell overrides: + nsresult Init(); + virtual void ScheduleNativeEventCallback(); + virtual PRBool ProcessNextNativeEvent(PRBool mayWait); private: - nsCOMPtr mEventQueue; + virtual ~nsAppShell(); + + static gboolean EventProcessorCallback(GIOChannel *source, + GIOCondition condition, + gpointer data); + + int mPipeFDs[2]; + PRUintn mTag; }; #endif /* nsAppShell_h__ */ diff --git a/mozilla/widget/src/gtk2/nsWidgetFactory.cpp b/mozilla/widget/src/gtk2/nsWidgetFactory.cpp index 8a3bf9f2118..33865406ade 100644 --- a/mozilla/widget/src/gtk2/nsWidgetFactory.cpp +++ b/mozilla/widget/src/gtk2/nsWidgetFactory.cpp @@ -39,6 +39,7 @@ #include "nsIGenericFactory.h" #include "nsWidgetsCID.h" #include "nsAppShell.h" +#include "nsAppShellSingleton.h" #include "nsBaseWidget.h" #include "nsLookAndFeel.h" #include "nsWindow.h" @@ -77,7 +78,6 @@ static NS_DEFINE_CID(kNativeFilePickerCID, NS_FILEPICKER_CID); NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow) NS_GENERIC_FACTORY_CONSTRUCTOR(nsChildWindow) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppShell) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel) NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard) @@ -276,9 +276,10 @@ nsWidgetGtk2ModuleDtor(nsIModule *aSelf) { nsFilePicker::Shutdown(); nsWindow::ReleaseGlobals(); - nsAppShell::ReleaseGlobals(); + nsAppShellShutdown(aSelf); } -NS_IMPL_NSGETMODULE_WITH_DTOR(nsWidgetGtk2Module, - components, - nsWidgetGtk2ModuleDtor) +NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(nsWidgetGtk2Module, + components, + nsAppShellInit, + nsWidgetGtk2ModuleDtor) diff --git a/mozilla/widget/src/mac/nsAppShell.cpp b/mozilla/widget/src/mac/nsAppShell.cpp index 8b83208e2f0..ced56ba88d6 100644 --- a/mozilla/widget/src/mac/nsAppShell.cpp +++ b/mozilla/widget/src/mac/nsAppShell.cpp @@ -20,6 +20,8 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Darin Fisher + * Mark Mentovai * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -35,183 +37,214 @@ * * ***** END LICENSE BLOCK ***** */ -// -// nsAppShell -// -// This file contains the default implementation of the application shell. Clients -// may either use this implementation or write their own. If you write your -// own, you must create a message sink to route events to. (The message sink -// interface may change, so this comment must be updated accordingly.) -// +/* + * Runs the main native Carbon run loop, interrupting it as needed to process + * Gecko events. + */ #include "nsAppShell.h" -#include "nsIAppShell.h" - -#include "nsIEventQueueService.h" -#include "nsIServiceManager.h" -#include "nsIWidget.h" -#include "nsMacMessagePump.h" +#include "nsIToolkit.h" #include "nsToolkit.h" -#include -#include -#include -#include -#include -#include +#include "nsMacMessagePump.h" -#include - -PRBool nsAppShell::mInitializedToolbox = PR_FALSE; - - -//------------------------------------------------------------------------- +// kWNETransitionEventList // -// nsISupports implementation macro +// This list encompasses all Carbon events that can be converted into +// EventRecords. Not all will necessarily be called; not all will necessarily +// be handled. Some items here may be redundant in that handlers are already +// installed elsewhere. This may need a good audit. // -//------------------------------------------------------------------------- -NS_IMPL_THREADSAFE_ISUPPORTS1(nsAppShell, nsIAppShell) +static const EventTypeSpec kWNETransitionEventList[] = { + { kEventClassMouse, kEventMouseDown }, + { kEventClassMouse, kEventMouseUp }, + { kEventClassMouse, kEventMouseMoved }, + { kEventClassMouse, kEventMouseDragged }, + { kEventClassKeyboard, kEventRawKeyDown }, + { kEventClassKeyboard, kEventRawKeyUp }, + { kEventClassKeyboard, kEventRawKeyRepeat }, + { kEventClassWindow, kEventWindowUpdate }, + { kEventClassWindow, kEventWindowActivated }, + { kEventClassWindow, kEventWindowDeactivated }, + { kEventClassWindow, kEventWindowCursorChange }, + { kEventClassApplication, kEventAppActivated }, + { kEventClassApplication, kEventAppDeactivated }, + { kEventClassAppleEvent, kEventAppleEvent }, + { kEventClassControl, kEventControlTrack }, +}; -//------------------------------------------------------------------------- -// -// Create the application shell -// -//------------------------------------------------------------------------- +// nsAppShell implementation -NS_IMETHODIMP nsAppShell::Create(int* argc, char ** argv) -{ - nsresult rv = NS_GetCurrentToolkit(getter_AddRefs(mToolkit)); - if (NS_FAILED(rv)) - return rv; - - nsIToolkit* toolkit = mToolkit.get(); - mMacPump.reset(new nsMacMessagePump(static_cast(toolkit))); - - if (!mMacPump.get() || ! nsMacMemoryCushion::EnsureMemoryCushion()) - return NS_ERROR_OUT_OF_MEMORY; - - return NS_OK; -} - -//------------------------------------------------------------------------- -// -// Enter a message handler loop -// -//------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::Run(void) -{ - if (!mMacPump.get()) - return NS_ERROR_NOT_INITIALIZED; - - mMacPump->StartRunning(); - mMacPump->DoMessagePump(); - - if (mExitCalled) // hack: see below - { - --mRefCnt; - if (mRefCnt == 0) - delete this; - } - - return NS_OK; -} - -//------------------------------------------------------------------------- -// -// Exit appshell -// -//------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::Exit(void) -{ - if (mMacPump.get()) - { - Spindown(); - mExitCalled = PR_TRUE; - ++mRefCnt; // hack: since the applications are likely to delete us - // after calling this method (see nsViewerApp::Exit()), - // we temporarily bump the refCnt to let the message pump - // exit properly. The object will delete itself afterwards. - } - return NS_OK; -} - -//------------------------------------------------------------------------- -// -// respond to notifications that an event queue has come or gone -// -//------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue * aQueue, PRBool aListen) -{ // unnecessary; handled elsewhere - return NS_OK; -} - -//------------------------------------------------------------------------- -// -// Prepare to process events -// -//------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::Spinup(void) -{ - if (mMacPump.get()) - { - mMacPump->StartRunning(); - return NS_OK; - } - return NS_ERROR_NOT_INITIALIZED; -} - -//------------------------------------------------------------------------- -// -// Stop being prepared to process events. -// -//------------------------------------------------------------------------- -NS_IMETHODIMP nsAppShell::Spindown(void) -{ - if (mMacPump.get()) - mMacPump->StopRunning(); - return NS_OK; -} - -//------------------------------------------------------------------------- -// -// nsAppShell constructor -// -//------------------------------------------------------------------------- nsAppShell::nsAppShell() +: mWNETransitionEventHandler(NULL) +, mCFRunLoop(NULL) +, mCFRunLoopSource(NULL) { - - mInitializedToolbox = PR_TRUE; - mRefCnt = 0; - mExitCalled = PR_FALSE; } -//------------------------------------------------------------------------- -// -// nsAppShell destructor -// -//------------------------------------------------------------------------- nsAppShell::~nsAppShell() { + if (mCFRunLoopSource) { + ::CFRunLoopRemoveSource(mCFRunLoop, mCFRunLoopSource, + kCFRunLoopCommonModes); + ::CFRelease(mCFRunLoopSource); + } + + if (mCFRunLoop) + ::CFRelease(mCFRunLoop); + + if (mWNETransitionEventHandler) + ::RemoveEventHandler(mWNETransitionEventHandler); } -NS_METHOD -nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent) +// Init +// +// Set up the transitional WaitNextEvent handler and the CFRunLoopSource +// used to interrupt the main Carbon event loop. +// +// public +nsresult +nsAppShell::Init() { - static EventRecord theEvent; // icky icky static (can't really do any better) + // The message pump is only used for its EventRecord dispatcher. It is + // used by the transitional WaitNextEvent handler. - if (!mMacPump.get()) - return NS_ERROR_NOT_INITIALIZED; + nsresult rv = NS_GetCurrentToolkit(getter_AddRefs(mToolkit)); + if (NS_FAILED(rv)) + return rv; - aRealEvent = mMacPump->GetEvent(theEvent); - aEvent = &theEvent; - return NS_OK; + nsIToolkit *toolkit = mToolkit.get(); + mMacPump = new nsMacMessagePump(static_cast(toolkit)); + if (!mMacPump.get() || !nsMacMemoryCushion::EnsureMemoryCushion()) + return NS_ERROR_OUT_OF_MEMORY; + + OSStatus err = ::InstallApplicationEventHandler( + ::NewEventHandlerUPP(WNETransitionEventHandler), + GetEventTypeCount(kWNETransitionEventList), + kWNETransitionEventList, + (void*)this, + &mWNETransitionEventHandler); + NS_ENSURE_TRUE(err == noErr, NS_ERROR_UNEXPECTED); + + // Add a CFRunLoopSource to the main native run loop. The source is + // responsible for interrupting the run loop when Gecko events are ready. + + // Silly Carbon, why do you require a cast here? + mCFRunLoop = (CFRunLoopRef)::GetCFRunLoopFromEventLoop(::GetMainEventLoop()); + NS_ENSURE_STATE(mCFRunLoop); + ::CFRetain(mCFRunLoop); + + CFRunLoopSourceContext context; + bzero(&context, sizeof(context)); + // context.version = 0; + context.info = this; + context.perform = ProcessGeckoEvents; + + mCFRunLoopSource = ::CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context); + NS_ENSURE_STATE(mCFRunLoopSource); + + ::CFRunLoopAddSource(mCFRunLoop, mCFRunLoopSource, kCFRunLoopCommonModes); + + return nsBaseAppShell::Init(); } -NS_METHOD -nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent) +// ScheduleNativeEventCallback +// +// Called (possibly on a non-main thread) when Gecko has an event that +// needs to be processed. The Gecko event needs to be processed on the +// main thread, so the native run loop must be interrupted. +// +// protected virtual +void +nsAppShell::ScheduleNativeEventCallback() { - if (!mMacPump.get()) - return NS_ERROR_NOT_INITIALIZED; + // This will invoke ProcessGeckoEvents on the main thread. - mMacPump->DispatchEvent(aRealEvent, (EventRecord *) aEvent); - return NS_OK; + NS_ADDREF_THIS(); + ::CFRunLoopSourceSignal(mCFRunLoopSource); + ::CFRunLoopWakeUp(mCFRunLoop); +} + +// ProcessNextNativeEvent +// +// If aMayWait is false, process a single native event. If it is true, run +// the native run loop until stopped by ProcessGeckoEvents. +// +// Returns true if more events are waiting in the native event queue. +// +// protected virtual +PRBool +nsAppShell::ProcessNextNativeEvent(PRBool aMayWait) +{ + EventQueueRef carbonEventQueue = ::GetCurrentEventQueue(); + + if (!aMayWait) { + // Only process a single event. + if (EventRef carbonEvent = + ::AcquireFirstMatchingEventInQueue(carbonEventQueue, + 0, + NULL, + kEventQueueOptionsNone)) { + ::SendEventToEventTarget(carbonEvent, ::GetEventDispatcherTarget()); + ::RemoveEventFromQueue(carbonEventQueue, carbonEvent); + ::ReleaseEvent(carbonEvent); + } + } + else { + // Run the loop until interrupted by ::QuitApplicationEventLoop(). + ::RunApplicationEventLoop(); + } + + return ::GetNumEventsInQueue(carbonEventQueue); +} + +// ProcessGeckoEvents +// +// The "perform" target of mCFRunLoop, called when mCFRunLoopSource is +// signalled from ScheduleNativeEventCallback. +// +// Arrange for Gecko events to be processed. They will either be processed +// after the main run loop returns (if we own the run loop) or on +// NativeEventCallback (if an embedder owns the loop). +// +// protected static +void +nsAppShell::ProcessGeckoEvents(void* aInfo) +{ + nsAppShell* self = NS_STATIC_CAST(nsAppShell*, aInfo); + + if (self->mRunWasCalled) { + // We own the run loop. Interrupt it. It will be started again later + // (unless exiting) by nsBaseAppShell. Trust me, I'm a doctor. + ::QuitApplicationEventLoop(); + } + + self->NativeEventCallback(); + + NS_RELEASE(self); +} + +// WNETransitionEventHandler +// +// Transitional WaitNextEvent handler. Accepts Carbon events from +// kWNETransitionEventList, converts them into EventRecords, and +// dispatches them through the path they would have gone if they +// had been received as EventRecords from WaitNextEvent. +// +// protected static +pascal OSStatus +nsAppShell::WNETransitionEventHandler(EventHandlerCallRef aHandlerCallRef, + EventRef aEvent, + void* aUserData) +{ + nsAppShell* self = NS_STATIC_CAST(nsAppShell*, aUserData); + + EventRecord eventRecord; + ::ConvertEventRefToEventRecord(aEvent, &eventRecord); + + PRBool handled = self->mMacPump->DispatchEvent(PR_TRUE, &eventRecord); + + if (handled) + return noErr; + + return eventNotHandledErr; } diff --git a/mozilla/widget/src/mac/nsAppShell.h b/mozilla/widget/src/mac/nsAppShell.h index 886dedede73..618d8403166 100644 --- a/mozilla/widget/src/mac/nsAppShell.h +++ b/mozilla/widget/src/mac/nsAppShell.h @@ -20,6 +20,8 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Darin Fisher + * Mark Mentovai * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -35,43 +37,51 @@ * * ***** END LICENSE BLOCK ***** */ -// -// nsAppShell -// -// This file contains the default interface of the application shell. Clients -// may either use this implementation or write their own. If you write your -// own, you must create a message sink to route events to. (The message sink -// interface may change, so this comment must be updated accordingly.) -// +/* + * Runs the main native run loop, interrupting it as needed to process Gecko + * events. + */ #ifndef nsAppShell_h__ #define nsAppShell_h__ -#include "nsIAppShell.h" +#include +#include + +#include "nsBaseAppShell.h" #include "nsCOMPtr.h" -#include "nsIToolkit.h" - -#include - -using std::auto_ptr; +#include "nsAutoPtr.h" +class nsIToolkit; class nsMacMessagePump; -class nsAppShell : public nsIAppShell +class nsAppShell : public nsBaseAppShell { - public: - nsAppShell(); - virtual ~nsAppShell(); +public: + nsAppShell(); - NS_DECL_ISUPPORTS - NS_DECL_NSIAPPSHELL - - private: - nsCOMPtr mToolkit; - auto_ptr mMacPump; - PRBool mExitCalled; - static PRBool mInitializedToolbox; + nsresult Init(); + +protected: + virtual ~nsAppShell(); + + virtual void ScheduleNativeEventCallback(); + virtual PRBool ProcessNextNativeEvent(PRBool aMayWait); + + static void ProcessGeckoEvents(void* aInfo); + static pascal OSStatus WNETransitionEventHandler( + EventHandlerCallRef aHandlerCallRef, + EventRef aEvent, + void* aUserData); + +protected: + nsCOMPtr mToolkit; + nsAutoPtr mMacPump; + + EventHandlerRef mWNETransitionEventHandler; + + CFRunLoopRef mCFRunLoop; + CFRunLoopSourceRef mCFRunLoopSource; }; #endif // nsAppShell_h__ - diff --git a/mozilla/widget/src/mac/nsMacMessagePump.cpp b/mozilla/widget/src/mac/nsMacMessagePump.cpp index 5aeb0e288df..338bb7d981c 100644 --- a/mozilla/widget/src/mac/nsMacMessagePump.cpp +++ b/mozilla/widget/src/mac/nsMacMessagePump.cpp @@ -57,7 +57,6 @@ #include "nsRepeater.h" -#include "nsIEventQueueService.h" #include "nsIServiceManager.h" #include "prthread.h" @@ -274,7 +273,7 @@ void nsMacMessagePump::DoMessagePump() #endif // PROFILE_WAITNEXTEVENT #endif // PROFILE - haveEvent = GetEvent(theEvent); + haveEvent = GetEvent(theEvent, PR_TRUE); #ifdef PROFILE #ifndef PROFILE_WAITNEXTEVENT @@ -361,7 +360,7 @@ PRBool nsMacMessagePump::BrowserIsBusy() * @param NONE * @return A boolean which states whether we have a real event */ -PRBool nsMacMessagePump::GetEvent(EventRecord &theEvent) +PRBool nsMacMessagePump::GetEvent(EventRecord &theEvent, PRBool mayWait) { PRBool inForeground = nsToolkit::IsAppInForeground(); PRBool buttonDown = ::Button(); @@ -374,7 +373,7 @@ PRBool nsMacMessagePump::GetEvent(EventRecord &theEvent) // if the mouse is down, and we're in the foreground, then eat // CPU so we respond quickly when scrolling etc. - SInt32 sleepTime = (buttonDown && inForeground) ? 0 : 5; + SInt32 sleepTime = (!mayWait || (buttonDown && inForeground)) ? 0 : 5; ::SetEventMask(everyEvent); // we need keyUp events PRBool haveEvent = ::WaitNextEvent(everyEvent, &theEvent, sleepTime, mouseRgn); diff --git a/mozilla/widget/src/mac/nsMacMessagePump.h b/mozilla/widget/src/mac/nsMacMessagePump.h index b9ef49150f5..2beecd1e78e 100644 --- a/mozilla/widget/src/mac/nsMacMessagePump.h +++ b/mozilla/widget/src/mac/nsMacMessagePump.h @@ -56,7 +56,6 @@ #include #include "prtypes.h" -#include "nsIEventQueueService.h" class nsToolkit; class nsMacTSMMessagePump; @@ -84,7 +83,7 @@ public: virtual ~nsMacMessagePump(); void DoMessagePump(); - PRBool GetEvent(EventRecord &theEvent); + PRBool GetEvent(EventRecord &theEvent, PRBool mayWait); // returns true if handled PRBool DispatchEvent(PRBool aRealEvent, EventRecord *anEvent); void StartRunning() {mRunning = PR_TRUE;} diff --git a/mozilla/widget/src/mac/nsToolkit.cpp b/mozilla/widget/src/mac/nsToolkit.cpp index a26827e95ed..4afecd35b1a 100644 --- a/mozilla/widget/src/mac/nsToolkit.cpp +++ b/mozilla/widget/src/mac/nsToolkit.cpp @@ -46,16 +46,12 @@ #include "nsIEventSink.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" #include "nsIServiceManager.h" +#include "nsThreadUtils.h" #include "nsGfxCIID.h" #include "nsIPref.h" -// Class IDs... -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - static nsMacNSPREventQueueHandler* gEventQueueHandler = nsnull; //------------------------------------------------------------------------- @@ -64,7 +60,6 @@ static nsMacNSPREventQueueHandler* gEventQueueHandler = nsnull; nsMacNSPREventQueueHandler::nsMacNSPREventQueueHandler(): Repeater() { mRefCnt = 0; - mEventQueueService = do_GetService(kEventQueueServiceCID); } //------------------------------------------------------------------------- @@ -114,18 +109,7 @@ void nsMacNSPREventQueueHandler::RepeatAction(const EventRecord& inMacEvent) //------------------------------------------------------------------------- PRBool nsMacNSPREventQueueHandler::EventsArePending() { - PRBool pendingEvents = PR_FALSE; - - if (mEventQueueService) - { - nsCOMPtr queue; - mEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - - if (queue) - queue->PendingEvents(&pendingEvents); - } - - return pendingEvents; + return NS_HasPendingEvents(NS_GetCurrentThread()); } @@ -134,15 +118,7 @@ PRBool nsMacNSPREventQueueHandler::EventsArePending() //------------------------------------------------------------------------- void nsMacNSPREventQueueHandler::ProcessPLEventQueue() { - NS_ASSERTION(mEventQueueService, "Need event queue service here"); - - nsCOMPtr queue; - mEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - if (queue) - { - nsresult rv = queue->ProcessPendingEvents(); - NS_ASSERTION(NS_SUCCEEDED(rv), "Error processing PLEvents"); - } + NS_ProcessPendingEvents(NS_GetCurrentThread()); } diff --git a/mozilla/widget/src/mac/nsToolkit.h b/mozilla/widget/src/mac/nsToolkit.h index b6239eef754..65907606513 100644 --- a/mozilla/widget/src/mac/nsToolkit.h +++ b/mozilla/widget/src/mac/nsToolkit.h @@ -44,7 +44,6 @@ #include "nsRepeater.h" #include "nsCOMPtr.h" -#include "nsIEventQueueService.h" /** * The toolkit abstraction is necessary because the message pump must @@ -138,8 +137,6 @@ protected: protected: nsrefcnt mRefCnt; - - nsCOMPtr mEventQueueService; }; diff --git a/mozilla/widget/src/mac/nsToolkitBase.cpp b/mozilla/widget/src/mac/nsToolkitBase.cpp index 0975ecf6267..96e019723c2 100644 --- a/mozilla/widget/src/mac/nsToolkitBase.cpp +++ b/mozilla/widget/src/mac/nsToolkitBase.cpp @@ -53,8 +53,6 @@ #include "nsToolkitBase.h" #include "nsWidgetAtoms.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" #include "nsIObserverService.h" #include "nsIServiceManager.h" #include "nsIPrefBranch2.h" diff --git a/mozilla/widget/src/mac/nsToolkitBase.h b/mozilla/widget/src/mac/nsToolkitBase.h index 555ee999d51..82d8e7b8437 100644 --- a/mozilla/widget/src/mac/nsToolkitBase.h +++ b/mozilla/widget/src/mac/nsToolkitBase.h @@ -43,7 +43,6 @@ #include "nsIToolkit.h" #include "nsCOMPtr.h" -#include "nsIEventQueueService.h" #include "nsIObserver.h" class nsToolkitBase : public nsIToolkit, public nsIObserver diff --git a/mozilla/widget/src/mac/nsWidgetFactory.cpp b/mozilla/widget/src/mac/nsWidgetFactory.cpp index 8ca0d38a689..5637deaf95e 100644 --- a/mozilla/widget/src/mac/nsWidgetFactory.cpp +++ b/mozilla/widget/src/mac/nsWidgetFactory.cpp @@ -47,6 +47,7 @@ #include "nsWindow.h" #include "nsMacWindow.h" #include "nsAppShell.h" +#include "nsAppShellSingleton.h" #include "nsFilePicker.h" #include "nsNativeScrollbar.h" @@ -74,7 +75,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacWindow) NS_GENERIC_FACTORY_CONSTRUCTOR(ChildWindow) NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppShell) NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMenuBarX) @@ -200,4 +200,5 @@ static const nsModuleComponentInfo gComponents[] = nsPrintSessionXConstructor }, }; -NS_IMPL_NSGETMODULE(nsWidgetMacModule, gComponents) +NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(nsWidgetMacModule, gComponents, + nsAppShellInit, nsAppShellShutdown) diff --git a/mozilla/widget/src/os2/nsFrameWindow.cpp b/mozilla/widget/src/os2/nsFrameWindow.cpp index c88ff2e90d5..6ad7732d511 100644 --- a/mozilla/widget/src/os2/nsFrameWindow.cpp +++ b/mozilla/widget/src/os2/nsFrameWindow.cpp @@ -242,8 +242,7 @@ void nsFrameWindow::RealDoCreate( HWND hwndP, nsWindow *aParent, // Record passed in things mAppShell = aAppShell; -// NS_IF_ADDREF( mAppShell); - GetAppShell(); // Let the base widget class update the refcount for us.... + NS_IF_ADDREF( mAppShell); mEventCallback = aHandleEventFunction; if( mParent) diff --git a/mozilla/widget/src/os2/nsWindow.cpp b/mozilla/widget/src/os2/nsWindow.cpp index 80230f4e5eb..74e0bd6daff 100644 --- a/mozilla/widget/src/os2/nsWindow.cpp +++ b/mozilla/widget/src/os2/nsWindow.cpp @@ -1003,8 +1003,7 @@ void nsWindow::RealDoCreate( HWND hwndP, // Record passed in things mAppShell = aAppShell; -// NS_IF_ADDREF( mAppShell); - GetAppShell(); // Let the base widget class update the refcount for us.... + NS_IF_ADDREF( mAppShell); mEventCallback = aHandleEventFunction; if( mParent) diff --git a/mozilla/widget/src/windows/nsAppShell.cpp b/mozilla/widget/src/windows/nsAppShell.cpp index 064b713f14c..5a6c57b868b 100644 --- a/mozilla/widget/src/windows/nsAppShell.cpp +++ b/mozilla/widget/src/windows/nsAppShell.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Michael Lowe + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -38,52 +39,13 @@ #include "nsAppShell.h" #include "nsToolkit.h" -#include "nsIWidget.h" -#include "nsIEventQueueService.h" -#include "nsIServiceManager.h" -#include - -// unknwn.h is needed to build with WIN32_LEAN_AND_MEAN -#include - -#include "nsWidgetsCID.h" -#include "aimm.h" - - -NS_IMPL_ISUPPORTS1(nsAppShell, nsIAppShell) - -static int gKeepGoing = 1; -//------------------------------------------------------------------------- -// -// nsAppShell constructor -// -//------------------------------------------------------------------------- -nsAppShell::nsAppShell() -{ -} - +#include "nsThreadUtils.h" +static UINT sMsgId; -//------------------------------------------------------------------------- -// -// Create the application shell -// //------------------------------------------------------------------------- -NS_METHOD nsAppShell::Create(int* argc, char ** argv) -{ - return NS_OK; -} - -//------------------------------------------------------------------------- -// -// Enter a message handler loop -// -//------------------------------------------------------------------------- - -#include "nsITimerManager.h" - -BOOL PeekKeyAndIMEMessage(LPMSG msg, HWND hwnd) +static BOOL PeekKeyAndIMEMessage(LPMSG msg, HWND hwnd) { MSG msg1, msg2, *lpMsg; BOOL b1, b2; @@ -105,145 +67,87 @@ BOOL PeekKeyAndIMEMessage(LPMSG msg, HWND hwnd) return false; } - -NS_METHOD nsAppShell::Run(void) +/*static*/ LRESULT CALLBACK +nsAppShell::EventWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - NS_ADDREF_THIS(); - MSG msg; - int keepGoing = 1; - - nsresult rv; - nsCOMPtr timerManager(do_GetService("@mozilla.org/timer/manager;1", &rv)); - if (NS_FAILED(rv)) return rv; - - timerManager->SetUseIdleTimers(PR_TRUE); - - gKeepGoing = 1; - // Process messages - do { - // Give priority to system messages (in particular keyboard, mouse, - // timer, and paint messages). - if (PeekKeyAndIMEMessage(&msg, NULL) || - ::PeekMessageW(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || - ::PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { - keepGoing = (msg.message != WM_QUIT); - - if (keepGoing != 0) { - TranslateMessage(&msg); - ::DispatchMessageW(&msg); - } - } else { - - PRBool hasTimers; - timerManager->HasIdleTimers(&hasTimers); - if (hasTimers) { - do { - timerManager->FireNextIdleTimer(); - timerManager->HasIdleTimers(&hasTimers); - } while (hasTimers && !::PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)); - } else { - - if (!gKeepGoing) { - // In this situation, PostQuitMessage() was called, but the WM_QUIT - // message was removed from the event queue by someone else - - // (see bug #54725). So, just exit the loop as if WM_QUIT had been - // reeceived... - keepGoing = 0; - } else { - // Block and wait for any posted application message - ::WaitMessage(); - } - } - } - - } while (keepGoing != 0); - Release(); - return msg.wParam; + if (uMsg == sMsgId) { + nsAppShell *as = NS_REINTERPRET_CAST(nsAppShell *, lParam); + as->NativeEventCallback(); + NS_RELEASE(as); + return TRUE; + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); } -inline NS_METHOD nsAppShell::Spinup(void) -{ return NS_OK; } - -inline NS_METHOD nsAppShell::Spindown(void) -{ return NS_OK; } - -inline NS_METHOD nsAppShell::ListenToEventQueue(nsIEventQueue * aQueue, PRBool aListen) -{ return NS_OK; } - -NS_METHOD -nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent) -{ - static MSG msg; - - BOOL gotMessage = false; - - nsresult rv; - nsCOMPtr timerManager(do_GetService("@mozilla.org/timer/manager;1", &rv)); - if (NS_FAILED(rv)) return rv; - - do { - // Give priority to system messages (in particular keyboard, mouse, - // timer, and paint messages). - if (PeekKeyAndIMEMessage(&msg, NULL) || - ::PeekMessageW(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || - ::PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { - gotMessage = true; - } else { - PRBool hasTimers; - timerManager->HasIdleTimers(&hasTimers); - if (hasTimers) { - do { - timerManager->FireNextIdleTimer(); - timerManager->HasIdleTimers(&hasTimers); - } while (hasTimers && !::PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)); - } else { - // Block and wait for any posted application message - ::WaitMessage(); - } - } - - } while (!gotMessage); - -#ifdef DEBUG_danm - if (msg.message != WM_TIMER) - printf("-> %d", msg.message); -#endif - - TranslateMessage(&msg); - aEvent = &msg; - aRealEvent = PR_TRUE; - return NS_OK; -} - -nsresult nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent) -{ - ::DispatchMessageW((MSG *)aEvent); - return NS_OK; -} - -//------------------------------------------------------------------------- -// -// Exit a message handler loop -// -//------------------------------------------------------------------------- - -NS_METHOD nsAppShell::Exit(void) -{ - PostQuitMessage(0); - // - // Also, set a global flag, just in case someone eats the WM_QUIT message. - // see bug #54725. - // - gKeepGoing = 0; - return NS_OK; -} - -//------------------------------------------------------------------------- -// -// nsAppShell destructor -// -//------------------------------------------------------------------------- nsAppShell::~nsAppShell() { + if (mEventWnd) { + // DestroyWindow doesn't do anything when called from a non UI thread. + // Since mEventWnd was created on the UI thread, it must be destroyed on + // the UI thread. + SendMessage(mEventWnd, WM_CLOSE, 0, 0); + } } +nsresult +nsAppShell::Init() +{ + if (!sMsgId) + sMsgId = RegisterWindowMessage("nsAppShell:EventID"); + + WNDCLASS wc; + HINSTANCE module = GetModuleHandle(NULL); + + const char *const kWindowClass = "nsAppShell:EventWindowClass"; + if (!GetClassInfo(module, kWindowClass, &wc)) { + wc.style = 0; + wc.lpfnWndProc = EventWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = module; + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = (HBRUSH) NULL; + wc.lpszMenuName = (LPCSTR) NULL; + wc.lpszClassName = kWindowClass; + RegisterClass(&wc); + } + + mEventWnd = CreateWindow(kWindowClass, "nsAppShell:EventWindow", + 0, 0, 0, 10, 10, NULL, NULL, module, NULL); + NS_ENSURE_STATE(mEventWnd); + + return nsBaseAppShell::Init(); +} + +void +nsAppShell::ScheduleNativeEventCallback() +{ + // post a message to the native event queue... + NS_ADDREF_THIS(); + ::PostMessage(mEventWnd, sMsgId, 0, NS_REINTERPRET_CAST(LPARAM, this)); +} + +PRBool +nsAppShell::ProcessNextNativeEvent(PRBool mayWait) +{ + PRBool gotMessage = PR_FALSE; + + do { + MSG msg; + // Give priority to system messages (in particular keyboard, mouse, timer, + // and paint messages). + if (PeekKeyAndIMEMessage(&msg, NULL) || + ::PeekMessageW(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || + ::PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { + gotMessage = PR_TRUE; + ::TranslateMessage(&msg); + ::DispatchMessageW(&msg); + } else if (mayWait) { + // Block and wait for any posted application message + ::WaitMessage(); + } + } while (!gotMessage && mayWait); + + return gotMessage; +} diff --git a/mozilla/widget/src/windows/nsAppShell.h b/mozilla/widget/src/windows/nsAppShell.h index 6a301859788..b79c0c2517c 100644 --- a/mozilla/widget/src/windows/nsAppShell.h +++ b/mozilla/widget/src/windows/nsAppShell.h @@ -38,21 +38,28 @@ #ifndef nsAppShell_h__ #define nsAppShell_h__ -#include "nsIAppShell.h" +#include "nsBaseAppShell.h" +#include /** * Native Win32 Application shell wrapper */ - -class nsAppShell : public nsIAppShell +class nsAppShell : public nsBaseAppShell { - public: - nsAppShell(); - virtual ~nsAppShell(); +public: + nsAppShell() : mEventWnd(NULL) {} - NS_DECL_ISUPPORTS - NS_DECL_NSIAPPSHELL + nsresult Init(); + +protected: + virtual void ScheduleNativeEventCallback(); + virtual PRBool ProcessNextNativeEvent(PRBool mayWait); + virtual ~nsAppShell(); + + static LRESULT CALLBACK EventWindowProc(HWND, UINT, WPARAM, LPARAM); + +protected: + HWND mEventWnd; }; #endif // nsAppShell_h__ - diff --git a/mozilla/widget/src/windows/nsToolkit.cpp b/mozilla/widget/src/windows/nsToolkit.cpp index 140f239f89a..4804314f896 100644 --- a/mozilla/widget/src/windows/nsToolkit.cpp +++ b/mozilla/widget/src/windows/nsToolkit.cpp @@ -37,14 +37,13 @@ * ***** END LICENSE BLOCK ***** */ #include "nsToolkit.h" +#include "nsAppShell.h" #include "nsWindow.h" +#include "nsWidgetsCID.h" #include "prmon.h" #include "prtime.h" #include "nsGUIEvent.h" -#include "plevent.h" #include "nsIServiceManager.h" -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" #include "nsComponentManagerUtils.h" #include #include @@ -52,11 +51,6 @@ // unknwn.h is needed to build with WIN32_LEAN_AND_MEAN #include -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - -// Cached reference to event queue service -static nsCOMPtr gEventQueueService; - NS_IMPL_ISUPPORTS1(nsToolkit, nsIToolkit) // If PR_TRUE the user is currently moving a top level window. @@ -136,24 +130,28 @@ struct ThreadInitInfo { #ifndef WINCE LRESULT CALLBACK DetectWindowMove(int code, WPARAM wParam, LPARAM lParam) { + static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); + /* This msg filter is required to determine when the user has * clicked in the window title bar and is moving the window. */ CWPSTRUCT* sysMsg = (CWPSTRUCT*)lParam; if (sysMsg) { + nsCOMPtr appShell = do_GetService(kAppShellCID); + NS_ASSERTION(appShell, "no appshell"); if (sysMsg->message == WM_ENTERSIZEMOVE) { gIsMovingWindow = PR_TRUE; - // Notify xpcom that it should favor interactivity + // Notify appshell that it should favor interactivity // over performance because the user is moving a // window - PL_FavorPerformanceHint(PR_FALSE, 0); + appShell->FavorPerformanceHint(PR_FALSE, 0); } else if (sysMsg->message == WM_EXITSIZEMOVE) { gIsMovingWindow = PR_FALSE; - // Notify xpcom that it should go back to its + // Notify appshell that it should go back to its // previous performance setting which may favor // performance over interactivity - PL_FavorPerformanceHint(PR_TRUE, 0); + appShell->FavorPerformanceHint(PR_TRUE, 0); } } return CallNextHookEx(nsMsgFilterHook, code, wParam, lParam); @@ -225,9 +223,6 @@ nsToolkit::~nsToolkit() // Remove the TLS reference to the toolkit... PR_SetThreadPrivate(gToolkitTLSIndex, nsnull); - // Remove reference to cached event queue - gEventQueueService = nsnull; - if (gMouseTrailer) { gMouseTrailer->DestroyTimer(); delete gMouseTrailer; @@ -278,23 +273,6 @@ nsToolkit::Shutdown() ::UnregisterClassW(L"nsToolkitClass", nsToolkit::mDllInstance); } -nsIEventQueue* -nsToolkit::GetEventQueue() -{ - if (! gEventQueueService) { - gEventQueueService = do_GetService(kEventQueueServiceCID); - } - - if (gEventQueueService) { - nsCOMPtr eventQueue; - gEventQueueService->GetSpecialEventQueue( - nsIEventQueueService::UI_THREAD_EVENT_QUEUE, - getter_AddRefs(eventQueue)); - return eventQueue; - } - - return nsnull; -} //------------------------------------------------------------------------- // diff --git a/mozilla/widget/src/windows/nsToolkit.h b/mozilla/widget/src/windows/nsToolkit.h index 6fd5698deca..2ee5abb1dbf 100644 --- a/mozilla/widget/src/windows/nsToolkit.h +++ b/mozilla/widget/src/windows/nsToolkit.h @@ -84,7 +84,6 @@ class nsToolkit : public nsIToolkit void CreateInternalWindow(PRThread *aThread); // Return whether the user is currently moving any application window PRBool UserIsMovingWindow(void); - nsIEventQueue* GetEventQueue(void); private: ~nsToolkit(); diff --git a/mozilla/widget/src/windows/nsWindow.cpp b/mozilla/widget/src/windows/nsWindow.cpp index 45beeb91569..e09ac15d265 100644 --- a/mozilla/widget/src/windows/nsWindow.cpp +++ b/mozilla/widget/src/windows/nsWindow.cpp @@ -56,7 +56,6 @@ #endif #include "nsWindow.h" -#include "plevent.h" #include "nsIAppShell.h" #include "nsIFontMetrics.h" #include "nsIFontEnumerator.h" @@ -70,7 +69,7 @@ #include "nsIScreenManager.h" #include "nsRect.h" #include "nsTransform2D.h" -#include "nsIEventQueue.h" +#include "nsThreadUtils.h" #include "nsIObserverService.h" #include "imgIContainer.h" #include "gfxIImageFrame.h" @@ -4034,7 +4033,7 @@ BOOL CALLBACK nsWindow::DispatchStarvedPaints(HWND aWnd, LPARAM aMsg) // Check for pending paints and dispatch any pending paint // messages for any nsIWidget which is a descendant of the // top-level window that *this* window is embedded within. -// Also dispatch pending PL_Events to avoid PL_EventQueue starvation. +// // Note: We do not dispatch pending paint messages for non // nsIWidget managed windows. @@ -4042,17 +4041,13 @@ void nsWindow::DispatchPendingEvents() { gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow()); - // Need to flush all pending PL_Events before - // painting to prevent reflow events from being starved. - // Note: Unfortunately, The flushing of PL_Events can not be done by - // dispatching the native WM_TIMER event that is used for PL_Event - // notification because the timer message will not appear in the - // native msg queue until 10ms after the event is posted. Which is too late. - nsCOMPtr eventQueue; - nsToolkit *toolkit = NS_STATIC_CAST(nsToolkit *, mToolkit); - eventQueue = toolkit->GetEventQueue(); - if (eventQueue) { - eventQueue->ProcessPendingEvents(); + // We need to ensure that reflow events do not get starved. + // At the same time, we don't want to recurse through here + // as that would prevent us from dispatching starved paints. + static int recursionBlocker = 0; + if (recursionBlocker++ == 0) { + NS_ProcessPendingEvents(nsnull, PR_MillisecondsToInterval(100)); + --recursionBlocker; } // Quickly check to see if there are any diff --git a/mozilla/widget/src/xpwidgets/Makefile.in b/mozilla/widget/src/xpwidgets/Makefile.in index 3b7e412334f..8b5672d95c6 100644 --- a/mozilla/widget/src/xpwidgets/Makefile.in +++ b/mozilla/widget/src/xpwidgets/Makefile.in @@ -69,6 +69,7 @@ endif DEFINES += -D_IMPL_NS_WIDGET -DUSE_TLS_FOR_TOOLKIT CPPSRCS = \ + nsBaseAppShell.cpp \ nsBaseWidget.cpp \ nsTransferable.cpp \ nsHTMLFormatConverter.cpp \ diff --git a/mozilla/widget/src/xpwidgets/nsAppShellSingleton.h b/mozilla/widget/src/xpwidgets/nsAppShellSingleton.h new file mode 100644 index 00000000000..f863a9210f4 --- /dev/null +++ b/mozilla/widget/src/xpwidgets/nsAppShellSingleton.h @@ -0,0 +1,98 @@ +/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Widget code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsAppShellSingleton_h__ +#define nsAppShellSingleton_h__ + +/** + * This file is designed to be included into the file that provides the + * nsIModule implementation for a particular widget toolkit. + * + * The following functions are defined: + * nsAppShellInit + * nsAppShellShutdown + * nsAppShellConstructor + * + * The nsAppShellInit function is designed to be used as a module constructor. + * If you already have a module constructor, then call nsAppShellInit from your + * module constructor. + * + * The nsAppShellShutdown function is designed to be used as a module + * destructor. If you already have a module destructor, then call + * nsAppShellShutdown from your module destructor. + * + * The nsAppShellConstructor function is designed to be used as a factory + * method for the nsAppShell class. + */ + +static nsAppShell *sAppShell; + +PR_STATIC_CALLBACK(nsresult) +nsAppShellInit(nsIModule *module) +{ + NS_ASSERTION(!sAppShell, "already initialized"); + + sAppShell = new nsAppShell(); + if (!sAppShell) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(sAppShell); + + nsresult rv = sAppShell->Init(); + if (NS_FAILED(rv)) { + NS_RELEASE(sAppShell); + return rv; + } + + return NS_OK; +} + +PR_STATIC_CALLBACK(void) +nsAppShellShutdown(nsIModule *module) +{ + NS_RELEASE(sAppShell); +} + +static NS_METHOD +nsAppShellConstructor(nsISupports *outer, const nsIID &iid, void **result) +{ + NS_ENSURE_TRUE(!outer, NS_ERROR_NO_AGGREGATION); + NS_ENSURE_TRUE(sAppShell, NS_ERROR_NOT_INITIALIZED); + + return sAppShell->QueryInterface(iid, result); +} + +#endif // nsAppShellSingleton_h__ diff --git a/mozilla/widget/src/xpwidgets/nsBaseAppShell.cpp b/mozilla/widget/src/xpwidgets/nsBaseAppShell.cpp new file mode 100644 index 00000000000..c8f4afe7ecd --- /dev/null +++ b/mozilla/widget/src/xpwidgets/nsBaseAppShell.cpp @@ -0,0 +1,211 @@ +/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Widget code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsBaseAppShell.h" +#include "nsThreadUtils.h" + +// When processing the next thread event, the appshell may process native +// events (if not in performance mode), which can result in suppressing the +// next thread event for at most this many ticks: +#define THREAD_EVENT_STARVATION_LIMIT PR_MillisecondsToInterval(20) + +NS_IMPL_THREADSAFE_ISUPPORTS2(nsBaseAppShell, nsIAppShell, nsIThreadObserver) + +nsBaseAppShell::nsBaseAppShell() + : mFavorPerf(0) + , mNativeEventPending(PR_FALSE) + , mStarvationDelay(0) + , mSwitchTime(0) + , mLastNativeEventTime(0) + , mRunWasCalled(PR_FALSE) + , mExiting(PR_FALSE) + , mProcessingNextNativeEvent(PR_FALSE) +{ +} + +nsresult +nsBaseAppShell::Init() +{ + // Configure ourselves as an observer for the current thread: + + nsCOMPtr threadInt = + do_QueryInterface(NS_GetCurrentThread()); + NS_ENSURE_STATE(threadInt); + + threadInt->SetObserver(this); + return NS_OK; +} + +void +nsBaseAppShell::NativeEventCallback() +{ + PRInt32 hasPending = PR_AtomicSet(&mNativeEventPending, 0); + if (hasPending == 0) + return; + if (mProcessingNextNativeEvent) + return; + + // nsBaseAppShell::Run is not being used to pump events, so this may be + // our only opportunity to process pending gecko events. + + nsIThread *thread = NS_GetCurrentThread(); + NS_ProcessPendingEvents(thread, THREAD_EVENT_STARVATION_LIMIT); + + // Continue processing pending events later (we don't want to starve the + // embedders event loop). + if (NS_HasPendingEvents(thread)) + OnDispatchedEvent(nsnull); +} + +PRBool +nsBaseAppShell::DoProcessNextNativeEvent(PRBool mayWait) +{ + // The next native event to be processed may trigger our NativeEventCallback, + // in which case we do not want it to process any thread events since we'll + // do that when this function returns. + + mProcessingNextNativeEvent = PR_TRUE; + PRBool result = ProcessNextNativeEvent(mayWait); + mProcessingNextNativeEvent = PR_FALSE; + return result; +} + +//------------------------------------------------------------------------- +// nsIAppShell methods: + +NS_IMETHODIMP +nsBaseAppShell::Run(void) +{ + nsIThread *thread = NS_GetCurrentThread(); + + NS_ENSURE_STATE(!mRunWasCalled); // should not call Run twice + mRunWasCalled = PR_TRUE; + + while (!mExiting) + NS_ProcessNextEvent(thread); + + NS_ProcessPendingEvents(thread); + return NS_OK; +} + +NS_IMETHODIMP +nsBaseAppShell::Exit(void) +{ + mExiting = PR_TRUE; + return NS_OK; +} + +NS_IMETHODIMP +nsBaseAppShell::FavorPerformanceHint(PRBool favorPerfOverStarvation, + PRUint32 starvationDelay) +{ + mStarvationDelay = PR_MillisecondsToInterval(starvationDelay); + if (favorPerfOverStarvation) { + ++mFavorPerf; + } else { + --mFavorPerf; + mSwitchTime = PR_IntervalNow(); + } + return NS_OK; +} + +//------------------------------------------------------------------------- +// nsIThreadObserver methods: + +// Called from any thread +NS_IMETHODIMP +nsBaseAppShell::OnDispatchedEvent(nsIThreadInternal *thr) +{ + PRInt32 lastVal = PR_AtomicSet(&mNativeEventPending, 1); + if (lastVal == 1) + return NS_OK; + + ScheduleNativeEventCallback(); + return NS_OK; +} + +// Called from the main thread +NS_IMETHODIMP +nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal *thr, PRBool mayWait, + PRUint32 recursionDepth) +{ + PRIntervalTime start = PR_IntervalNow(); + PRIntervalTime limit = THREAD_EVENT_STARVATION_LIMIT; + + if (mFavorPerf <= 0 && start > mSwitchTime + mStarvationDelay) { + // Favor pending native events + PRIntervalTime now = start; + PRBool keepGoing; + do { + mLastNativeEventTime = now; + keepGoing = DoProcessNextNativeEvent(PR_FALSE); + } while (keepGoing && ((now = PR_IntervalNow()) - start) < limit); + } else { + // Avoid starving native events completely when in performance mode + if (start - mLastNativeEventTime > limit) { + mLastNativeEventTime = start; + DoProcessNextNativeEvent(PR_FALSE); + } + } + + // When mayWait is true, we need to make sure that there is an event in the + // thread's event queue before we return. Otherwise, the thread will block + // on its event queue waiting for an event. + PRBool needEvent = mayWait; + + while (!NS_HasPendingEvents(thr)) { + // If we have been asked to exit from Run, then we should not wait for + // events to process. + if (mRunWasCalled && mExiting && mayWait) + mayWait = PR_FALSE; + + mLastNativeEventTime = PR_IntervalNow(); + if (!DoProcessNextNativeEvent(mayWait) || !mayWait) + break; + } + + // Make sure that the thread event queue does not block on its monitor, as + // it normally would do if it did not have any pending events. To avoid + // that, we simply insert a dummy event into its queue during shutdown. + if (needEvent && !NS_HasPendingEvents(thr)) { + if (!mDummyEvent) + mDummyEvent = new nsRunnable(); + thr->Dispatch(mDummyEvent, NS_DISPATCH_NORMAL); + } + + return NS_OK; +} diff --git a/mozilla/widget/src/xpwidgets/nsBaseAppShell.h b/mozilla/widget/src/xpwidgets/nsBaseAppShell.h new file mode 100644 index 00000000000..454b897e5ba --- /dev/null +++ b/mozilla/widget/src/xpwidgets/nsBaseAppShell.h @@ -0,0 +1,108 @@ +/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Widget code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsBaseAppShell_h__ +#define nsBaseAppShell_h__ + +#include "nsIAppShell.h" +#include "nsIThreadInternal.h" +#include "nsIRunnable.h" +#include "nsCOMPtr.h" +#include "prinrval.h" + +/** + * A singleton that manages the UI thread's event queue. Subclass this class + * to enable platform-specific event queue support. + */ +class nsBaseAppShell : public nsIAppShell, public nsIThreadObserver +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIAPPSHELL + NS_DECL_NSITHREADOBSERVER + + nsBaseAppShell(); + +protected: + virtual ~nsBaseAppShell() {} + + /** + * This method is called by subclasses when the app shell singleton is + * instantiated. + */ + nsresult Init(); + + /** + * Called by subclasses from a native event. See ScheduleNativeEventCallback. + */ + void NativeEventCallback(); + + /** + * Implemented by subclasses. Invoke NativeEventCallback from a native + * event. This method may be called on any thread. + */ + virtual void ScheduleNativeEventCallback() = 0; + + /** + * Implemented by subclasses. Process the next native event. Only wait for + * the next native event if mayWait is true. This method is only called on + * the main application thread. + * + * @param mayWait + * If "true", then this method may wait if necessary for the next available + * native event. DispatchNativeEvent may be called to unblock a call to + * ProcessNextNativeEvent that is waiting. + * @return + * This method returns "true" if a native event was processed. + */ + virtual PRBool ProcessNextNativeEvent(PRBool mayWait) = 0; + +private: + PRBool DoProcessNextNativeEvent(PRBool mayWait); + + nsCOMPtr mDummyEvent; + PRInt32 mFavorPerf; + PRInt32 mNativeEventPending; + PRIntervalTime mStarvationDelay; + PRIntervalTime mSwitchTime; + PRIntervalTime mLastNativeEventTime; + PRPackedBool mRunWasCalled; + PRPackedBool mExiting; + PRPackedBool mProcessingNextNativeEvent; +}; + +#endif // nsBaseAppShell_h__ diff --git a/mozilla/widget/src/xpwidgets/nsBaseWidget.cpp b/mozilla/widget/src/xpwidgets/nsBaseWidget.cpp index 2abbdf0e3df..c7d5758ee4c 100644 --- a/mozilla/widget/src/xpwidgets/nsBaseWidget.cpp +++ b/mozilla/widget/src/xpwidgets/nsBaseWidget.cpp @@ -167,8 +167,6 @@ void nsBaseWidget::BaseCreate(nsIWidget *aParent, } - mAppShell = aAppShell; // addrefs - // save the event callback function mEventCallback = aHandleEventFunction; @@ -657,20 +655,6 @@ nsIDeviceContext* nsBaseWidget::GetDeviceContext() return mContext; } -//------------------------------------------------------------------------- -// -// Return the App Shell -// -//------------------------------------------------------------------------- - -nsIAppShell *nsBaseWidget::GetAppShell() -{ - nsIAppShell* theAppShell = mAppShell; - NS_IF_ADDREF(theAppShell); - return theAppShell; -} - - #ifdef MOZ_CAIRO_GFX //------------------------------------------------------------------------- // @@ -699,7 +683,6 @@ void nsBaseWidget::OnDestroy() // release references to device context, toolkit, and app shell NS_IF_RELEASE(mContext); NS_IF_RELEASE(mToolkit); - mAppShell = nsnull; // clear out nsCOMPtr } NS_METHOD nsBaseWidget::SetWindowClass(const nsAString& aName, diff --git a/mozilla/widget/src/xpwidgets/nsBaseWidget.h b/mozilla/widget/src/xpwidgets/nsBaseWidget.h index b969e876a81..f7f6588562f 100644 --- a/mozilla/widget/src/xpwidgets/nsBaseWidget.h +++ b/mozilla/widget/src/xpwidgets/nsBaseWidget.h @@ -108,7 +108,6 @@ public: nsresult MakeFullScreenInternal(PRBool aFullScreen); virtual nsIRenderingContext* GetRenderingContext(); virtual nsIDeviceContext* GetDeviceContext(); - virtual nsIAppShell * GetAppShell(); virtual nsIToolkit* GetToolkit(); #ifdef MOZ_CAIRO_GFX virtual gfxASurface* GetThebesSurface(); @@ -154,7 +153,6 @@ protected: void* mClientData; EVENT_CALLBACK mEventCallback; nsIDeviceContext *mContext; - nsCOMPtr mAppShell; nsIToolkit *mToolkit; nsIMouseListener *mMouseListener; nsIEventListener *mEventListener; diff --git a/mozilla/xpcom/base/nsConsoleService.cpp b/mozilla/xpcom/base/nsConsoleService.cpp index d3c8379034d..6d5b57d89ac 100644 --- a/mozilla/xpcom/base/nsConsoleService.cpp +++ b/mozilla/xpcom/base/nsConsoleService.cpp @@ -46,6 +46,7 @@ #include "nsIServiceManager.h" #include "nsIProxyObjectManager.h" #include "nsSupportsArray.h" +#include "nsThreadUtils.h" #include "nsConsoleService.h" #include "nsConsoleMessage.h" @@ -309,24 +310,12 @@ nsresult nsConsoleService::GetProxyForListener(nsIConsoleListener* aListener, nsIConsoleListener** aProxy) { - nsresult rv; - *aProxy = nsnull; - - nsCOMPtr proxyManager = - (do_GetService(NS_XPCOMPROXY_CONTRACTID)); - - if (proxyManager == nsnull) - return NS_ERROR_NOT_AVAILABLE; - /* - * NOTE this will fail if the calling thread doesn't have an eventQ. - * * Would it be better to catch that case and leave the listener unproxied? */ - rv = proxyManager->GetProxyForObject(NS_CURRENT_EVENTQ, - NS_GET_IID(nsIConsoleListener), - aListener, - PROXY_ASYNC | PROXY_ALWAYS, - (void**) aProxy); - return rv; + return NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, + NS_GET_IID(nsIConsoleListener), + aListener, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, + (void**) aProxy); } diff --git a/mozilla/xpcom/base/nsMemoryImpl.cpp b/mozilla/xpcom/base/nsMemoryImpl.cpp index 36c2ad191a2..8a838bc2cdb 100644 --- a/mozilla/xpcom/base/nsMemoryImpl.cpp +++ b/mozilla/xpcom/base/nsMemoryImpl.cpp @@ -37,16 +37,15 @@ #include "nsXPCOM.h" #include "nsMemoryImpl.h" +#include "nsThreadUtils.h" -#include "nsIEventQueueService.h" #include "nsIObserverService.h" -#include "nsIRunnable.h" #include "nsIServiceManager.h" #include "nsISupportsArray.h" -#include "nsIThread.h" #include "prmem.h" -#include "plevent.h" +#include "prcvar.h" +#include "pratom.h" #include "nsAlgorithm.h" #include "nsAutoLock.h" @@ -55,10 +54,14 @@ #if defined(XP_WIN) #include -#define NS_MEMORY_FLUSHER_THREAD +#define NS_MEMORY_FLUSHER #else // Need to implement the nsIMemory::IsLowMemory() predicate -#undef NS_MEMORY_FLUSHER_THREAD +#undef NS_MEMORY_FLUSHER +#endif + +#ifdef NS_MEMORY_FLUSHER +#include "nsITimer.h" #endif //////////////////////////////////////////////////////////////////////////////// @@ -115,41 +118,37 @@ reallocator(void* ptr, PRSize size, PRUint32& counter, PRUint32 max) #define NS_TEST_MEMORY_FLUSHER #endif -#ifdef NS_MEMORY_FLUSHER_THREAD +#ifdef NS_MEMORY_FLUSHER /** - * A runnable that is used to periodically check the status - * of the system, determine if too much memory is in use, - * and if so, trigger a "memory flush". + * A class that is used to periodically check the status of the system, + * determine if too much memory is in use, and if so, trigger a "memory flush". */ - -class MemoryFlusher : public nsIRunnable +class MemoryFlusher : public nsITimerCallback { public: // We don't use the generic macros because we are a special static object NS_IMETHOD QueryInterface(REFNSIID aIID, void** aResult); - NS_IMETHOD_(nsrefcnt) AddRef(void) { return 1; } + NS_IMETHOD_(nsrefcnt) AddRef(void) { return 2; } NS_IMETHOD_(nsrefcnt) Release(void) { return 1; } - NS_DECL_NSIRUNNABLE + NS_DECL_NSITIMERCALLBACK nsresult Init(); void StopAndJoin(); private: - static PRBool sRunning; static PRIntervalTime sTimeout; static PRLock* sLock; static PRCondVar* sCVar; - static nsIThread* sThread; enum { - kInitialTimeout = 60 /*seconds*/ + kTimeout = 60000 // milliseconds }; }; static MemoryFlusher sGlobalMemoryFlusher; -#endif // NS_MEMORY_FLUSHER_THREAD +#endif // NS_MEMORY_FLUSHER static nsMemoryImpl sGlobalMemory; @@ -197,31 +196,17 @@ nsMemoryImpl::IsLowMemory(PRBool *result) } -nsresult -nsMemoryImpl::Startup() +/*static*/ nsresult +nsMemoryImpl::InitFlusher() { - sFlushLock = PR_NewLock(); - if (!sFlushLock) return NS_ERROR_FAILURE; - -#ifdef NS_MEMORY_FLUSHER_THREAD +#ifdef NS_MEMORY_FLUSHER return sGlobalMemoryFlusher.Init(); #else return NS_OK; #endif } -void -nsMemoryImpl::Shutdown() -{ -#ifdef NS_MEMORY_FLUSHER_THREAD - sGlobalMemoryFlusher.StopAndJoin(); -#endif - - if (sFlushLock) PR_DestroyLock(sFlushLock); - sFlushLock = nsnull; -} - -nsresult +/*static*/ nsresult nsMemoryImpl::Create(nsISupports* outer, const nsIID& aIID, void **aResult) { NS_ENSURE_NO_AGGREGATION(outer); @@ -237,34 +222,15 @@ nsMemoryImpl::FlushMemory(const PRUnichar* aReason, PRBool aImmediate) // They've asked us to run the flusher *immediately*. We've // got to be on the UI main thread for us to be able to do // that...are we? - PRBool isOnUIThread = PR_FALSE; - - nsCOMPtr main; - rv = nsIThread::GetMainThread(getter_AddRefs(main)); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr current; - rv = nsIThread::GetCurrent(getter_AddRefs(current)); - if (NS_SUCCEEDED(rv)) { - if (current == main) - isOnUIThread = PR_TRUE; - } - } - - if (! isOnUIThread) { + if (!NS_IsMainThread()) { NS_ERROR("can't synchronously flush memory: not on UI thread"); return NS_ERROR_FAILURE; } } - { - // Are we already flushing? - nsAutoLock l(sFlushLock); - if (sIsFlushing) - return NS_OK; - - // Well, we are now! - sIsFlushing = PR_TRUE; - } + PRInt32 lastVal = PR_AtomicSet(&sIsFlushing, 1); + if (lastVal) + return NS_OK; // Run the flushers immediately if we can; otherwise, proxy to the // UI thread an run 'em asynchronously. @@ -272,17 +238,8 @@ nsMemoryImpl::FlushMemory(const PRUnichar* aReason, PRBool aImmediate) rv = RunFlushers(aReason); } else { - nsCOMPtr eqs = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (eqs) { - nsCOMPtr eq; - rv = eqs->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eq)); - if (NS_SUCCEEDED(rv)) { - PL_InitEvent(&sFlushEvent.mEvent, this, HandleFlushEvent, DestroyFlushEvent); - sFlushEvent.mReason = aReason; - - rv = eq->PostEvent(NS_REINTERPRET_CAST(PLEvent*, &sFlushEvent)); - } - } + sFlushEvent.mReason = aReason; + rv = NS_DispatchToMainThread(&sFlushEvent, NS_DISPATCH_NORMAL); } return rv; @@ -296,35 +253,24 @@ nsMemoryImpl::RunFlushers(const PRUnichar* aReason) os->NotifyObservers(this, "memory-pressure", aReason); } - { - // Done flushing - nsAutoLock l(sFlushLock); - sIsFlushing = PR_FALSE; - } - + sIsFlushing = 0; return NS_OK; } -void* -nsMemoryImpl::HandleFlushEvent(PLEvent* aEvent) -{ - FlushEvent* event = NS_REINTERPRET_CAST(FlushEvent*, aEvent); +// XXX need NS_IMPL_STATIC_ADDREF/RELEASE +NS_IMETHODIMP_(nsrefcnt) nsMemoryImpl::FlushEvent::AddRef() { return 2; } +NS_IMETHODIMP_(nsrefcnt) nsMemoryImpl::FlushEvent::Release() { return 1; } +NS_IMPL_QUERY_INTERFACE1(nsMemoryImpl::FlushEvent, nsIRunnable) - sGlobalMemory.RunFlushers(event->mReason); - return 0; +NS_IMETHODIMP +nsMemoryImpl::FlushEvent::Run() +{ + sGlobalMemory.RunFlushers(mReason); + return NS_OK; } -void -nsMemoryImpl::DestroyFlushEvent(PLEvent* aEvent) -{ - // no-op, since mEvent is a member of nsMemoryImpl -} - -PRLock* -nsMemoryImpl::sFlushLock; - -PRBool -nsMemoryImpl::sIsFlushing = PR_FALSE; +PRInt32 +nsMemoryImpl::sIsFlushing = 0; nsMemoryImpl::FlushEvent nsMemoryImpl::sFlushEvent; @@ -357,116 +303,42 @@ NS_Free(void* ptr) PR_Free(ptr); } -#ifdef NS_MEMORY_FLUSHER_THREAD +#ifdef NS_MEMORY_FLUSHER -NS_IMPL_QUERY_INTERFACE1(MemoryFlusher, nsIRunnable) +NS_IMPL_QUERY_INTERFACE1(MemoryFlusher, nsITimerCallback) NS_IMETHODIMP -MemoryFlusher::Run() +MemoryFlusher::Notify(nsITimer *timer) { - nsresult rv; - - sRunning = PR_TRUE; - - while (1) { - PRStatus status; - - { - nsAutoLock l(sLock); - if (! sRunning) { - rv = NS_OK; - break; - } - - status = PR_WaitCondVar(sCVar, sTimeout); - } - - if (status != PR_SUCCESS) { - rv = NS_ERROR_FAILURE; - break; - } - - if (! sRunning) { - rv = NS_OK; - break; - } - - PRBool isLowMemory; - rv = sGlobalMemory.IsLowMemory(&isLowMemory); - if (NS_FAILED(rv)) - break; + PRBool isLowMemory; + sGlobalMemory.IsLowMemory(&isLowMemory); #ifdef NS_TEST_MEMORY_FLUSHER - // Fire the flusher *every* time - isLowMemory = PR_TRUE; + // Fire the flusher *every* time + isLowMemory = PR_TRUE; #endif - if (isLowMemory) { - sGlobalMemory.FlushMemory(NS_LITERAL_STRING("low-memory").get(), PR_FALSE); - } - } - - sRunning = PR_FALSE; - - return rv; + if (isLowMemory) + sGlobalMemory.FlushMemory(NS_LITERAL_STRING("low-memory").get(), + PR_FALSE); + return NS_OK; } nsresult MemoryFlusher::Init() { - sTimeout = PR_SecondsToInterval(kInitialTimeout); - sLock = PR_NewLock(); - if (!sLock) return NS_ERROR_FAILURE; + nsCOMPtr timer = do_CreateInstance(NS_TIMER_CONTRACTID); + NS_ENSURE_STATE(timer); - sCVar = PR_NewCondVar(sLock); - if (!sCVar) return NS_ERROR_FAILURE; + // There is no need to keep a reference to the timer object because we + // don't need to kill the timer. It will be killed automatically when + // XPCOM is shutdown. - return NS_NewThread(&sThread, - this, - 0, /* XXX use default stack size? */ - PR_JOINABLE_THREAD); + return timer->InitWithCallback(this, kTimeout, + nsITimer::TYPE_REPEATING_SLACK); } -void -MemoryFlusher::StopAndJoin() -{ - if (sRunning) { - { - nsAutoLock l(sLock); - sRunning = PR_FALSE; - PR_NotifyCondVar(sCVar); - } - - if (sThread) - sThread->Join(); - } - - NS_IF_RELEASE(sThread); - - if (sLock) - PR_DestroyLock(sLock); - - if (sCVar) - PR_DestroyCondVar(sCVar); -} - - -PRBool -MemoryFlusher::sRunning; - -PRIntervalTime -MemoryFlusher::sTimeout; - -PRLock* -MemoryFlusher::sLock; - -PRCondVar* -MemoryFlusher::sCVar; - -nsIThread* -MemoryFlusher::sThread; - -#endif // NS_MEMORY_FLUSHER_THREAD +#endif // NS_MEMORY_FLUSHER nsresult NS_GetMemoryManager(nsIMemory* *result) diff --git a/mozilla/xpcom/base/nsMemoryImpl.h b/mozilla/xpcom/base/nsMemoryImpl.h index e179b1d52ba..ac556936edf 100644 --- a/mozilla/xpcom/base/nsMemoryImpl.h +++ b/mozilla/xpcom/base/nsMemoryImpl.h @@ -39,8 +39,7 @@ #define nsMemoryImpl_h__ #include "nsIMemory.h" -#include "prlock.h" -#include "plevent.h" +#include "nsIRunnable.h" // nsMemoryImpl is a static object. We can do this because it doesn't have // a constructor/destructor or any instance members. Please don't add @@ -56,26 +55,22 @@ public: NS_DECL_NSIMEMORY - static NS_HIDDEN_(nsresult) Startup(); - static NS_HIDDEN_(void) Shutdown(); + static NS_HIDDEN_(nsresult) InitFlusher(); static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void **aResult); NS_HIDDEN_(nsresult) FlushMemory(const PRUnichar* aReason, PRBool aImmediate); protected: - struct FlushEvent { - PLEvent mEvent; + struct FlushEvent : public nsIRunnable { + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIRUNNABLE const PRUnichar* mReason; }; NS_HIDDEN_(nsresult) RunFlushers(const PRUnichar* aReason); - static NS_HIDDEN_(void*) PR_CALLBACK HandleFlushEvent(PLEvent* aEvent); - static NS_HIDDEN_(void) PR_CALLBACK DestroyFlushEvent(PLEvent* aEvent); - - static PRLock* sFlushLock; - static PRBool sIsFlushing; + static PRInt32 sIsFlushing; static FlushEvent sFlushEvent; }; diff --git a/mozilla/xpcom/build/Makefile.in b/mozilla/xpcom/build/Makefile.in index 66f73078eac..5db9df928b8 100644 --- a/mozilla/xpcom/build/Makefile.in +++ b/mozilla/xpcom/build/Makefile.in @@ -139,6 +139,10 @@ SDK_HEADERS = \ nsXPCOMCID.h \ $(NULL) +EXPORTS = \ + nsXPCOMCIDInternal.h \ + $(NULL) + # pull in MoreFiles for MacOSX ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT))) SHARED_LIBRARY_LIBS += ../MoreFiles/$(LIB_PREFIX)macmorefiles_s.$(LIB_SUFFIX) diff --git a/mozilla/xpcom/build/dlldeps.cpp b/mozilla/xpcom/build/dlldeps.cpp index 8cb7fec92aa..38e35b25eda 100644 --- a/mozilla/xpcom/build/dlldeps.cpp +++ b/mozilla/xpcom/build/dlldeps.cpp @@ -47,7 +47,6 @@ #include "nsIAtom.h" #include "nsFixedSizeAllocator.h" #include "nsRecyclingAllocator.h" -#include "nsIThread.h" #include "nsDeque.h" #include "nsTraceRefcnt.h" #include "nsTraceRefcntImpl.h" @@ -95,6 +94,7 @@ #include "nsXPCOMStrings.h" #include "nsStringBuffer.h" #include "nsCategoryCache.h" +#include "nsThreadUtils.h" #if !defined(WINCE) && !defined(XP_OS2) #include "nsWindowsRegKey.h" @@ -145,7 +145,6 @@ void XXXNeverCalled() a.Init(0, 0, 0, 0, 0); a.Alloc(0); a.Free(0, 0); - nsIThread::GetCurrent(nsnull); nsDeque d(nsnull); nsDequeIterator di(d); nsTraceRefcnt::LogAddCOMPtr(nsnull, nsnull); @@ -267,4 +266,14 @@ void XXXNeverCalled() #if !defined(WINCE) && !defined(XP_OS2) NS_NewWindowsRegKey(nsnull); #endif + + NS_NewThread(nsnull, nsnull); + NS_GetCurrentThread(nsnull); + NS_GetCurrentThread(); + NS_GetMainThread(nsnull); + NS_DispatchToCurrentThread(nsnull); + NS_DispatchToMainThread(nsnull, 0); + NS_ProcessPendingEvents(nsnull, 0); + NS_HasPendingEvents(nsnull); + NS_ProcessNextEvent(nsnull, PR_FALSE); } diff --git a/mozilla/xpcom/build/nsXPCOMCID.h b/mozilla/xpcom/build/nsXPCOMCID.h index 26299091d0b..26a4f2c36ad 100644 --- a/mozilla/xpcom/build/nsXPCOMCID.h +++ b/mozilla/xpcom/build/nsXPCOMCID.h @@ -180,12 +180,4 @@ { 0xA9, 0x43, 0xB0, 0x23, 0x34, 0xA6, 0xD0, 0x83 } } #define NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID "@mozilla.org/supports-interface-pointer;1" -/** - * nsHashPropertyBag impl of nsIWritablePropertyBag - */ -#define NS_HASH_PROPERTY_BAG_CID \ -{ 0x678c50b8, 0x6bcb, 0x4ad0, \ -{ 0xb9, 0xb8, 0xc8, 0x11, 0x75, 0x95, 0x51, 0x99 } } -#define NS_HASH_PROPERTY_BAG_CONTRACTID "@mozilla.org/hash-property-bag;1" - #endif diff --git a/mozilla/xpcom/threads/nsEventQueueUtils.h b/mozilla/xpcom/build/nsXPCOMCIDInternal.h similarity index 55% rename from mozilla/xpcom/threads/nsEventQueueUtils.h rename to mozilla/xpcom/build/nsXPCOMCIDInternal.h index 5df2e406f23..08e6f7f59c4 100644 --- a/mozilla/xpcom/threads/nsEventQueueUtils.h +++ b/mozilla/xpcom/build/nsXPCOMCIDInternal.h @@ -1,3 +1,5 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -11,15 +13,14 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is Mozilla. + * The Original Code is Mozilla code. * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Darin Fisher + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -35,44 +36,36 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef nsEventQueueUtils_h__ -#define nsEventQueueUtils_h__ +#ifndef nsXPCOMCIDInternal_h__ +#define nsXPCOMCIDInternal_h__ -#include "nsIEventQueueService.h" -#include "nsIServiceManager.h" -#include "nsCOMPtr.h" +#include "nsXPCOMCID.h" -inline nsresult -NS_GetEventQueueService(nsIEventQueueService **result) -{ - static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - return CallGetService(kEventQueueServiceCID, result); -} +/** + * A hashtable-based property bag component. + * @implements nsIWritablePropertyBag, nsIWritablePropertyBag2 + */ +#define NS_HASH_PROPERTY_BAG_CID \ +{ 0x678c50b8, 0x6bcb, 0x4ad0, \ +{ 0xb9, 0xb8, 0xc8, 0x11, 0x75, 0x95, 0x51, 0x99 } } +#define NS_HASH_PROPERTY_BAG_CONTRACTID "@mozilla.org/hash-property-bag;1" -inline nsresult -NS_GetCurrentEventQ(nsIEventQueue **result, - nsIEventQueueService *serv = nsnull) -{ - nsCOMPtr eqs; - if (!serv) { - nsresult rv = NS_GetEventQueueService(getter_AddRefs(eqs)); - if (NS_FAILED(rv)) return rv; - serv = eqs; - } - return serv->GetThreadEventQueue(NS_CURRENT_THREAD, result); -} +/** + * The global thread manager service. This component is a singleton. + * @implements nsIThreadManager + */ +#define NS_THREADMANAGER_CONTRACTID "@mozilla.org/thread-manager;1" -inline nsresult -NS_GetMainEventQ(nsIEventQueue **result, - nsIEventQueueService *serv = nsnull) -{ - nsCOMPtr eqs; - if (!serv) { - nsresult rv = NS_GetEventQueueService(getter_AddRefs(eqs)); - if (NS_FAILED(rv)) return rv; - serv = eqs; - } - return serv->GetThreadEventQueue(NS_UI_THREAD, result); -} +/** + * A thread pool component. + * @implements nsIThreadPool + */ +#define NS_THREADPOOL_CONTRACTID "@mozilla.org/thread-pool;1" -#endif // !nsEventQueueUtils_h__ +/** + * The global proxy object manager. This component is a singleton. + * @implement nsIProxyObjectManager + */ +#define NS_XPCOMPROXY_CONTRACTID "@mozilla.org/xpcomproxy;1" + +#endif // nsXPCOMCIDInternal_h__ diff --git a/mozilla/xpcom/build/nsXPComInit.cpp b/mozilla/xpcom/build/nsXPComInit.cpp index bfb7450cc0c..fb901cfd818 100644 --- a/mozilla/xpcom/build/nsXPComInit.cpp +++ b/mozilla/xpcom/build/nsXPComInit.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 sts=4 ci et: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -38,6 +39,7 @@ #include "nsXPCOM.h" #include "nsXPCOMPrivate.h" +#include "nsXPCOMCIDInternal.h" #include "nscore.h" #include "nsIClassInfoImpl.h" #include "nsStaticComponents.h" @@ -71,9 +73,8 @@ #include "nsIServiceManager.h" #include "nsGenericFactory.h" -#include "nsEventQueueService.h" -#include "nsEventQueue.h" -#include "nsEventQueueUtils.h" +#include "nsThreadManager.h" +#include "nsThreadPool.h" #include "nsIProxyObjectManager.h" #include "nsProxyEventPrivate.h" // access to the impl of nsProxyObjectManager for the generic factory registration. @@ -154,7 +155,6 @@ static NS_DEFINE_CID(kMemoryCID, NS_MEMORY_CID); static NS_DEFINE_CID(kINIParserFactoryCID, NS_INIPARSERFACTORY_CID); NS_GENERIC_FACTORY_CONSTRUCTOR(nsProcess) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsEventQueueServiceImpl, Init) #define NS_ENVIRONMENT_CLASSNAME "Environment Service" @@ -226,6 +226,21 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsUUIDGenerator) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacUtilsImpl) #endif +static NS_METHOD +nsThreadManagerGetSingleton(nsISupports* outer, + const nsIID& aIID, + void* *aInstancePtr) +{ + NS_ASSERTION(aInstancePtr, "null outptr"); + NS_ENSURE_TRUE(!outer, NS_ERROR_NO_AGGREGATION); + + return nsThreadManager::get()->QueryInterface(aIID, aInstancePtr); +} +NS_DECL_CLASSINFO(nsThreadManager) + +NS_GENERIC_FACTORY_CONSTRUCTOR(nsThreadPool) +NS_DECL_CLASSINFO(nsThreadPool) + static NS_METHOD nsXPTIInterfaceInfoManagerGetSingleton(nsISupports* outer, const nsIID& aIID, @@ -358,9 +373,6 @@ static const nsModuleComponentInfo components[] = { #endif COMPONENT(OBSERVERSERVICE, nsObserverService::Create), COMPONENT(GENERICFACTORY, nsGenericFactory::Create), - COMPONENT(EVENTQUEUESERVICE, nsEventQueueServiceImplConstructor), - COMPONENT(EVENTQUEUE, nsEventQueueImpl::Create), - COMPONENT(THREAD, nsThread::Create), #define NS_XPCOMPROXY_CID NS_PROXYEVENT_MANAGER_CID COMPONENT(XPCOMPROXY, nsProxyObjectManager::Create), @@ -397,6 +409,12 @@ static const nsModuleComponentInfo components[] = { COMPONENT(PROCESS, nsProcessConstructor), COMPONENT(ENVIRONMENT, nsEnvironment::Create), + COMPONENT_CI_FLAGS(THREADMANAGER, nsThreadManagerGetSingleton, + nsThreadManager, + nsIClassInfo::THREADSAFE | nsIClassInfo::SINGLETON), + COMPONENT_CI_FLAGS(THREADPOOL, nsThreadPoolConstructor, + nsThreadPool, nsIClassInfo::THREADSAFE), + COMPONENT_CI_FLAGS(STRINGINPUTSTREAM, nsStringInputStreamConstructor, nsStringInputStream, nsIClassInfo::THREADSAFE), COMPONENT(MULTIPLEXINPUTSTREAM, nsMultiplexInputStreamConstructor), @@ -484,17 +502,13 @@ NS_InitXPCOM3(nsIServiceManager* *result, NS_LogInit(); // Establish the main thread here. - rv = nsIThread::SetMainThread(); + rv = nsThreadManager::get()->Init(); if (NS_FAILED(rv)) return rv; // Set up the timer globals/timer thread rv = nsTimerImpl::Startup(); NS_ENSURE_SUCCESS(rv, rv); - // Startup the memory manager - rv = nsMemoryImpl::Startup(); - if (NS_FAILED(rv)) return rv; - #ifndef WINCE // If the locale hasn't already been setup by our embedder, // get us out of the "C" locale and into the system @@ -628,6 +642,9 @@ NS_InitXPCOM3(nsIServiceManager* *result, // to the directory service. nsDirectoryService::gService->RegisterCategoryProviders(); + // Initialize memory flusher + nsMemoryImpl::InitFlusher(); + // Notify observers of xpcom autoregistration start NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_OBSERVER_ID, nsnull, @@ -661,8 +678,9 @@ NS_InitXPCOM3(nsIServiceManager* *result, EXPORT_XPCOM_API(nsresult) NS_ShutdownXPCOM(nsIServiceManager* servMgr) { - nsresult rv; + NS_ENSURE_STATE(NS_IsMainThread()); + nsresult rv; nsCOMPtr moduleLoaders; // Notify observers of xpcom shutting down @@ -670,14 +688,8 @@ NS_ShutdownXPCOM(nsIServiceManager* servMgr) // Block it so that the COMPtr will get deleted before we hit // servicemanager shutdown - // grab the event queue service so that we can process events and - // manage event queues - nsRefPtr eqs; - CallGetService(NS_EVENTQUEUESERVICE_CONTRACTID, - (nsEventQueueServiceImpl**) getter_AddRefs(eqs)); - - nsCOMPtr currentQ; - NS_GetCurrentEventQ(getter_AddRefs(currentQ), eqs); + nsCOMPtr thread = do_GetCurrentThread(); + NS_ENSURE_STATE(thread); nsRefPtr observerService; CallGetService("@mozilla.org/observer-service;1", @@ -695,28 +707,27 @@ NS_ShutdownXPCOM(nsIServiceManager* servMgr) } } - if (currentQ) - currentQ->ProcessPendingEvents(); - - // Shutdown the timer thread and all timers that might still be alive - nsTimerImpl::Shutdown(); - - if (currentQ) - currentQ->ProcessPendingEvents(); + NS_ProcessPendingEvents(thread); if (observerService) (void) observerService-> NotifyObservers(nsnull, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, nsnull); - if (currentQ) - currentQ->ProcessPendingEvents(); + NS_ProcessPendingEvents(thread); - if (eqs) - eqs->Shutdown(); + // Shutdown the timer thread and all timers that might still be alive before + // shutting down the component manager + nsTimerImpl::Shutdown(); - if (currentQ) - currentQ->ProcessPendingEvents(); + NS_ProcessPendingEvents(thread); + + // Shutdown all remaining threads. This method does not return until + // all threads created using the thread manager (with the exception of + // the main thread) have exited. + nsThreadManager::get()->Shutdown(); + + NS_ProcessPendingEvents(thread); // We save the "xpcom-shutdown-loaders" observers to notify after // the observerservice is gone. @@ -808,9 +819,7 @@ NS_ShutdownXPCOM(nsIServiceManager* servMgr) ShutdownSpecialSystemDirectory(); EmptyEnumeratorImpl::Shutdown(); - nsMemoryImpl::Shutdown(); - nsThread::Shutdown(); NS_PurgeAtomTable(); NS_IF_RELEASE(gDebug); diff --git a/mozilla/xpcom/components/nsCategoryManager.cpp b/mozilla/xpcom/components/nsCategoryManager.cpp index de75f0ad662..6efed14e216 100644 --- a/mozilla/xpcom/components/nsCategoryManager.cpp +++ b/mozilla/xpcom/components/nsCategoryManager.cpp @@ -59,6 +59,7 @@ #include "nsQuickSort.h" #include "nsEnumeratorUtils.h" #include "nsIProxyObjectManager.h" +#include "nsThreadUtils.h" class nsIComponentLoaderManager; @@ -546,12 +547,13 @@ nsCategoryManager::NotifyObservers( const char *aTopic, return; nsCOMPtr obsProxy; - NS_GetProxyForObject(NS_UI_THREAD_EVENTQ, + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIObserverService), observerService, - PROXY_ASYNC, + NS_PROXY_ASYNC, getter_AddRefs(obsProxy)); - if (!obsProxy) return; + if (!obsProxy) + return; if (aEntryName) { nsCOMPtr entry diff --git a/mozilla/xpcom/ds/nsObserverService.cpp b/mozilla/xpcom/ds/nsObserverService.cpp index c5b11be88f9..c13bf96161d 100644 --- a/mozilla/xpcom/ds/nsObserverService.cpp +++ b/mozilla/xpcom/ds/nsObserverService.cpp @@ -47,8 +47,8 @@ #include "nsObserverService.h" #include "nsObserverList.h" #include "nsHashtable.h" +#include "nsThreadUtils.h" #include "nsIWeakReference.h" -#include "nsIThread.h" #include "nsIEnumerator.h" #define NOTIFY_GLOBAL_OBSERVERS @@ -111,7 +111,7 @@ nsObserverService::Create(nsISupports* outer, const nsIID& aIID, void* *aInstanc } #define NS_ENSURE_VALIDCALL \ - if (!nsIThread::IsMainThread()) { \ + if (!NS_IsMainThread()) { \ NS_ERROR("Using observer service off the main thread!"); \ return NS_ERROR_UNEXPECTED; \ } \ diff --git a/mozilla/xpcom/ds/nsRecyclingAllocator.cpp b/mozilla/xpcom/ds/nsRecyclingAllocator.cpp index da79eafc95f..525537a3f1e 100644 --- a/mozilla/xpcom/ds/nsRecyclingAllocator.cpp +++ b/mozilla/xpcom/ds/nsRecyclingAllocator.cpp @@ -238,7 +238,9 @@ nsRecyclingAllocator::Free(void *ptr) (void) NS_NewTimer(&mRecycleTimer, nsRecycleTimerCallback, this, NS_SEC_TO_MS(mRecycleAfter), nsITimer::TYPE_REPEATING_SLACK); - NS_ASSERTION(mRecycleTimer, "nsRecyclingAllocator: Creating timer failed"); + // This can fail during xpcom shutdown + if (!mRecycleTimer) + NS_WARNING("nsRecyclingAllocator: Creating timer failed"); } } diff --git a/mozilla/xpcom/glue/Makefile.in b/mozilla/xpcom/glue/Makefile.in index 2ee9270de58..0e59db6e7ad 100644 --- a/mozilla/xpcom/glue/Makefile.in +++ b/mozilla/xpcom/glue/Makefile.in @@ -86,6 +86,8 @@ SDK_HEADERS = \ nsTHashtable.h \ nsVoidArray.h \ nsTArray.h \ + nsThreadUtils.h \ + nsTWeakRef.h \ nsID.h \ nsIGenericFactory.h \ nsIInterfaceRequestorUtils.h \ diff --git a/mozilla/xpcom/glue/nsTWeakRef.h b/mozilla/xpcom/glue/nsTWeakRef.h new file mode 100644 index 00000000000..21618f0d7f7 --- /dev/null +++ b/mozilla/xpcom/glue/nsTWeakRef.h @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsTWeakRef_h__ +#define nsTWeakRef_h__ + +#ifndef nsDebug_h___ +#include "nsDebug.h" +#endif + +/** + * A weak reference class for use with generic C++ objects. NOT THREADSAFE! + * + * Example usage: + * + * class A { + * public: + * A() : mWeakSelf(this) { + * } + * ~A() { + * mWeakSelf.forget(); + * } + * void Bar() { printf("Bar!\n"); } + * const nsTWeakRef &AsWeakRef() const { return mWeakSelf; } + * private: + * nsTWeakRef mWeakSelf; + * }; + * + * class B { + * public: + * void SetA(const nsTWeakRef &a) { + * mA = a; + * } + * void Foo() { + * if (mA) + * mA->Bar(); + * } + * private: + * nsTWeakRef mA; + * }; + * + * void Test() { + * B b; + * { + * A a; + * b.SetA(a.AsWeakRef()); + * b.Foo(); // prints "Bar!" + * } + * b.Foo(); // prints nothing because |a| has already been destroyed + * } + * + * One can imagine much more complex examples, especially when asynchronous + * event processing is involved. + * + * Keep in mind that you should only ever need a class like this when you have + * multiple instances of B, such that it is not possible for A and B to simply + * have pointers to one another. + */ +template +class nsTWeakRef { +public: + ~nsTWeakRef() { + if (mRef) + mRef->Release(); + } + + /** + * Construct from an object pointer (may be null). + */ + explicit + nsTWeakRef(Type *obj = nsnull) { + if (obj) { + mRef = new Inner(obj); + } else { + mRef = nsnull; + } + } + + /** + * Construct from another weak reference object. + */ + explicit + nsTWeakRef(const nsTWeakRef &other) : mRef(other.mRef) { + if (mRef) + mRef->AddRef(); + } + + /** + * Assign from an object pointer. + */ + nsTWeakRef &operator=(Type *obj) { + if (mRef) + mRef->Release(); + if (obj) { + mRef = new Inner(obj); + } else { + mRef = nsnull; + } + return *this; + } + + /** + * Assign from another weak reference object. + */ + nsTWeakRef &operator=(const nsTWeakRef &other) { + if (mRef) + mRef->Release(); + mRef = other.mRef; + if (mRef) + mRef->AddRef(); + return *this; + } + + /** + * Get the referenced object. This method may return null if the reference + * has been cleared or if an out-of-memory error occured at assignment. + */ + Type *get() const { + return mRef ? mRef->mObj : nsnull; + } + + /** + * Called to "null out" the weak reference. Typically, the object referenced + * by this weak reference calls this method when it is being destroyed. + * @returns The former referenced object. + */ + Type *forget() { + Type *obj; + if (mRef) { + obj = mRef->mObj; + mRef->mObj = nsnull; + mRef->Release(); + mRef = nsnull; + } else { + obj = nsnull; + } + return obj; + } + + /** + * Allow |*this| to be treated as a |Type*| for convenience. + */ + operator Type *() const { + return get(); + } + + /** + * Allow |*this| to be treated as a |Type*| for convenience. Use with + * caution since this method will crash if the referenced object is null. + */ + Type *operator->() const { + NS_ASSERTION(mRef && mRef->mObj, + "You can't dereference a null weak reference with operator->()."); + return get(); + } + +private: + + struct Inner { + int mCnt; + Type *mObj; + + Inner(Type *obj) : mCnt(1), mObj(obj) {} + void AddRef() { ++mCnt; } + void Release() { if (--mCnt == 0) delete this; } + }; + + Inner *mRef; +}; + +#endif // nsTWeakRef_h__ diff --git a/mozilla/xpcom/glue/nsThreadUtils.cpp b/mozilla/xpcom/glue/nsThreadUtils.cpp new file mode 100644 index 00000000000..7c7b12b4921 --- /dev/null +++ b/mozilla/xpcom/glue/nsThreadUtils.cpp @@ -0,0 +1,233 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsThreadUtils.h" + +#ifdef MOZILLA_INTERNAL_API +# include "nsThreadManager.h" +#else +# include "nsXPCOMCIDInternal.h" +# include "nsIThreadManager.h" +# include "nsServiceManagerUtils.h" +#endif + +#ifndef XPCOM_GLUE_AVOID_NSPR + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsRunnable, nsIRunnable) + +NS_IMETHODIMP +nsRunnable::Run() +{ + // Do nothing + return NS_OK; +} + +#endif // XPCOM_GLUE_AVOID_NSPR + +//----------------------------------------------------------------------------- + +NS_METHOD +NS_NewThread(nsIThread **result, nsIRunnable *event) +{ + nsCOMPtr thread; +#ifdef MOZILLA_INTERNAL_API + nsresult rv = nsThreadManager::get()-> + nsThreadManager::NewThread(0, getter_AddRefs(thread)); +#else + nsresult rv; + nsCOMPtr mgr = + do_GetService(NS_THREADMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mgr->NewThread(0, getter_AddRefs(thread)); +#endif + NS_ENSURE_SUCCESS(rv, rv); + + if (event) { + rv = thread->Dispatch(event, NS_DISPATCH_NORMAL); + NS_ENSURE_SUCCESS(rv, rv); + } + + *result = nsnull; + thread.swap(*result); + return NS_OK; +} + +NS_METHOD +NS_GetCurrentThread(nsIThread **result) +{ +#ifdef MOZILLA_INTERNAL_API + return nsThreadManager::get()->nsThreadManager::GetCurrentThread(result); +#else + nsresult rv; + nsCOMPtr mgr = + do_GetService(NS_THREADMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + return mgr->GetCurrentThread(result); +#endif +} + +NS_METHOD +NS_GetMainThread(nsIThread **result) +{ +#ifdef MOZILLA_INTERNAL_API + return nsThreadManager::get()->nsThreadManager::GetMainThread(result); +#else + nsresult rv; + nsCOMPtr mgr = + do_GetService(NS_THREADMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + return mgr->GetMainThread(result); +#endif +} + +NS_METHOD_(PRBool) +NS_IsMainThread() +{ + PRBool result = PR_FALSE; +#ifdef MOZILLA_INTERNAL_API + nsThreadManager::get()->nsThreadManager::GetIsMainThread(&result); +#else + nsCOMPtr mgr = + do_GetService(NS_THREADMANAGER_CONTRACTID); + if (mgr) + mgr->GetIsMainThread(&result); +#endif + return result; +} + +NS_METHOD +NS_DispatchToCurrentThread(nsIRunnable *event) +{ +#ifdef MOZILLA_INTERNAL_API + nsIThread *thread = NS_GetCurrentThread(); + NS_ENSURE_STATE(thread); +#else + nsCOMPtr thread; + nsresult rv = NS_GetCurrentThread(getter_AddRefs(thread)); + NS_ENSURE_SUCCESS(rv, rv); +#endif + return thread->Dispatch(event, NS_DISPATCH_NORMAL); +} + +NS_METHOD +NS_DispatchToMainThread(nsIRunnable *event, PRUint32 dispatchFlags) +{ + nsCOMPtr thread; + nsresult rv = NS_GetMainThread(getter_AddRefs(thread)); + NS_ENSURE_SUCCESS(rv, rv); + return thread->Dispatch(event, dispatchFlags); +} + +NS_METHOD +NS_ProcessPendingEvents(nsIThread *thread, PRIntervalTime timeout) +{ + nsresult rv = NS_OK; + +#ifdef MOZILLA_INTERNAL_API + if (!thread) { + thread = NS_GetCurrentThread(); + NS_ENSURE_STATE(thread); + } +#else + nsCOMPtr current; + if (!thread) { + rv = NS_GetCurrentThread(getter_AddRefs(current)); + NS_ENSURE_SUCCESS(rv, rv); + thread = current.get(); + } +#endif + + PRIntervalTime start = PR_IntervalNow(); + for (;;) { + PRBool processedEvent; + rv = thread->ProcessNextEvent(PR_FALSE, &processedEvent); + if (NS_FAILED(rv) || !processedEvent) + break; + if (PR_IntervalNow() - start > timeout) + break; + } + return rv; +} + +PRBool +NS_HasPendingEvents(nsIThread *thread) +{ +#ifdef MOZILLA_INTERNAL_API + if (!thread) { + thread = NS_GetCurrentThread(); + NS_ENSURE_STATE(thread); + } +#else + nsCOMPtr current; + if (!thread) { + NS_GetCurrentThread(getter_AddRefs(current)); + NS_ENSURE_TRUE(current, PR_FALSE); + thread = current.get(); + } +#endif + PRBool val; + return NS_SUCCEEDED(thread->HasPendingEvents(&val)) && val; +} + +PRBool +NS_ProcessNextEvent(nsIThread *thread, PRBool mayWait) +{ +#ifdef MOZILLA_INTERNAL_API + if (!thread) { + thread = NS_GetCurrentThread(); + NS_ENSURE_STATE(thread); + } +#else + nsCOMPtr current; + if (!thread) { + NS_GetCurrentThread(getter_AddRefs(current)); + NS_ENSURE_TRUE(current, PR_FALSE); + thread = current.get(); + } +#endif + PRBool val; + return NS_SUCCEEDED(thread->ProcessNextEvent(mayWait, &val)) && val; +} + +#ifdef MOZILLA_INTERNAL_API +nsIThread * +NS_GetCurrentThread() { + return nsThreadManager::get()->GetCurrentThread(); +} +#endif diff --git a/mozilla/xpcom/glue/nsThreadUtils.h b/mozilla/xpcom/glue/nsThreadUtils.h new file mode 100644 index 00000000000..ffb982170d7 --- /dev/null +++ b/mozilla/xpcom/glue/nsThreadUtils.h @@ -0,0 +1,375 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsThreadUtils_h__ +#define nsThreadUtils_h__ + +#include "prthread.h" +#include "prinrval.h" +#include "nsIThreadManager.h" +#include "nsIThread.h" +#include "nsIRunnable.h" +#include "nsStringGlue.h" +#include "nsCOMPtr.h" + +// This is needed on some systems to prevent collisions between the symbols +// appearing in xpcom_core and xpcomglue. It may be unnecessary in the future +// with better toolchain support. +#ifdef MOZILLA_INTERNAL_API +# define NS_NewThread NS_NewThread_P +# define NS_GetCurrentThread NS_GetCurrentThread_P +# define NS_GetMainThread NS_GetMainThread_P +# define NS_IsMainThread NS_IsMainThread_P +# define NS_DispatchToCurrentThread NS_DispatchToCurrentThread_P +# define NS_DispatchToMainThread NS_DispatchToMainThread_P +# define NS_ProcessPendingEvents NS_ProcessPendingEvents_P +# define NS_HasPendingEvents NS_HasPendingEvents_P +# define NS_ProcessNextEvent NS_ProcessNextEvent_P +#endif + +//----------------------------------------------------------------------------- +// These methods are alternatives to the methods on nsIThreadManager, provided +// for convenience. + +/** + * Create a new thread, and optionally provide an initial event for the thread. + * + * @param result + * The resulting nsIThread object. + * @param initialEvent + * The initial event to run on this thread. This parameter may be null. + * + * @returns NS_ERROR_INVALID_ARG + * Indicates that the given name is not unique. + */ +extern NS_COM_GLUE NS_METHOD +NS_NewThread(nsIThread **result, nsIRunnable *initialEvent = nsnull); + +/** + * Get a reference to the current thread. + * + * @param result + * The resulting nsIThread object. + */ +extern NS_COM_GLUE NS_METHOD +NS_GetCurrentThread(nsIThread **result); + +/** + * Get a reference to the main thread. + * + * @param result + * The resulting nsIThread object. + */ +extern NS_COM_GLUE NS_METHOD +NS_GetMainThread(nsIThread **result); + +/** + * Test to see if the current thread is the main thread. + * + * @returns PR_TRUE if the current thread is the main thread, and PR_FALSE + * otherwise. + */ +extern NS_COM_GLUE NS_METHOD_(PRBool) +NS_IsMainThread(); + +/** + * Dispatch the given event to the current thread. + * + * @param event + * The event to dispatch. + * + * @returns NS_ERROR_INVALID_ARG + * If event is null. + */ +extern NS_COM_GLUE NS_METHOD +NS_DispatchToCurrentThread(nsIRunnable *event); + +/** + * Dispatch the given event to the main thread. + * + * @param event + * The event to dispatch. + * @param dispatchFlags + * The flags to pass to the main thread's dispatch method. + * + * @returns NS_ERROR_INVALID_ARG + * If event is null. + */ +extern NS_COM_GLUE NS_METHOD +NS_DispatchToMainThread(nsIRunnable *event, + PRUint32 dispatchFlags = NS_DISPATCH_NORMAL); + +/** + * Process all pending events for the given thread before returning. This + * method simply calls ProcessNextEvent on the thread while HasPendingEvents + * continues to return true and the time spent in NS_ProcessPendingEvents + * does not exceed the given timeout value. + * + * @param thread + * The thread object for which to process pending events. If null, then + * events will be processed for the current thread. + * @param timeout + * The maximum number of milliseconds to spend processing pending events. + * Events are not pre-empted to honor this timeout. Rather, the timeout + * value is simply used to determine whether or not to process another event. + * Pass PR_INTERVAL_NO_TIMEOUT to specify no timeout. + */ +extern NS_COM_GLUE NS_METHOD +NS_ProcessPendingEvents(nsIThread *thread, + PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT); + +/** + * Shortcut for nsIThread::HasPendingEvents. + * + * It is an error to call this function when the given thread is not the + * current thread. This function will return PR_FALSE if called from some + * other thread. + * + * @param thread + * The current thread or null. + * + * @returns + * A boolean value that if "true" indicates that there are pending events + * in the current thread's event queue. + */ +extern NS_COM_GLUE PRBool +NS_HasPendingEvents(nsIThread *thread = nsnull); + +/** + * Shortcut for nsIThread::ProcessNextEvent. + * + * It is an error to call this function when the given thread is not the + * current thread. This function will simply return PR_FALSE if called + * from some other thread. + * + * @param thread + * The current thread or null. + * @param mayWait + * A boolean parameter that if "true" indicates that the method may block + * the calling thread to wait for a pending event. + * + * @returns + * A boolean value that if "true" indicates that an event from the current + * thread's event queue was processed. + */ +extern NS_COM_GLUE PRBool +NS_ProcessNextEvent(nsIThread *thread = nsnull, PRBool mayWait = PR_TRUE); + +//----------------------------------------------------------------------------- +// Helpers that work with nsCOMPtr: + +inline already_AddRefed +do_GetCurrentThread() { + nsIThread *thread = nsnull; + NS_GetCurrentThread(&thread); + return already_AddRefed(thread); +} + +inline already_AddRefed +do_GetMainThread() { + nsIThread *thread = nsnull; + NS_GetMainThread(&thread); + return already_AddRefed(thread); +} + +//----------------------------------------------------------------------------- + +#ifdef MOZILLA_INTERNAL_API +// Fast access to the current thread. Do not release the returned pointer! If +// you want to use this pointer from some other thread, then you will need to +// AddRef it. Otherwise, you should only consider this pointer valid from code +// running on the current thread. +extern NS_COM_GLUE nsIThread *NS_GetCurrentThread(); +#endif + +//----------------------------------------------------------------------------- + +#ifndef XPCOM_GLUE_AVOID_NSPR + +#undef IMETHOD_VISIBILITY +#define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT + +// This class is designed to be subclassed. +class NS_COM_GLUE nsRunnable : public nsIRunnable +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIRUNNABLE + + nsRunnable() { + } + +protected: + virtual ~nsRunnable() { + } +}; + +#undef IMETHOD_VISIBILITY +#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN + +#endif // XPCOM_GLUE_AVOID_NSPR + +#ifdef MOZILLA_INTERNAL_API +#include "nsAutoPtr.h" + +// An event that can be used to call a method on a class. The class type must +// support reference counting. +template +class nsRunnableMethod : public nsRunnable +{ +public: + typedef void (T::*Method)(); + + nsRunnableMethod(T *obj, Method method) + : mObj(obj), mMethod(method) { + } + + NS_IMETHOD Run() { + (mObj->*mMethod)(); + return NS_OK; + } + +private: + nsRefPtr mObj; + Method mMethod; +}; + +// Use this helper function like so: +// +// nsCOMPtr event = +// NS_NewRunnableMethod(myObject, &MyClass::HandleEvent); +// NS_DispatchToCurrentThread(event); +// +// Constraints: +// - myObject must be of type MyClass +// - MyClass must defined AddRef and Release methods +// +template +inline nsIRunnable * +NS_NewRunnableMethod(T *obj, typename nsRunnableMethod::Method method) { + return new nsRunnableMethod(obj, method); +} + +#endif // MOZILLA_INTERNAL_API + +// This class is designed to be used when you have an event class E that has a +// pointer back to resource class R. If R goes away while E is still pending, +// then it is important to "revoke" E so that it does not try use R after R has +// been destroyed. nsRevocableEventPtr makes it easy for R to manage such +// situations: +// +// class R; +// +// class E : public nsRunnable { +// public: +// void Revoke() { +// mResource = nsnull; +// } +// private: +// R *mResource; +// }; +// +// class R { +// public: +// void EventHandled() { +// mEvent.Forget(); +// } +// private: +// nsRevocableEventPtr mEvent; +// }; +// +// void R::PostEvent() { +// // Make sure any pending event is revoked. +// mEvent->Revoke(); +// +// nsCOMPtr event = new E(); +// if (NS_SUCCEEDED(NS_DispatchToCurrentThread(event))) { +// // Keep pointer to event so we can revoke it. +// mEvent = event; +// } +// } +// +// NS_IMETHODIMP E::Run() { +// if (!mResource) +// return NS_OK; +// ... +// mResource->EventHandled(); +// return NS_OK; +// } +// +template +class nsRevocableEventPtr { +public: + nsRevocableEventPtr() + : mEvent(nsnull) { + } + + ~nsRevocableEventPtr() { + Revoke(); + } + + const nsRevocableEventPtr& operator=(T *event) { + Revoke(); + mEvent = event; + return *this; + } + + void Revoke() { + if (mEvent) { + mEvent->Revoke(); + mEvent = nsnull; + } + } + + void Forget() { + mEvent = nsnull; + } + + PRBool IsPending() { + return mEvent != nsnull; + } + +private: + // Not implemented + nsRevocableEventPtr(const nsRevocableEventPtr&); + nsRevocableEventPtr& operator=(const nsRevocableEventPtr&); + + T *mEvent; +}; + +#endif // nsThreadUtils_h__ diff --git a/mozilla/xpcom/glue/objs.mk b/mozilla/xpcom/glue/objs.mk index aee4f070bf7..0830e8b29f1 100644 --- a/mozilla/xpcom/glue/objs.mk +++ b/mozilla/xpcom/glue/objs.mk @@ -58,6 +58,7 @@ XPCOM_GLUE_SRC_LCPPSRCS = \ nsQuickSort.cpp \ nsVoidArray.cpp \ nsTArray.cpp \ + nsThreadUtils.cpp \ $(NULL) XPCOM_GLUE_SRC_CPPSRCS = $(addprefix $(topsrcdir)/xpcom/glue/, $(XPCOM_GLUE_SRC_LCPPSRCS)) diff --git a/mozilla/xpcom/io/nsIAsyncInputStream.idl b/mozilla/xpcom/io/nsIAsyncInputStream.idl index bb9a46c3cdd..99053fd116e 100644 --- a/mozilla/xpcom/io/nsIAsyncInputStream.idl +++ b/mozilla/xpcom/io/nsIAsyncInputStream.idl @@ -52,7 +52,7 @@ interface nsIEventTarget; * necessary that a non-blocking nsIInputStream implementation also implement * nsIAsyncInputStream. */ -[scriptable, uuid(15a15329-00de-44e8-ab06-0d0b0d43dc5b)] +[scriptable, uuid(a5f255ab-4801-4161-8816-277ac92f6ad1)] interface nsIAsyncInputStream : nsIInputStream { /** diff --git a/mozilla/xpcom/io/nsIAsyncOutputStream.idl b/mozilla/xpcom/io/nsIAsyncOutputStream.idl index f8fbded2f62..c9ea330567f 100644 --- a/mozilla/xpcom/io/nsIAsyncOutputStream.idl +++ b/mozilla/xpcom/io/nsIAsyncOutputStream.idl @@ -52,7 +52,7 @@ interface nsIEventTarget; * necessary that a non-blocking nsIOutputStream implementation also implement * nsIAsyncOutputStream. */ -[scriptable, uuid(10dc9c94-8aff-49c6-8af9-d7fdb7339dae)] +[scriptable, uuid(beb632d3-d77a-4e90-9134-f9ece69e8200)] interface nsIAsyncOutputStream : nsIOutputStream { /** diff --git a/mozilla/xpcom/io/nsStreamUtils.cpp b/mozilla/xpcom/io/nsStreamUtils.cpp index fb7fbce7153..a90eed23bd6 100644 --- a/mozilla/xpcom/io/nsStreamUtils.cpp +++ b/mozilla/xpcom/io/nsStreamUtils.cpp @@ -40,12 +40,13 @@ #include "nsCOMPtr.h" #include "nsIPipe.h" #include "nsIEventTarget.h" +#include "nsIRunnable.h" #include "nsAutoLock.h" #include "nsString.h" //----------------------------------------------------------------------------- -class nsInputStreamReadyEvent : public PLEvent +class nsInputStreamReadyEvent : public nsIRunnable , public nsIInputStreamCallback { public: @@ -61,28 +62,28 @@ public: private: ~nsInputStreamReadyEvent() { - if (mCallback) { - nsresult rv; - // - // whoa!! looks like we never posted this event. take care to - // release mCallback on the correct thread. if mTarget lives on the - // calling thread, then we are ok. otherwise, we have to try to - // proxy the Release over the right thread. if that thread is dead, - // then there's nothing we can do... better to leak than crash. - // - PRBool val; - rv = mTarget->IsOnCurrentThread(&val); - if (NS_FAILED(rv) || !val) { - nsCOMPtr event; - NS_NewInputStreamReadyEvent(getter_AddRefs(event), mCallback, mTarget); - mCallback = 0; - if (event) { - rv = event->OnInputStreamReady(nsnull); - if (NS_FAILED(rv)) { - NS_NOTREACHED("leaking stream event"); - nsISupports *sup = event; - NS_ADDREF(sup); - } + if (!mCallback) + return; + // + // whoa!! looks like we never posted this event. take care to + // release mCallback on the correct thread. if mTarget lives on the + // calling thread, then we are ok. otherwise, we have to try to + // proxy the Release over the right thread. if that thread is dead, + // then there's nothing we can do... better to leak than crash. + // + PRBool val; + nsresult rv = mTarget->IsOnCurrentThread(&val); + if (NS_FAILED(rv) || !val) { + nsCOMPtr event; + NS_NewInputStreamReadyEvent(getter_AddRefs(event), mCallback, + mTarget); + mCallback = 0; + if (event) { + rv = event->OnInputStreamReady(nsnull); + if (NS_FAILED(rv)) { + NS_NOTREACHED("leaking stream event"); + nsISupports *sup = event; + NS_ADDREF(sup); } } } @@ -93,48 +94,38 @@ public: { mStream = stream; - // will be released when event is handled - NS_ADDREF_THIS(); - - PL_InitEvent(this, nsnull, EventHandler, EventCleanup); - - if (NS_FAILED(mTarget->PostEvent(this))) { - NS_WARNING("PostEvent failed"); - NS_RELEASE_THIS(); + nsresult rv = + mTarget->Dispatch(this, NS_DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + NS_WARNING("Dispatch failed"); return NS_ERROR_FAILURE; } return NS_OK; } + NS_IMETHOD Run() + { + if (mCallback) { + if (mStream) + mCallback->OnInputStreamReady(mStream); + mCallback = nsnull; + } + return NS_OK; + } + private: nsCOMPtr mStream; nsCOMPtr mCallback; nsCOMPtr mTarget; - - PR_STATIC_CALLBACK(void *) EventHandler(PLEvent *plevent) - { - nsInputStreamReadyEvent *ev = (nsInputStreamReadyEvent *) plevent; - // bypass event delivery if this is a cleanup event... - if (ev->mCallback) - ev->mCallback->OnInputStreamReady(ev->mStream); - ev->mCallback = 0; - return NULL; - } - - PR_STATIC_CALLBACK(void) EventCleanup(PLEvent *plevent) - { - nsInputStreamReadyEvent *ev = (nsInputStreamReadyEvent *) plevent; - NS_RELEASE(ev); - } }; -NS_IMPL_THREADSAFE_ISUPPORTS1(nsInputStreamReadyEvent, +NS_IMPL_THREADSAFE_ISUPPORTS2(nsInputStreamReadyEvent, nsIRunnable, nsIInputStreamCallback) //----------------------------------------------------------------------------- -class nsOutputStreamReadyEvent : public PLEvent +class nsOutputStreamReadyEvent : public nsIRunnable , public nsIOutputStreamCallback { public: @@ -150,82 +141,65 @@ public: private: ~nsOutputStreamReadyEvent() { - if (mCallback) { - nsresult rv; - // - // whoa!! looks like we never posted this event. take care to - // release mCallback on the correct thread. if mTarget lives on the - // calling thread, then we are ok. otherwise, we have to try to - // proxy the Release over the right thread. if that thread is dead, - // then there's nothing we can do... better to leak than crash. - // - PRBool val; - rv = mTarget->IsOnCurrentThread(&val); - if (NS_FAILED(rv) || !val) { - nsCOMPtr event; - NS_NewOutputStreamReadyEvent(getter_AddRefs(event), mCallback, mTarget); - mCallback = 0; - if (event) { - rv = event->OnOutputStreamReady(nsnull); - if (NS_FAILED(rv)) { - NS_NOTREACHED("leaking stream event"); - nsISupports *sup = event; - NS_ADDREF(sup); - } + if (!mCallback) + return; + // + // whoa!! looks like we never posted this event. take care to + // release mCallback on the correct thread. if mTarget lives on the + // calling thread, then we are ok. otherwise, we have to try to + // proxy the Release over the right thread. if that thread is dead, + // then there's nothing we can do... better to leak than crash. + // + PRBool val; + nsresult rv = mTarget->IsOnCurrentThread(&val); + if (NS_FAILED(rv) || !val) { + nsCOMPtr event; + NS_NewOutputStreamReadyEvent(getter_AddRefs(event), mCallback, + mTarget); + mCallback = 0; + if (event) { + rv = event->OnOutputStreamReady(nsnull); + if (NS_FAILED(rv)) { + NS_NOTREACHED("leaking stream event"); + nsISupports *sup = event; + NS_ADDREF(sup); } } } } public: - void Init(nsIOutputStreamCallback *callback, nsIEventTarget *target) - { - mCallback = callback; - mTarget = target; - - PL_InitEvent(this, nsnull, EventHandler, EventCleanup); - } - NS_IMETHOD OnOutputStreamReady(nsIAsyncOutputStream *stream) { mStream = stream; - // this will be released when the event is handled - NS_ADDREF_THIS(); - - PL_InitEvent(this, nsnull, EventHandler, EventCleanup); - - if (NS_FAILED(mTarget->PostEvent(this))) { + nsresult rv = + mTarget->Dispatch(this, NS_DISPATCH_NORMAL); + if (NS_FAILED(rv)) { NS_WARNING("PostEvent failed"); - NS_RELEASE_THIS(); return NS_ERROR_FAILURE; } return NS_OK; } + NS_IMETHOD Run() + { + if (mCallback) { + if (mStream) + mCallback->OnOutputStreamReady(mStream); + mCallback = nsnull; + } + return NS_OK; + } + private: nsCOMPtr mStream; nsCOMPtr mCallback; nsCOMPtr mTarget; - - PR_STATIC_CALLBACK(void *) EventHandler(PLEvent *plevent) - { - nsOutputStreamReadyEvent *ev = (nsOutputStreamReadyEvent *) plevent; - if (ev->mCallback) - ev->mCallback->OnOutputStreamReady(ev->mStream); - ev->mCallback = 0; - return NULL; - } - - PR_STATIC_CALLBACK(void) EventCleanup(PLEvent *ev) - { - nsOutputStreamReadyEvent *event = (nsOutputStreamReadyEvent *) ev; - NS_RELEASE(event); - } }; -NS_IMPL_THREADSAFE_ISUPPORTS1(nsOutputStreamReadyEvent, +NS_IMPL_THREADSAFE_ISUPPORTS2(nsOutputStreamReadyEvent, nsIRunnable, nsIOutputStreamCallback) //----------------------------------------------------------------------------- @@ -235,6 +209,8 @@ NS_NewInputStreamReadyEvent(nsIInputStreamCallback **event, nsIInputStreamCallback *callback, nsIEventTarget *target) { + NS_ASSERTION(callback, "null callback"); + NS_ASSERTION(target, "null target"); nsInputStreamReadyEvent *ev = new nsInputStreamReadyEvent(callback, target); if (!ev) return NS_ERROR_OUT_OF_MEMORY; @@ -247,6 +223,8 @@ NS_NewOutputStreamReadyEvent(nsIOutputStreamCallback **event, nsIOutputStreamCallback *callback, nsIEventTarget *target) { + NS_ASSERTION(callback, "null callback"); + NS_ASSERTION(target, "null target"); nsOutputStreamReadyEvent *ev = new nsOutputStreamReadyEvent(callback, target); if (!ev) return NS_ERROR_OUT_OF_MEMORY; @@ -260,6 +238,7 @@ NS_NewOutputStreamReadyEvent(nsIOutputStreamCallback **event, // abstract stream copier... class nsAStreamCopier : public nsIInputStreamCallback , public nsIOutputStreamCallback + , public nsIRunnable { public: NS_DECL_ISUPPORTS @@ -386,26 +365,20 @@ public: return NS_OK; } - PR_STATIC_CALLBACK(void*) HandleContinuationEvent(PLEvent *event) + // continuation event handler + NS_IMETHOD Run() { - nsAStreamCopier *self = (nsAStreamCopier *) event->owner; - self->Process(); + Process(); // clear "in process" flag and post any pending continuation event - nsAutoLock lock(self->mLock); - self->mEventInProcess = PR_FALSE; - if (self->mEventIsPending) { - self->mEventIsPending = PR_FALSE; - self->PostContinuationEvent_Locked(); + nsAutoLock lock(mLock); + mEventInProcess = PR_FALSE; + if (mEventIsPending) { + mEventIsPending = PR_FALSE; + PostContinuationEvent_Locked(); } - return nsnull; - } - PR_STATIC_CALLBACK(void) DestroyContinuationEvent(PLEvent *event) - { - nsAStreamCopier *self = (nsAStreamCopier *) event->owner; - NS_RELEASE(self); - delete event; + return NS_OK; } nsresult PostContinuationEvent() @@ -427,23 +400,11 @@ public: if (mEventInProcess) mEventIsPending = PR_TRUE; else { - PLEvent *event = new PLEvent; - if (!event) - rv = NS_ERROR_OUT_OF_MEMORY; - else { - NS_ADDREF_THIS(); - PL_InitEvent(event, this, - HandleContinuationEvent, - DestroyContinuationEvent); - - rv = mTarget->PostEvent(event); - if (NS_SUCCEEDED(rv)) - mEventInProcess = PR_TRUE; - else { - NS_ERROR("unable to post continuation event"); - PL_DestroyEvent(event); - } - } + rv = mTarget->Dispatch(this, NS_DISPATCH_NORMAL); + if (NS_SUCCEEDED(rv)) + mEventInProcess = PR_TRUE; + else + NS_WARNING("unable to post continuation event"); } return rv; } @@ -462,9 +423,10 @@ protected: PRPackedBool mEventIsPending; }; -NS_IMPL_THREADSAFE_ISUPPORTS2(nsAStreamCopier, +NS_IMPL_THREADSAFE_ISUPPORTS3(nsAStreamCopier, nsIInputStreamCallback, - nsIOutputStreamCallback) + nsIOutputStreamCallback, + nsIRunnable) class nsStreamCopierIB : public nsAStreamCopier { diff --git a/mozilla/xpcom/io/nsStreamUtils.h b/mozilla/xpcom/io/nsStreamUtils.h index 9040403ace8..e449642c494 100644 --- a/mozilla/xpcom/io/nsStreamUtils.h +++ b/mozilla/xpcom/io/nsStreamUtils.h @@ -54,12 +54,12 @@ class nsIEventTarget; * the proxy object is destroyed on. * * This function is designed to be used to implement AsyncWait when the - * aEventTarget parameter is non-null. + * aTarget parameter is non-null. */ extern NS_COM nsresult NS_NewInputStreamReadyEvent(nsIInputStreamCallback **aEvent, nsIInputStreamCallback *aNotify, - nsIEventTarget *aEventTarget); + nsIEventTarget *aTarget); /** * A "one-shot" proxy of the OnOutputStreamReady callback. The resulting @@ -69,12 +69,12 @@ NS_NewInputStreamReadyEvent(nsIInputStreamCallback **aEvent, * the proxy object is destroyed on. * * This function is designed to be used to implement AsyncWait when the - * aEventTarget parameter is non-null. + * aTarget parameter is non-null. */ extern NS_COM nsresult NS_NewOutputStreamReadyEvent(nsIOutputStreamCallback **aEvent, nsIOutputStreamCallback *aNotify, - nsIEventTarget *aEventTarget); + nsIEventTarget *aTarget); /* ------------------------------------------------------------------------- */ @@ -102,7 +102,7 @@ typedef void (* nsAsyncCopyCallbackFun)(void *closure, nsresult status); extern NS_COM nsresult NS_AsyncCopy(nsIInputStream *aSource, nsIOutputStream *aSink, - nsIEventTarget *aEventTarget, + nsIEventTarget *aTarget, nsAsyncCopyMode aMode = NS_ASYNCCOPY_VIA_READSEGMENTS, PRUint32 aChunkSize = 4096, nsAsyncCopyCallbackFun aCallbackFun = nsnull, diff --git a/mozilla/xpcom/proxy/public/Makefile.in b/mozilla/xpcom/proxy/public/Makefile.in index d6950b9a751..77c62a8f7ad 100644 --- a/mozilla/xpcom/proxy/public/Makefile.in +++ b/mozilla/xpcom/proxy/public/Makefile.in @@ -50,14 +50,13 @@ XPIDL_MODULE = proxyObjInst endif EXPORTS = \ - nsProxyEvent.h \ nsProxyRelease.h \ nsProxiedService.h \ $(NULL) -XPIDLSRCS = nsIProxyCreateInstance.idl \ - nsIProxyObjectManager.idl \ - $(NULL) +XPIDLSRCS = \ + nsIProxyObjectManager.idl \ + $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/mozilla/xpcom/proxy/public/nsIProxyCreateInstance.idl b/mozilla/xpcom/proxy/public/nsIProxyCreateInstance.idl index cd576f7b9a7..e69de29bb2d 100644 --- a/mozilla/xpcom/proxy/public/nsIProxyCreateInstance.idl +++ b/mozilla/xpcom/proxy/public/nsIProxyCreateInstance.idl @@ -1,53 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsISupports.idl" - -[scriptable, uuid(948c2080-0398-11d3-915e-0000863011c4)] -interface nsIProxyCreateInstance : nsISupports -{ - [noscript] void CreateInstanceByIID(in nsIIDRef cid, - in nsISupports aOuter, - in nsIIDRef iid, - out voidPtr result); - - [noscript] void CreateInstanceByContractID(in string aContractID, - in nsISupports aOuter, - in nsIIDRef iid, - out voidPtr result); -}; - diff --git a/mozilla/xpcom/proxy/public/nsIProxyObjectManager.idl b/mozilla/xpcom/proxy/public/nsIProxyObjectManager.idl index b8de77e198d..16f2e5e3b9c 100644 --- a/mozilla/xpcom/proxy/public/nsIProxyObjectManager.idl +++ b/mozilla/xpcom/proxy/public/nsIProxyObjectManager.idl @@ -22,6 +22,7 @@ * Contributor(s): * Doug Turner (Original Author) * Dan Mosedale + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -36,75 +37,108 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ + #include "nsISupports.idl" -interface nsIEventQueue; + +interface nsIEventTarget; /** + * An interface for the proxy object manager. + * * See http://www.mozilla.org/projects/xpcom/Proxies.html */ - -[scriptable, uuid(eea90d43-b059-11d2-915e-c12b696c9333)] +[scriptable, uuid(ee8ce1e3-0319-4bd9-8f70-7258b21c7733)] interface nsIProxyObjectManager : nsISupports { /** - * Constants for proxyType + * Construct a proxy object that invokes methods on the real object + * synchronously (i.e., the calling thread is blocked until the real method + * call returns). This flag causes methods invoked on the proxy object to + * emmulate a real method call. + * + * For C++ callers, NS_PROXY_SYNC is a synonym for this flag. */ - /** - * Synchronous: Block until result available, like function call. - */ - const long INVOKE_SYNC = 0x0001; - /** - * Asynchronous: Return without waiting for result. - * (Warning: do not pass &pointers into stack when using this flag.) - */ - const long INVOKE_ASYNC = 0x0002; + const long INVOKE_SYNC = 0x0001; /** - * Always create proxy even if for same thread as current thread. + * Construct a proxy object that invokes methods on the real object + * asynchronously (i.e., the calling thread does not wait for the real + * method call to occur). + * + * WARNING: do not pass pointers into the stack when using this flag. + * + * For C++ callers, NS_PROXY_ASYNC is a synonym for this flag. + */ + const long INVOKE_ASYNC = 0x0002; + + /** + * Always create the proxy object even if for same thread as current thread. + * + * For C++ callers, NS_PROXY_ALWAYS is a synonym for this flag. */ const long FORCE_PROXY_CREATION = 0x0004; - - void getProxyForObject(in nsIEventQueue destQueue, + /** + * Create a proxy for the given object. The proxy implements the specified + * interface, but when its methods are invoked, it causes the corresponding + * method on the actual object to be called via the designated event + * target. Typically, the event target identifies a thread where the + * method call should occur. + * + * @param target + * If target is null, then the current thread is used as the target. + * Otherwise, target identifies the nsIEventTarget from which proxy + * method calls should be executed. + * @param iid + * Identifies the interface being proxied. The given object must QI to + * this type. + * @param object + * The object being proxied. + * @param proxyType + * Specifies the type of proxy to construct. Either INVOKE_SYNC or + * INVOKE_ASYNC must be specified. FORCE_PROXY_CREATION may be bit-wise + * OR'd with either of those flags. + * @param result + * This param holds the resulting proxy object upon successful return. + */ + void getProxyForObject(in nsIEventTarget target, in nsIIDRef iid, in nsISupports object, in PRInt32 proxyType, [iid_is(iid),retval] out nsQIResult result); - - void getProxy(in nsIEventQueue destQueue, - in nsIIDRef cid, - in nsISupports aOuter, - in nsIIDRef iid, - in PRInt32 proxyType, - [iid_is(iid),retval] out nsQIResult result); - }; %{C++ -#include "nsProxyEvent.h" - -#define NS_XPCOMPROXY_CONTRACTID "@mozilla.org/xpcomproxy;1" -#define NS_XPCOMPROXY_CLASSNAME "XPCom Proxy" - -#define NS_PROXYEVENT_MANAGER_CID \ -{ 0xeea90d41, \ - 0xb059, \ - 0x11d2, \ - {0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33}\ -} +/** + * convenience macros + */ +#define NS_PROXY_SYNC nsIProxyObjectManager::INVOKE_SYNC +#define NS_PROXY_ASYNC nsIProxyObjectManager::INVOKE_ASYNC +#define NS_PROXY_ALWAYS nsIProxyObjectManager::FORCE_PROXY_CREATION /** - * Helper function for code that already has a link-time dependency on - * libxpcom and needs to get proxies in a bunch of different places. - * This way, the caller isn't forced to get the proxy object manager - * themselves every single time, thus making the calling code more - * readable. + * Pass this value as the target to {NS_}GetProxyForObject to specify the current + * thread as the target for the proxy object. + */ +#define NS_PROXY_TO_CURRENT_THREAD ((nsIEventTarget *) 0) + +/** + * Pass this value as the target to NS_GetProxyForObject to specify the main + * thread as the target for the proxy object. + */ +#define NS_PROXY_TO_MAIN_THREAD ((nsIEventTarget *) 1) + +#ifdef MOZILLA_INTERNAL_API +/** + * Helper function for code that already has a link-time dependency on the + * internal API (MOZILLA_INTERNAL_API) and needs to get proxies in a bunch of + * different places. This way, the caller isn't forced to get the proxy object + * manager themselves every single time, thus making the calling code more + * readable. The parameters are the same as for GetProxyForObject. */ extern NS_COM nsresult -NS_GetProxyForObject(nsIEventQueue *destQueue, - REFNSIID aIID, - nsISupports* aObj, - PRInt32 proxyType, - void** aProxyObject); +NS_GetProxyForObject(nsIEventTarget *target, REFNSIID iid, nsISupports* object, + PRInt32 proxyType, void** result); +#endif %} diff --git a/mozilla/xpcom/proxy/public/nsProxiedService.h b/mozilla/xpcom/proxy/public/nsProxiedService.h index 7ab4adb8808..d3a3ca1ef46 100644 --- a/mozilla/xpcom/proxy/public/nsProxiedService.h +++ b/mozilla/xpcom/proxy/public/nsProxiedService.h @@ -36,8 +36,8 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef nsProxiedService_h_ -#define nsProxiedService_h_ +#ifndef nsProxiedService_h__ +#define nsProxiedService_h__ #include "nsIServiceManager.h" #include "nsIProxyObjectManager.h" @@ -57,10 +57,10 @@ // if(NS_FAILED(rv)) // return; // nsIMyService pIProxiedObject = NULL; -// rv = pIProxyObjectManager->GetProxyForObject(pIProxyQueue, -// NS_GET_IID(nsIMyService), -// pIMyService, PROXY_SYNC, -// (void**)&pIProxiedObject); +// rv = pIProxyObjectManager->GetProxyForObject(pIDispatchTarget, +// NS_GET_IID(nsIMyService), +// pIMyService, NS_PROXY_SYNC, +// (void**)&pIProxiedObject); // pIProxiedObject->DoIt(...); // Executed on same thread as pIProxyQueue // ... // pIProxiedObject->Release(); // Must be done as not managed for you. @@ -69,7 +69,7 @@ // { // nsresult rv; // NS_WITH_PROXIED_SERVICE(nsIMyService, pIMyService, kMyServiceCID, -// pIProxyQueue, &rv); +// pIDispatchTarget, &rv); // if(NS_FAILED(rv)) // return; // pIMyService->DoIt(...); // Executed on the same thread as pIProxyQueue @@ -96,19 +96,19 @@ class nsProxiedService { public: nsProxiedService(const nsCID &aClass, const nsIID &aIID, - nsIEventQueue* aEventQ, PRBool always, nsresult* rv) + nsIEventTarget* aTarget, PRBool always, nsresult* rv) { nsCOMPtr svc = do_GetService(aClass, rv); if (NS_SUCCEEDED(*rv)) - InitProxy(svc, aIID, aEventQ, always, rv); + InitProxy(svc, aIID, aTarget, always, rv); } nsProxiedService(const char* aContractID, const nsIID &aIID, - nsIEventQueue* aEventQ, PRBool always, nsresult* rv) + nsIEventTarget* aTarget, PRBool always, nsresult* rv) { nsCOMPtr svc = do_GetService(aContractID, rv); if (NS_SUCCEEDED(*rv)) - InitProxy(svc, aIID, aEventQ, always, rv); + InitProxy(svc, aIID, aTarget, always, rv); } operator nsISupports*() const @@ -119,13 +119,13 @@ public: private: void InitProxy(nsISupports *aObj, const nsIID &aIID, - nsIEventQueue* aEventQ, PRBool always, nsresult*rv) + nsIEventTarget* aTarget, PRBool always, nsresult*rv) { - PRInt32 proxyType = PROXY_SYNC; + PRInt32 proxyType = NS_PROXY_SYNC; if (always) - proxyType |= PROXY_ALWAYS; + proxyType |= NS_PROXY_ALWAYS; - *rv = NS_GetProxyForObject(aEventQ, + *rv = NS_GetProxyForObject(aTarget, aIID, aObj, proxyType, @@ -135,4 +135,4 @@ private: nsCOMPtr mProxiedService; }; -#endif // nsProxiedService_h_ +#endif // nsProxiedService_h__ diff --git a/mozilla/xpcom/proxy/public/nsProxyEvent.h b/mozilla/xpcom/proxy/public/nsProxyEvent.h index 1cff90ba832..e69de29bb2d 100644 --- a/mozilla/xpcom/proxy/public/nsProxyEvent.h +++ b/mozilla/xpcom/proxy/public/nsProxyEvent.h @@ -1,185 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef __nsProxyEvent_h_ -#define __nsProxyEvent_h_ - -#include "nsCOMPtr.h" -#include "nsAutoPtr.h" -#include "nscore.h" -#include "nsISupports.h" -#include "nsIFactory.h" - -#include "nsIEventQueueService.h" -#include "nsIEventQueue.h" -#include "plevent.h" -#include "prtypes.h" -#include "xptcall.h" -#include "xptinfo.h" - -class nsProxyObjectCallInfo; - -#define PROXY_SYNC 0x0001 // acts just like a function call. -#define PROXY_ASYNC 0x0002 // fire and forget. This will return immediately and you will lose all return information. -#define PROXY_ALWAYS 0x0004 // ignore check to see if the eventQ is on the same thread as the caller, and alway return a proxied object. - -//#define AUTOPROXIFICATION - -// WARNING about PROXY_ASYNC: -// -// If the calling thread goes away, any function which accesses the calling stack -// will blow up. -// -// example: -// -// myFoo->bar(&x) -// -// ... thread goes away ... -// -// bar(PRInt32 *x) -// { -// *x = 0; <----- You will blow up here. -// -// -// So what gets saved? -// -// You can safely pass base types by value. You can also pass interface pointers. -// I will make sure that the interface pointers are addrefed while they are being -// proxied. You can also pass string and wstring. These I will copy and free. -// -// I do **NOT** copy arrays or strings with size. If you are using these either -// change your interface, or contact me about this feature request. - - - - -class nsProxyObject -{ -public: - nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject, - nsIEventQueueService* eventQService); - nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, - nsISupports *aDelegate, const nsIID &aIID, nsIEventQueueService* eventQService); - - void AddRef(); - void Release(); - - ~nsProxyObject(); - - nsresult Post( PRUint32 methodIndex, - nsXPTMethodInfo * info, - nsXPTCMiniVariant * params, - nsIInterfaceInfo * interfaceInfo); - - nsresult PostAndWait(nsProxyObjectCallInfo *proxyInfo); - nsISupports* GetRealObject() const { return mRealObject; } - nsIEventQueue* GetQueue() const { return mDestQueue; } - PRInt32 GetProxyType() const { return mProxyType; } - - friend class nsProxyEventObject; -private: - - nsAutoRefCnt mRefCnt; - - PRInt32 mProxyType; - - nsCOMPtr mDestQueue; /* destination queue */ - - nsCOMPtr mRealObject; /* the non-proxy object that this event is referring to. - This is a strong ref. */ - nsCOMPtr mEventQService; - - nsresult convertMiniVariantToVariant(nsXPTMethodInfo * methodInfo, - nsXPTCMiniVariant * params, - nsXPTCVariant **fullParam, - uint8 *paramCount); - -}; - - -class nsProxyObjectCallInfo -{ -public: - - nsProxyObjectCallInfo(nsProxyObject* owner, - nsXPTMethodInfo *methodInfo, - PRUint32 methodIndex, - nsXPTCVariant* parameterList, - PRUint32 parameterCount, - PLEvent *event); - - ~nsProxyObjectCallInfo(); - - PRUint32 GetMethodIndex() const { return mMethodIndex; } - nsXPTCVariant* GetParameterList() const { return mParameterList; } - PRUint32 GetParameterCount() const { return mParameterCount; } - PLEvent* GetPLEvent() const { return mEvent; } - nsresult GetResult() const { return mResult; } - nsProxyObject* GetProxyObject() const { return mOwner; } - - PRBool GetCompleted(); - void SetCompleted(); - void PostCompleted(); - - void SetResult(nsresult rv) {mResult = rv; } - - nsIEventQueue* GetCallersQueue(); - void SetCallersQueue(nsIEventQueue* queue); - -private: - - nsresult mResult; /* this is the return result of the called function */ - nsXPTMethodInfo *mMethodInfo; - PRUint32 mMethodIndex; /* which method to be called? */ - nsXPTCVariant *mParameterList; /* marshalled in parameter buffer */ - PRUint32 mParameterCount; /* number of params */ - PLEvent *mEvent; /* the current plevent */ - PRInt32 mCompleted; /* is true when the method has been called. */ - - nsCOMPtr mCallersEventQ; /* this is the eventQ that we must post a message back to - when we are done invoking the method (only PROXY_SYNC). - */ - - nsRefPtr mOwner; /* this is the strong referenced nsProxyObject */ - - void RefCountInInterfacePointers(PRBool addRef); - void CopyStrings(PRBool copy); - -}; - - -#endif diff --git a/mozilla/xpcom/proxy/public/nsProxyRelease.h b/mozilla/xpcom/proxy/public/nsProxyRelease.h index 9792736b380..5253f7e30fb 100644 --- a/mozilla/xpcom/proxy/public/nsProxyRelease.h +++ b/mozilla/xpcom/proxy/public/nsProxyRelease.h @@ -38,7 +38,7 @@ #ifndef nsProxyRelease_h_ #define nsProxyRelease_h__ -#include "nsIEventQueueService.h" +#include "nsIEventTarget.h" #include "pratom.h" #include "prmem.h" @@ -58,55 +58,4 @@ NS_COM nsresult NS_ProxyRelease (nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy=PR_FALSE); - -#define NS_IMPL_PROXY_RELEASE(_class) \ -NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \ -{ \ - NS_PRECONDITION(0 != mRefCnt, "dup release"); \ - nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); \ - NS_LOG_RELEASE(this, count, #_class); \ - \ - if (count == 0) \ - { \ - mRefCnt = 1; /* stabilize */ \ - PRBool callDirectly = PR_TRUE; \ - static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); \ - nsCOMPtr eventQService \ - = do_GetService(kEventQueueServiceCID); \ - NS_ASSERTION(eventQService, "event queue service is unavailable"); \ - \ - nsCOMPtr eventQ; \ - if (eventQService) { \ - eventQService->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eventQ)); \ - if (eventQ) \ - eventQ->IsOnCurrentThread(&callDirectly); \ - } \ - \ - if (callDirectly) \ - { \ - NS_RELEASE(this); \ - return 0; \ - } \ - PLEvent *event = new PLEvent; \ - if (event == nsnull) \ - { \ - NS_ASSERTION(0, "Could not create a plevent. Deleting on wrong thread!"); \ - NS_DELETEXPCOM(this); \ - return 0; \ - } \ - \ - PL_InitEvent(event, \ - NS_STATIC_CAST(nsISupports*, this), \ - ReleaseDestructorEventHandler, \ - ReleaseDestructorDestroyHandler); \ - \ - eventQ->PostEvent(event); \ - return 0; \ - } \ - return count; \ -} \ - - - - #endif diff --git a/mozilla/xpcom/proxy/src/Makefile.in b/mozilla/xpcom/proxy/src/Makefile.in index ba36ed6bb0a..93ab33ac2a7 100644 --- a/mozilla/xpcom/proxy/src/Makefile.in +++ b/mozilla/xpcom/proxy/src/Makefile.in @@ -58,6 +58,7 @@ CPPSRCS = \ $(NULL) DEFINES += -D_IMPL_NS_COM -DEXPORT_XPTC_API +LOCAL_INCLUDES += -I$(top_srcdir)/xpcom/threads/ # No shared lib; Force creation of static lib FORCE_STATIC_LIB = 1 diff --git a/mozilla/xpcom/proxy/src/nsIProxyCreateInstance.h b/mozilla/xpcom/proxy/src/nsIProxyCreateInstance.h index beadae7a42d..e69de29bb2d 100644 --- a/mozilla/xpcom/proxy/src/nsIProxyCreateInstance.h +++ b/mozilla/xpcom/proxy/src/nsIProxyCreateInstance.h @@ -1,37 +0,0 @@ -/* - * DO NOT EDIT. THIS FILE IS GENERATED FROM nsIProxyCreateInstance.idl - */ - -#ifndef __gen_nsIProxyCreateInstance_h__ -#define __gen_nsIProxyCreateInstance_h__ - -#include "nsISupports.h" /* interface nsISupports */ -#include "nsrootidl.h" /* interface nsrootidl */ - -#ifdef XPIDL_JS_STUBS -#include "jsapi.h" -#endif - -/* starting interface: nsIProxyCreateInstance */ - -/* {948c2080-0398-11d3-915e-0000863011c4} */ -#define NS_IPROXYCREATEINSTANCE_IID_STR "948c2080-0398-11d3-915e-0000863011c4" -#define NS_IPROXYCREATEINSTANCE_IID \ - {0x948c2080, 0x0398, 0x11d3, \ - { 0x91, 0x5e, 0x00, 0x00, 0x86, 0x30, 0x11, 0xc4 }} - -class nsIProxyCreateInstance : public nsISupports { - public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_IPROXYCREATEINSTANCE_IID) - - /* void CreateInstanceByIID (in nsIIDRef cid, in nsISupports aOuter, in nsIIDRef iid, out voidStar result); */ - NS_IMETHOD CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result) = 0; - - /* void CreateInstanceByContractID (in string aContractID, in nsISupports aOuter, in nsIIDRef iid, out voidStar result); */ - NS_IMETHOD CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result) = 0; -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsIProxyCreateInstance, - NS_IPROXYCREATEINSTANCE_IID) - -#endif /* __gen_nsIProxyCreateInstance_h__ */ diff --git a/mozilla/xpcom/proxy/src/nsProxyEvent.cpp b/mozilla/xpcom/proxy/src/nsProxyEvent.cpp index cf93367abdb..ae519b7fe6c 100644 --- a/mozilla/xpcom/proxy/src/nsProxyEvent.cpp +++ b/mozilla/xpcom/proxy/src/nsProxyEvent.cpp @@ -1,4 +1,6 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 sts=4 ci et: */ +/* * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 @@ -57,12 +59,19 @@ #include "prmem.h" #include "xptcall.h" +#include "nsXPCOMCID.h" +#include "nsServiceManagerUtils.h" #include "nsIComponentManager.h" +#include "nsIThreadInternal.h" +#include "nsThreadUtils.h" +#include "nsEventQueue.h" #include "nsMemory.h" -#include "nsIEventQueueService.h" -#include "nsIThread.h" -#include "nsIAtom.h" //hack! Need a way to define a component as threadsafe (ie. sta). +#include "prlog.h" +#ifdef PR_LOGGING +static PRLogModuleInfo *sLog = PR_NewLogModule("xpcomproxy"); +#endif +#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args) /** * Map the nsAUTF8String, nsUTF8String classes to the nsACString and @@ -72,19 +81,156 @@ #define nsAUTF8String nsACString #define nsUTF8String nsCString -static void* PR_CALLBACK EventHandler(PLEvent *self); -static void PR_CALLBACK DestroyHandler(PLEvent *self); -static void* PR_CALLBACK CompletedEventHandler(PLEvent *self); -static void PR_CALLBACK CompletedDestroyHandler(PLEvent *self) ; -static void* PR_CALLBACK ProxyDestructorEventHandler(PLEvent *self); -static void PR_CALLBACK ProxyDestructorDestroyHandler(PLEvent *self) ; +//----------------------------------------------------------------------------- -nsProxyObjectCallInfo::nsProxyObjectCallInfo( nsProxyObject* owner, - nsXPTMethodInfo *methodInfo, - PRUint32 methodIndex, - nsXPTCVariant* parameterList, - PRUint32 parameterCount, - PLEvent *event) +#define NS_PROXYEVENT_IID \ +{ /* 9a24dc5e-2b42-4a5a-aeca-37b8c8fd8ccd */ \ + 0x9a24dc5e, \ + 0x2b42, \ + 0x4a5a, \ + {0xae, 0xca, 0x37, 0xb8, 0xc8, 0xfd, 0x8c, 0xcd} \ +} + +class nsProxyEvent : public nsIRunnable +{ +public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_IID) + NS_DECL_ISUPPORTS + + nsProxyEvent(nsProxyObjectCallInfo *info = nsnull) + : mInfo(info) + {} + + void SetInfo(nsProxyObjectCallInfo *info) + { + NS_ASSERTION(info, "null info"); + NS_ASSERTION(!mInfo, "unexpected change to mInfo"); + mInfo = info; + } + + PRBool IsSyncProxyEvent() + { + return mInfo->GetProxyObject()->GetProxyType() & NS_PROXY_SYNC; + } + +protected: + nsProxyObjectCallInfo *mInfo; +}; +NS_DEFINE_STATIC_IID_ACCESSOR(nsProxyEvent, NS_PROXYEVENT_IID) +NS_IMPL_THREADSAFE_ISUPPORTS2(nsProxyEvent, nsProxyEvent, nsIRunnable) + +//----------------------------------------------------------------------------- + +class nsProxyThreadFilter : public nsIThreadEventFilter +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSITHREADEVENTFILTER +}; + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsProxyThreadFilter, nsIThreadEventFilter) + +NS_IMETHODIMP_(PRBool) +nsProxyThreadFilter::AcceptEvent(nsIRunnable *event) +{ + LOG(("PROXY(%p): filter event [%p]\n", this, event)); + + // If we encounter one of our proxy events that is for a synchronous method + // call, then we want to put it in our event queue for processing. Else, + // we want to allow the event to be dispatched to the thread's event queue + // for processing later once we complete the current sync method call. + + nsCOMPtr pe = do_QueryInterface(event); + return pe && pe->IsSyncProxyEvent(); +} + +//----------------------------------------------------------------------------- + +class nsProxyCallEvent : public nsProxyEvent +{ +public: + nsProxyCallEvent() + : nsProxyEvent() + {} + + NS_IMETHOD Run() + { + NS_ASSERTION(mInfo, "no info"); + Invoke(); + if (IsSyncProxyEvent()) { + mInfo->PostCompleted(); + } else { + delete mInfo; + mInfo = nsnull; + } + return NS_OK; + } + + void Invoke() + { + LOG(("PROXY(%p): Invoke\n", this)); + + nsProxyObject *proxyObject = mInfo->GetProxyObject(); + if (proxyObject) + { + // invoke the magic of xptc... + nsresult rv = XPTC_InvokeByIndex(proxyObject->GetRealObject(), + mInfo->GetMethodIndex(), + mInfo->GetParameterCount(), + mInfo->GetParameterList()); + mInfo->SetResult(rv); + } + else + { + mInfo->SetResult(NS_ERROR_OUT_OF_MEMORY); + } + } +}; + +//----------------------------------------------------------------------------- + +class nsProxyCallCompletedEvent : public nsProxyEvent +{ +public: + nsProxyCallCompletedEvent(nsProxyObjectCallInfo *info) + : nsProxyEvent(info) + {} + + NS_IMETHOD Run() + { + NS_ASSERTION(mInfo, "no info"); + mInfo->SetCompleted(); + return NS_OK; + } +}; + +//----------------------------------------------------------------------------- + +class nsProxyDestructorEvent : public nsRunnable +{ +public: + nsProxyDestructorEvent(nsProxyObject *doomed) + : mDoomed(doomed) + {} + + NS_IMETHOD Run() + { + delete mDoomed; + return NS_OK; + } + +private: + nsProxyObject *mDoomed; +}; + +//----------------------------------------------------------------------------- + +nsProxyObjectCallInfo::nsProxyObjectCallInfo(nsProxyObject* owner, + nsXPTMethodInfo *methodInfo, + PRUint32 methodIndex, + nsXPTCVariant* parameterList, + PRUint32 parameterCount, + nsIRunnable *event) { NS_ASSERTION(owner, "No nsProxyObject!"); NS_ASSERTION(methodInfo, "No nsXPTMethodInfo!"); @@ -94,14 +240,14 @@ nsProxyObjectCallInfo::nsProxyObjectCallInfo( nsProxyObject* owner, mMethodIndex = methodIndex; mParameterList = parameterList; mParameterCount = parameterCount; - mEvent = event; + mEvent = event; // XXX strong or weak ref? mMethodInfo = methodInfo; - mCallersEventQ = nsnull; + mCallersTarget = nsnull; mOwner = owner; RefCountInInterfacePointers(PR_TRUE); - if (mOwner->GetProxyType() & PROXY_ASYNC) + if (mOwner->GetProxyType() & NS_PROXY_ASYNC) CopyStrings(PR_TRUE); } @@ -109,15 +255,13 @@ nsProxyObjectCallInfo::nsProxyObjectCallInfo( nsProxyObject* owner, nsProxyObjectCallInfo::~nsProxyObjectCallInfo() { RefCountInInterfacePointers(PR_FALSE); - if (mOwner->GetProxyType() & PROXY_ASYNC) + if (mOwner->GetProxyType() & NS_PROXY_ASYNC) CopyStrings(PR_FALSE); mOwner = nsnull; - PR_FREEIF(mEvent); - if (mParameterList) - free( (void*) mParameterList); + free((void*) mParameterList); } void @@ -137,7 +281,7 @@ nsProxyObjectCallInfo::RefCountInInterfacePointers(PRBool addRef) if (anInterface) { - if(addRef) + if (addRef) anInterface->AddRef(); else anInterface->Release(); @@ -155,7 +299,7 @@ nsProxyObjectCallInfo::CopyStrings(PRBool copy) { const nsXPTParamInfo paramInfo = mMethodInfo->GetParam(i); - if(paramInfo.IsIn()) + if (paramInfo.IsIn()) { const nsXPTType& type = paramInfo.GetType(); uint8 type_tag = type.TagPart(); @@ -230,67 +374,45 @@ nsProxyObjectCallInfo::GetCompleted() void nsProxyObjectCallInfo::SetCompleted() { + LOG(("PROXY(%p): SetCompleted\n", this)); PR_AtomicSet(&mCompleted, 1); } void nsProxyObjectCallInfo::PostCompleted() { - if (mCallersEventQ) - { - PLEvent *event = PR_NEW(PLEvent); - - PL_InitEvent(event, - this, - CompletedEventHandler, - CompletedDestroyHandler); - - mCallersEventQ->PostSynchronousEvent(event, nsnull); - PR_FREEIF(event); - } - else - { - // caller does not have an eventQ? This is an error! - SetCompleted(); + LOG(("PROXY(%p): PostCompleted\n", this)); + + if (mCallersTarget) { + nsCOMPtr event = + new nsProxyCallCompletedEvent(this); + if (event && + NS_SUCCEEDED(mCallersTarget->Dispatch(event, NS_DISPATCH_NORMAL))) + return; } + + // OOM? caller does not have a target? This is an error! + NS_WARNING("Failed to dispatch nsProxyCallCompletedEvent"); + SetCompleted(); } -nsIEventQueue* -nsProxyObjectCallInfo::GetCallersQueue() +nsIEventTarget* +nsProxyObjectCallInfo::GetCallersTarget() { - return mCallersEventQ; -} -void -nsProxyObjectCallInfo::SetCallersQueue(nsIEventQueue* queue) -{ - mCallersEventQ = queue; -} - - -nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject, - nsIEventQueueService* eventQService) -{ - mEventQService = eventQService; - - mRealObject = realObject; - mDestQueue = do_QueryInterface(destQueue); - mProxyType = proxyType; + return mCallersTarget; } - -nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, - nsISupports *aDelegate, const nsIID &aIID, nsIEventQueueService* eventQService) +void +nsProxyObjectCallInfo::SetCallersTarget(nsIEventTarget* target) { - mEventQService = eventQService; + mCallersTarget = target; +} - nsCOMPtr compMgr; - NS_GetComponentManager(getter_AddRefs(compMgr)); - compMgr->CreateInstance(aClass, - aDelegate, - aIID, - getter_AddRefs(mRealObject)); - - mDestQueue = do_QueryInterface(destQueue); +nsProxyObject::nsProxyObject(nsIEventTarget *target, PRInt32 proxyType, + nsISupports *realObject) +{ + mRealObject = realObject; + mTarget = target; mProxyType = proxyType; } @@ -300,10 +422,9 @@ nsProxyObject::~nsProxyObject() // do not remove assignments. mRealObject = 0; - mDestQueue = 0; + mTarget = 0; } - void nsProxyObject::AddRef() { @@ -314,92 +435,81 @@ nsProxyObject::AddRef() void nsProxyObject::Release(void) { - NS_PRECONDITION(0 != mRefCnt, "dup release"); + NS_PRECONDITION(0 != mRefCnt, "dup release"); - nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); - NS_LOG_RELEASE(this, count, "nsProxyObject"); + nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); + NS_LOG_RELEASE(this, count, "nsProxyObject"); - if (count == 0) - { - mRefCnt = 1; /* stabilize */ + if (count == 0) + { + mRefCnt = 1; /* stabilize */ - PRBool callDirectly; - mDestQueue->IsOnCurrentThread(&callDirectly); + PRBool callDirectly; + mTarget->IsOnCurrentThread(&callDirectly); - if (callDirectly) - { - delete this; - return; - } + if (callDirectly) + { + delete this; + return; + } - // need to do something special here so that - // the real object will always be deleted on - // the correct thread.. + // need to do something special here so that + // the real object will always be deleted on + // the correct thread.. - PLEvent *event = PR_NEW(PLEvent); - if (event == nsnull) - { - NS_ASSERTION(0, "Could not create a plevent. Leaking nsProxyObject!"); - return; // if this happens we are going to leak. - } - - PL_InitEvent(event, - this, - ProxyDestructorEventHandler, - ProxyDestructorDestroyHandler); + nsCOMPtr event = new nsProxyDestructorEvent(this); + if (event == nsnull) + { + NS_NOTREACHED("Leaking nsProxyObject!"); + return; // if this happens we are going to leak. + } - mDestQueue->PostEvent(event); - } -} + if (NS_FAILED(mTarget->Dispatch(event, NS_DISPATCH_NORMAL))) + NS_WARNING("Failed to dispatch nsProxyDestructorEvent"); + } +} nsresult nsProxyObject::PostAndWait(nsProxyObjectCallInfo *proxyInfo) { - if (proxyInfo == nsnull || mEventQService == nsnull) - return NS_ERROR_NULL_POINTER; - - PRBool eventLoopCreated = PR_FALSE; - nsresult rv; + LOG(("PROXY(%p): PostAndWait enter [%p]\n", this, proxyInfo)); - nsCOMPtr eventQ; - rv = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eventQ)); - if (NS_FAILED(rv)) - { - rv = mEventQService->CreateMonitoredThreadEventQueue(); - eventLoopCreated = PR_TRUE; - if (NS_FAILED(rv)) - return rv; - - rv = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eventQ)); - } + NS_ENSURE_ARG_POINTER(proxyInfo); - if (NS_FAILED(rv)) - return rv; - - proxyInfo->SetCallersQueue(eventQ); - - PLEvent* event = proxyInfo->GetPLEvent(); + nsIRunnable* event = proxyInfo->GetEvent(); if (!event) return NS_ERROR_NULL_POINTER; + + nsIThread *thread = NS_GetCurrentThread(); + nsCOMPtr threadInt = do_QueryInterface(thread); + NS_ENSURE_STATE(threadInt); + + // Install thread filter to limit event processing only to subclasses of + // nsProxyEvent. XXX Add support for sequencing? + nsRefPtr filter = new nsProxyThreadFilter(); + if (!filter) + return NS_ERROR_OUT_OF_MEMORY; + threadInt->PushEventQueue(filter); + + proxyInfo->SetCallersTarget(thread); - mDestQueue->PostEvent(event); - - while (! proxyInfo->GetCompleted()) - { - PLEvent *nextEvent; - rv = eventQ->WaitForEvent(&nextEvent); - if (NS_FAILED(rv)) break; - - eventQ->HandleEvent(nextEvent); - } - - if (eventLoopCreated) - { - mEventQService->DestroyThreadEventQueue(); - eventQ = 0; + // Dispatch can fail if the thread is shutting down + nsresult rv = mTarget->Dispatch(event, NS_DISPATCH_NORMAL); + if (NS_SUCCEEDED(rv)) { + while (!proxyInfo->GetCompleted()) { + if (!NS_ProcessNextEvent(thread)) { + rv = NS_ERROR_UNEXPECTED; + break; + } + } + } else { + NS_WARNING("Failed to dispatch nsProxyCallEvent"); } - + + threadInt->PopEventQueue(); + + LOG(("PROXY(%p): PostAndWait exit [%p %x]\n", this, proxyInfo, rv)); return rv; } @@ -424,7 +534,7 @@ nsProxyObject::convertMiniVariantToVariant(nsXPTMethodInfo *methodInfo, for (int i = 0; i < paramCount; i++) { const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i); - if ((mProxyType & PROXY_ASYNC) && paramInfo.IsDipper()) + if ((mProxyType & NS_PROXY_ASYNC) && paramInfo.IsDipper()) { NS_WARNING("Async proxying of out parameters is not supported"); return NS_ERROR_PROXY_INVALID_OUT_PARAMETER; @@ -444,7 +554,7 @@ nsProxyObject::Post( PRUint32 methodIndex, { nsresult rv = NS_OK; - if (! mDestQueue || ! mRealObject) + if (! mTarget || ! mRealObject) return NS_ERROR_OUT_OF_MEMORY; if (methodInfo->IsNotXPCOM()) @@ -461,10 +571,10 @@ nsProxyObject::Post( PRUint32 methodIndex, // see if we should call into the method directly. Either it is a QI function call // (methodIndex == 0), or it is a sync proxy and this code is running on the same thread - // as the destination event queue. + // as the destination dispatch target. if ( (methodIndex == 0) || - (mProxyType & PROXY_SYNC && - NS_SUCCEEDED(mDestQueue->IsOnCurrentThread(&callDirectly)) && + (mProxyType & NS_PROXY_SYNC && + NS_SUCCEEDED(mTarget->IsOnCurrentThread(&callDirectly)) && callDirectly)) { @@ -479,34 +589,30 @@ nsProxyObject::Post( PRUint32 methodIndex, return rv; } - PLEvent *event = PR_NEW(PLEvent); - - if (event == nsnull) { + nsRefPtr event = new nsProxyCallEvent(); + if (!event) { if (fullParam) free(fullParam); return NS_ERROR_OUT_OF_MEMORY; } - - nsProxyObjectCallInfo *proxyInfo = new nsProxyObjectCallInfo(this, - methodInfo, - methodIndex, - fullParam, // will be deleted by ~() - paramCount, - event); // will be deleted by ~() - if (proxyInfo == nsnull) { - PR_DELETE(event); + nsProxyObjectCallInfo *proxyInfo = + new nsProxyObjectCallInfo(this, + methodInfo, + methodIndex, + fullParam, // will be deleted by ~() + paramCount, + event); // will be deleted by ~() + + if (!proxyInfo) { if (fullParam) free(fullParam); return NS_ERROR_OUT_OF_MEMORY; } - PL_InitEvent(event, - proxyInfo, - EventHandler, - DestroyHandler); - - if (mProxyType & PROXY_SYNC) + event->SetInfo(proxyInfo); + + if (mProxyType & NS_PROXY_SYNC) { rv = PostAndWait(proxyInfo); @@ -516,78 +622,10 @@ nsProxyObject::Post( PRUint32 methodIndex, return rv; } - if (mProxyType & PROXY_ASYNC) + if (mProxyType & NS_PROXY_ASYNC) { - mDestQueue->PostEvent(event); + mTarget->Dispatch(event, NS_DISPATCH_NORMAL); return NS_OK; } return NS_ERROR_UNEXPECTED; } - - - -static void DestroyHandler(PLEvent *self) -{ - nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self); - nsProxyObject* proxyObject = owner->GetProxyObject(); - - if (proxyObject == nsnull) - return; - - if (proxyObject->GetProxyType() & PROXY_ASYNC) - { - delete owner; - } - else - { - owner->PostCompleted(); - } - -} - -static void* EventHandler(PLEvent *self) -{ - nsProxyObjectCallInfo *info = (nsProxyObjectCallInfo*)PL_GetEventOwner(self); - NS_ASSERTION(info, "No nsProxyObjectCallInfo!"); - - nsProxyObject *proxyObject = info->GetProxyObject(); - - if (proxyObject) - { - // invoke the magic of xptc... - nsresult rv = XPTC_InvokeByIndex( proxyObject->GetRealObject(), - info->GetMethodIndex(), - info->GetParameterCount(), - info->GetParameterList()); - info->SetResult(rv); - } - else - { - info->SetResult(NS_ERROR_OUT_OF_MEMORY); - } - return NULL; -} - -static void CompletedDestroyHandler(PLEvent *self) -{ -} - -static void* CompletedEventHandler(PLEvent *self) -{ - nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self); - owner->SetCompleted(); - return nsnull; -} - -static void* ProxyDestructorEventHandler(PLEvent *self) -{ - nsProxyObject* owner = (nsProxyObject*) PL_GetEventOwner(self); - NS_DELETEXPCOM(owner); - return nsnull; -} - -static void ProxyDestructorDestroyHandler(PLEvent *self) -{ - PR_DELETE(self); -} - diff --git a/mozilla/xpcom/proxy/src/nsProxyEvent.h b/mozilla/xpcom/proxy/src/nsProxyEvent.h new file mode 100644 index 00000000000..33754126ce5 --- /dev/null +++ b/mozilla/xpcom/proxy/src/nsProxyEvent.h @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsProxyEvent_h__ +#define nsProxyEvent_h__ + +#include "nsCOMPtr.h" +#include "nsAutoPtr.h" +#include "nscore.h" +#include "nsISupports.h" +#include "nsIFactory.h" +#include "nsIEventTarget.h" + +#include "prtypes.h" +#include "xptcall.h" +#include "xptinfo.h" + +class nsProxyObjectCallInfo; +class nsIRunnable; + +//#define AUTOPROXIFICATION + +// WARNING about NS_PROXY_ASYNC: +// +// If the calling thread goes away, any function which accesses the calling stack +// will blow up. +// +// example: +// +// myFoo->bar(&x) +// +// ... thread goes away ... +// +// bar(PRInt32 *x) +// { +// *x = 0; <----- You will blow up here. +// +// +// So what gets saved? +// +// You can safely pass base types by value. You can also pass interface pointers. +// I will make sure that the interface pointers are addrefed while they are being +// proxied. You can also pass string and wstring. These I will copy and free. +// +// I do **NOT** copy arrays or strings with size. If you are using these either +// change your interface, or contact me about this feature request. + + +class nsProxyObject +{ +public: + nsProxyObject(nsIEventTarget *destQueue, PRInt32 proxyType, + nsISupports *realObject); + + void AddRef(); + void Release(); + + ~nsProxyObject(); + + nsresult Post( PRUint32 methodIndex, + nsXPTMethodInfo * info, + nsXPTCMiniVariant * params, + nsIInterfaceInfo * interfaceInfo); + + nsresult PostAndWait(nsProxyObjectCallInfo *proxyInfo); + nsISupports* GetRealObject() const { return mRealObject; } + nsIEventTarget* GetTarget() const { return mTarget; } + PRInt32 GetProxyType() const { return mProxyType; } + + friend class nsProxyEventObject; +private: + + nsAutoRefCnt mRefCnt; + + PRInt32 mProxyType; + + nsCOMPtr mTarget; /* event target */ + + nsCOMPtr mRealObject; /* the non-proxy object that this event is referring to. + This is a strong ref. */ + + nsresult convertMiniVariantToVariant(nsXPTMethodInfo * methodInfo, + nsXPTCMiniVariant * params, + nsXPTCVariant **fullParam, + uint8 *paramCount); +}; + + +class nsProxyObjectCallInfo +{ +public: + + nsProxyObjectCallInfo(nsProxyObject* owner, + nsXPTMethodInfo *methodInfo, + PRUint32 methodIndex, + nsXPTCVariant* parameterList, + PRUint32 parameterCount, + nsIRunnable *event); + + ~nsProxyObjectCallInfo(); + + PRUint32 GetMethodIndex() const { return mMethodIndex; } + nsXPTCVariant* GetParameterList() const { return mParameterList; } + PRUint32 GetParameterCount() const { return mParameterCount; } + nsIRunnable* GetEvent() const { return mEvent; } + nsresult GetResult() const { return mResult; } + nsProxyObject* GetProxyObject() const { return mOwner; } + + PRBool GetCompleted(); + void SetCompleted(); + void PostCompleted(); + + void SetResult(nsresult rv) { mResult = rv; } + + nsIEventTarget* GetCallersTarget(); + void SetCallersTarget(nsIEventTarget* target); + +private: + + nsresult mResult; /* this is the return result of the called function */ + nsXPTMethodInfo *mMethodInfo; + PRUint32 mMethodIndex; /* which method to be called? */ + nsXPTCVariant *mParameterList; /* marshalled in parameter buffer */ + PRUint32 mParameterCount; /* number of params */ + nsIRunnable *mEvent; /* the current runnable */ + PRInt32 mCompleted; /* is true when the method has been called. */ + + nsCOMPtr mCallersTarget; /* this is the dispatch target that we must post a message back to + when we are done invoking the method (only NS_PROXY_SYNC). */ + + nsRefPtr mOwner; /* this is the strong referenced nsProxyObject */ + + void RefCountInInterfacePointers(PRBool addRef); + void CopyStrings(PRBool copy); +}; + +#endif // nsProxyEvent_h__ diff --git a/mozilla/xpcom/proxy/src/nsProxyEventClass.cpp b/mozilla/xpcom/proxy/src/nsProxyEventClass.cpp index 769a973fb7e..c690ead7c92 100644 --- a/mozilla/xpcom/proxy/src/nsProxyEventClass.cpp +++ b/mozilla/xpcom/proxy/src/nsProxyEventClass.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 sts=4 ci et: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -76,12 +77,13 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID) /* find in our hash table */ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance(); - if (manager == nsnull) return nsnull; + if (manager == nsnull) + return nsnull; - // don't need to lock the map, because this is only called - // by nsProxyEventClass::GetNewOrUsed which locks it for us. + // don't need to lock the map, because this is only called by + // nsProxyEventClass::GetNewOrUsed which locks it for us. - nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap(); + nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap(); if (iidToClassMap == nsnull) { @@ -94,7 +96,7 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID) #ifdef PROXYEVENTCLASS_DEBUG char* iidStr = aIID.ToString(); printf("GetNewOrUsedClass %s\n", iidStr); - nsCRT::free(iidStr); + PR_Free(iidStr); #endif clazz = (nsProxyEventClass*) iidToClassMap->Get(&key); @@ -104,7 +106,7 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID) #ifdef PROXYEVENTCLASS_DEBUG char* iidStr = aIID.ToString(); printf("GetNewOrUsedClass %s hit\n", iidStr); - nsCRT::free(iidStr); + PR_Free(iidStr); #endif } else @@ -142,7 +144,7 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID) if (isISupportsDescendent) { clazz = new nsProxyEventClass(aIID, info); - if(!clazz->mDescriptors) + if (!clazz->mDescriptors) NS_RELEASE(clazz); // sets clazz to NULL } } @@ -153,12 +155,12 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID) nsProxyEventClass::nsProxyEventClass() { - NS_WARNING("This constructor should never be called"); + NS_NOTREACHED("This constructor should never be called"); } nsProxyEventClass::nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo) -: mIID(aIID), - mDescriptors(NULL) + : mIID(aIID), + mDescriptors(NULL) { NS_ADDREF_THIS(); @@ -168,7 +170,8 @@ nsProxyEventClass::nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo) nsIDKey key(aIID); nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance(); - if (manager == nsnull) return; + if (manager == nsnull) + return; // don't need to lock the map, because this is only called // by GetNewOrUsed which locks it for us. @@ -184,7 +187,7 @@ nsProxyEventClass::nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo) #ifdef PROXYEVENTCLASS_DEBUG char* iidStr = aIID.ToString(); printf("GetNewOrUsedClass %s put\n", iidStr); - nsCRT::free(iidStr); + PR_Free(iidStr); #endif } @@ -208,7 +211,7 @@ nsProxyEventClass::nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo) nsProxyEventClass::~nsProxyEventClass() { - if(mDescriptors && mDescriptors != &zero_methods_descriptor) + if (mDescriptors && mDescriptors != &zero_methods_descriptor) delete [] mDescriptors; if (nsProxyObjectManager::IsManagerShutdown()) @@ -227,7 +230,7 @@ nsProxyEventClass::~nsProxyEventClass() #ifdef PROXYEVENTCLASS_DEBUG char* iidStr = mIID.ToString(); printf("GetNewOrUsedClass %s remove\n", iidStr); - nsCRT::free(iidStr); + PR_Free(iidStr); #endif } #endif @@ -242,7 +245,6 @@ nsProxyEventClass::CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID *aInstancePtr = nsnull; // in case of error. - // The functions we will call: QueryInterface(REFNSIID aIID, void** aInstancePtr) nsXPTCMiniVariant var[2]; @@ -278,7 +280,7 @@ nsProxyEventClass::CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID return NS_ERROR_FAILURE; } - rv = manager->GetProxyForObject(self->GetQueue(), + rv = manager->GetProxyForObject(self->GetTarget(), aIID, self->GetRealObject(), self->GetProxyType(), @@ -311,7 +313,7 @@ public: static ProxyEventClassIdentity* singleton = NULL; if(!singleton) singleton = new ProxyEventClassIdentity(); - return (void*) singleton; + return singleton; } }; @@ -333,41 +335,41 @@ nsProxyEventClass::DelegatedQueryInterface(nsProxyEventObject* self, nsProxyEventObject* sibling; { - nsProxyObjectManager* manager = nsProxyObjectManager::GetInstance(); - nsAutoMonitor mon(manager->GetMonitor()); + nsProxyObjectManager* manager = nsProxyObjectManager::GetInstance(); + nsAutoMonitor mon(manager->GetMonitor()); - // This includes checking for nsISupports and the iid of self. - // And it also checks for other wrappers that have been constructed - // for this object. - if(nsnull != (sibling = self->LockedFind(aIID))) - { - NS_ADDREF(sibling); - *aInstancePtr = (void*) sibling; - return NS_OK; - } - - // check if asking for an interface that we inherit from - nsCOMPtr current = GetInterfaceInfo(); - nsCOMPtr parent; - - while(NS_SUCCEEDED(current->GetParent(getter_AddRefs(parent))) && parent) - { - current = parent; - - nsIID* iid; - if(NS_SUCCEEDED(current->GetInterfaceIID(&iid)) && iid) + // This includes checking for nsISupports and the iid of self. + // And it also checks for other wrappers that have been constructed + // for this object. + if (nsnull != (sibling = self->LockedFind(aIID))) { - PRBool found = aIID.Equals(*iid); - nsMemory::Free(iid); - if(found) + NS_ADDREF(sibling); + *aInstancePtr = (void*) sibling; + return NS_OK; + } + + // check if asking for an interface that we inherit from + nsCOMPtr current = GetInterfaceInfo(); + nsCOMPtr parent; + + while (NS_SUCCEEDED(current->GetParent(getter_AddRefs(parent))) && parent) + { + current = parent; + + nsIID* iid; + if (NS_SUCCEEDED(current->GetInterfaceIID(&iid)) && iid) { - *aInstancePtr = (void*) self; - NS_ADDREF(self); - return NS_OK; + PRBool found = aIID.Equals(*iid); + nsMemory::Free(iid); + if (found) + { + *aInstancePtr = (void*) self; + NS_ADDREF(self); + return NS_OK; + } } } } - } return CallQueryInterfaceOnProxy(self, aIID, (nsProxyEventObject**)aInstancePtr); } diff --git a/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp b/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp index 5c8cfa3aef7..f1c577dbf4e 100644 --- a/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp +++ b/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp @@ -44,7 +44,6 @@ #include "nsIProxyObjectManager.h" #include "nsProxyEventPrivate.h" -#include "nsIEventQueueService.h" #include "nsServiceManagerUtils.h" #include "nsHashtable.h" @@ -55,36 +54,35 @@ #include "nsAutoLock.h" static NS_DEFINE_IID(kProxyObject_Identity_Class_IID, NS_PROXYEVENT_IDENTITY_CLASS_IID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); //////////////////////////////////////////////////////////////////////////////// class nsProxyEventKey : public nsHashKey { public: - nsProxyEventKey(void* rootObjectKey, void* destQueueKey, PRInt32 proxyType) - : mRootObjectKey(rootObjectKey), mDestQueueKey(destQueueKey), mProxyType(proxyType) { + nsProxyEventKey(void* rootObjectKey, void* targetKey, PRInt32 proxyType) + : mRootObjectKey(rootObjectKey), mTargetKey(targetKey), mProxyType(proxyType) { } PRUint32 HashCode(void) const { return NS_PTR_TO_INT32(mRootObjectKey) ^ - NS_PTR_TO_INT32(mDestQueueKey) ^ mProxyType; + NS_PTR_TO_INT32(mTargetKey) ^ mProxyType; } PRBool Equals(const nsHashKey *aKey) const { const nsProxyEventKey* other = (const nsProxyEventKey*)aKey; return mRootObjectKey == other->mRootObjectKey - && mDestQueueKey == other->mDestQueueKey + && mTargetKey == other->mTargetKey && mProxyType == other->mProxyType; } nsHashKey *Clone() const { - return new nsProxyEventKey(mRootObjectKey, mDestQueueKey, mProxyType); + return new nsProxyEventKey(mRootObjectKey, mTargetKey, mProxyType); } protected: void* mRootObjectKey; - void* mDestQueueKey; + void* mTargetKey; PRInt32 mProxyType; }; @@ -127,7 +125,7 @@ nsProxyEventObject::DebugDump(const char * message, PRUint32 hashKey) printf("%s wrapper around @ %x\n", isRoot ? "ROOT":"non-root\n", GetRealObject()); nsCOMPtr rootObject = do_QueryInterface(mProxyObject->mRealObject); - nsCOMPtr rootQueue = do_QueryInterface(mProxyObject->mDestQueue); + nsCOMPtr rootQueue = do_QueryInterface(mProxyObject->mTarget); nsProxyEventKey key(rootObject, rootQueue, mProxyObject->mProxyType); printf("Hashkey: %d\n", key.HashCode()); @@ -167,7 +165,7 @@ nsProxyEventObject::DebugDump(const char * message, PRUint32 hashKey) // ////////////////////////////////////////////////////////////////////////////////////////////////// nsProxyEventObject* -nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue, +nsProxyEventObject::GetNewOrUsedProxy(nsIEventTarget *target, PRInt32 proxyType, nsISupports *aObj, REFNSIID aIID) @@ -199,7 +197,7 @@ nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue, // if you hit this assertion, you might want to check out how // you are using proxies. You shouldn't need to be creating // a proxy from a proxy. -- dougt@netscape.com - NS_ASSERTION(0, "Someone is building a proxy from a proxy"); + NS_WARNING("Someone is building a proxy from a proxy"); NS_ASSERTION(identificationObject, "where did my identification object go!"); if (!identificationObject) { @@ -229,7 +227,7 @@ nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue, // Get the root nsISupports of the event queue... This is used later, // as part of the hashtable key... - nsCOMPtr destQRoot = do_QueryInterface(destQueue, &rv); + nsCOMPtr destQRoot = do_QueryInterface(target, &rv); if (NS_FAILED(rv) || !destQRoot) { return nsnull; } @@ -247,10 +245,6 @@ nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue, return nsnull; } - nsCOMPtr eventQService(do_GetService(kEventQueueServiceCID, &rv)); - if (NS_FAILED(rv)) - return nsnull; - nsAutoMonitor mon(manager->GetMonitor()); // Get the hash table containing root proxy objects... @@ -299,12 +293,11 @@ nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue, return nsnull; } - peo = new nsProxyEventObject(destQueue, + peo = new nsProxyEventObject(target, proxyType, rootObject, rootClazz, - nsnull, - eventQService); + nsnull); if(!peo) { // Ouch... Out of memory! return nsnull; @@ -352,12 +345,11 @@ nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue, return nsnull; } - peo = new nsProxyEventObject(destQueue, + peo = new nsProxyEventObject(target, proxyType, rawInterface, proxyClazz, - rootProxy, - eventQService); + rootProxy); if (!peo) { // Ouch... Out of memory! return nsnull; @@ -402,19 +394,18 @@ nsProxyEventObject::nsProxyEventObject() NS_WARNING("This constructor should never be called"); } -nsProxyEventObject::nsProxyEventObject(nsIEventQueue *destQueue, +nsProxyEventObject::nsProxyEventObject(nsIEventTarget *target, PRInt32 proxyType, nsISupports* aObj, nsProxyEventClass* aClass, - nsProxyEventObject* root, - nsIEventQueueService* eventQService) + nsProxyEventObject* root) : mClass(aClass), mRoot(root), mNext(nsnull) { NS_IF_ADDREF(mRoot); - mProxyObject = new nsProxyObject(destQueue, proxyType, aObj, eventQService); + mProxyObject = new nsProxyObject(target, proxyType, aObj); #ifdef DEBUG_xpcom_proxy DebugDump("Create", 0); @@ -456,7 +447,7 @@ nsProxyEventObject::~nsProxyEventObject() if (realToProxyMap != nsnull) { nsCOMPtr rootObject = do_QueryInterface(mProxyObject->mRealObject); - nsCOMPtr rootQueue = do_QueryInterface(mProxyObject->mDestQueue); + nsCOMPtr rootQueue = do_QueryInterface(mProxyObject->mTarget); nsProxyEventKey key(rootObject, rootQueue, mProxyObject->mProxyType); #ifdef DEBUG_dougt void* value = diff --git a/mozilla/xpcom/proxy/src/nsProxyEventPrivate.h b/mozilla/xpcom/proxy/src/nsProxyEventPrivate.h index 07ad7141dac..42f1a134b2a 100644 --- a/mozilla/xpcom/proxy/src/nsProxyEventPrivate.h +++ b/mozilla/xpcom/proxy/src/nsProxyEventPrivate.h @@ -36,20 +36,19 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef __nsProxyEventPrivate_h_ -#define __nsProxyEventPrivate_h_ +#ifndef nsProxyEventPrivate_h__ +#define nsProxyEventPrivate_h__ #include "nscore.h" #include "nsISupports.h" #include "nsIFactory.h" #include "nsHashtable.h" -#include "plevent.h" #include "xptcall.h" // defines nsXPTCVariant -#include "nsIEventQueue.h" #include "nsProxyEvent.h" #include "nsIProxyObjectManager.h" +#include "prmon.h" class nsProxyEventObject; class nsProxyEventClass; @@ -113,7 +112,7 @@ public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_OBJECT_IID) - static nsProxyEventObject* GetNewOrUsedProxy(nsIEventQueue *destQueue, + static nsProxyEventObject* GetNewOrUsedProxy(nsIEventTarget *target, PRInt32 proxyType, nsISupports *aObj, REFNSIID aIID); @@ -126,17 +125,16 @@ public: nsProxyEventClass* GetClass() const { return mClass; } - nsIEventQueue* GetQueue() const { return (mProxyObject ? mProxyObject->GetQueue() : nsnull);} + nsIEventTarget* GetTarget() const { return (mProxyObject ? mProxyObject->GetTarget() : nsnull);} nsISupports* GetRealObject() const { return (mProxyObject ? mProxyObject->GetRealObject(): nsnull);} PRInt32 GetProxyType() const { return (mProxyObject ? mProxyObject->GetProxyType() : nsnull);} nsProxyEventObject(); - nsProxyEventObject(nsIEventQueue *destQueue, + nsProxyEventObject(nsIEventTarget *target, PRInt32 proxyType, nsISupports* aObj, nsProxyEventClass* aClass, - nsProxyEventObject* root, - nsIEventQueueService* eventQService); + nsProxyEventObject* root); nsProxyEventObject* LockedFind(REFNSIID aIID); @@ -170,11 +168,9 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsProxyEventObject, NS_PROXYEVENT_OBJECT_IID) class nsProxyObjectManager: public nsIProxyObjectManager { public: - NS_DECL_ISUPPORTS NS_DECL_NSIPROXYOBJECTMANAGER - static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); nsProxyObjectManager(); @@ -198,5 +194,12 @@ private: PRMonitor *mProxyCreationMonitor; }; +#define NS_XPCOMPROXY_CLASSNAME "nsProxyObjectManager" +#define NS_PROXYEVENT_MANAGER_CID \ +{ 0xeea90d41, \ + 0xb059, \ + 0x11d2, \ + {0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33} \ +} -#endif +#endif // nsProxyEventPrivate_h__ diff --git a/mozilla/xpcom/proxy/src/nsProxyObjectManager.cpp b/mozilla/xpcom/proxy/src/nsProxyObjectManager.cpp index 566c4e8199d..afac93313ed 100644 --- a/mozilla/xpcom/proxy/src/nsProxyObjectManager.cpp +++ b/mozilla/xpcom/proxy/src/nsProxyObjectManager.cpp @@ -50,59 +50,15 @@ #include "nsProxyEvent.h" #include "nsIProxyObjectManager.h" #include "nsProxyEventPrivate.h" - -#include "nsIProxyCreateInstance.h" +#include "nsThreadUtils.h" #include "nsIComponentManager.h" #include "nsIServiceManager.h" #include "nsCOMPtr.h" -#include "nsIEventQueueService.h" #include "nsIThread.h" -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - -/***************************************************************************/ -/* nsProxyCreateInstance */ -/* This private class will allow us to create Instances on another thread */ -/***************************************************************************/ -class nsProxyCreateInstance : public nsIProxyCreateInstance -{ - NS_DECL_ISUPPORTS - NS_IMETHOD CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result); - NS_IMETHOD CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result); - - nsProxyCreateInstance() - { - NS_GetComponentManager(getter_AddRefs(mCompMgr)); - NS_ASSERTION(mCompMgr, "no component manager"); - } - -private: - - nsCOMPtr mCompMgr; -}; - -NS_IMPL_ISUPPORTS1(nsProxyCreateInstance, nsIProxyCreateInstance) - -NS_IMETHODIMP nsProxyCreateInstance::CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result) -{ - return mCompMgr->CreateInstance(cid, - aOuter, - iid, - result); -} - - -NS_IMETHODIMP nsProxyCreateInstance::CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result) -{ - return mCompMgr->CreateInstanceByContractID(aContractID, - aOuter, - iid, - result); -} - ///////////////////////////////////////////////////////////////////////// // nsProxyObjectManager ///////////////////////////////////////////////////////////////////////// @@ -118,20 +74,20 @@ nsProxyObjectManager::nsProxyObjectManager() mProxyCreationMonitor = PR_NewMonitor(); } -static PRBool PurgeProxyClasses(nsHashKey *aKey, void *aData, void* closure) +static PRIntn +PurgeProxyClasses(nsHashKey *aKey, void *aData, void* closure) { - nsProxyEventClass* ptr = NS_REINTERPRET_CAST(nsProxyEventClass*, aData); + nsProxyEventClass* ptr = NS_STATIC_CAST(nsProxyEventClass*, aData); NS_RELEASE(ptr); - return PR_TRUE; + return kHashEnumerateNext; } nsProxyObjectManager::~nsProxyObjectManager() { - mProxyClassMap.Reset((nsHashtableEnumFunc)PurgeProxyClasses, nsnull); + mProxyClassMap.Reset(PurgeProxyClasses, nsnull); - if (mProxyCreationMonitor) { + if (mProxyCreationMonitor) PR_DestroyMonitor(mProxyCreationMonitor); - } nsProxyObjectManager::mInstance = nsnull; } @@ -139,158 +95,73 @@ nsProxyObjectManager::~nsProxyObjectManager() PRBool nsProxyObjectManager::IsManagerShutdown() { - if (mInstance) - return PR_FALSE; - return PR_TRUE; + return mInstance == nsnull; } nsProxyObjectManager * nsProxyObjectManager::GetInstance() { - if (! mInstance) - { + if (!mInstance) mInstance = new nsProxyObjectManager(); - } return mInstance; } - void nsProxyObjectManager::Shutdown() { mInstance = nsnull; } - -// Helpers NS_IMETHODIMP -nsProxyObjectManager::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr) +nsProxyObjectManager::Create(nsISupports* outer, const nsIID& aIID, + void* *aInstancePtr) { nsProxyObjectManager *proxyObjectManager = GetInstance(); - - if (proxyObjectManager == nsnull) + if (!proxyObjectManager) return NS_ERROR_OUT_OF_MEMORY; return proxyObjectManager->QueryInterface(aIID, aInstancePtr); } - NS_IMETHODIMP -nsProxyObjectManager::GetProxyForObject(nsIEventQueue *destQueue, +nsProxyObjectManager::GetProxyForObject(nsIEventTarget* aTarget, REFNSIID aIID, nsISupports* aObj, PRInt32 proxyType, void** aProxyObject) { - if (!aObj) return NS_ERROR_NULL_POINTER; - if (!aProxyObject) return NS_ERROR_NULL_POINTER; - - nsresult rv; - nsCOMPtr postQ; - + NS_ENSURE_ARG_POINTER(aObj); *aProxyObject = nsnull; - // check to see if the destination Q is a special case. + // handle special values + nsCOMPtr thread; + if (aTarget == NS_PROXY_TO_CURRENT_THREAD) { + aTarget = NS_GetCurrentThread(); + } else if (aTarget == NS_PROXY_TO_MAIN_THREAD) { + thread = do_GetMainThread(); + aTarget = thread.get(); + } + + // check to see if the target is on our thread. If so, just return the + // real object. - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) - return rv; - - rv = eventQService->ResolveEventQueue(destQueue, getter_AddRefs(postQ)); - if (NS_FAILED(rv)) - return rv; - - // check to see if the eventQ is on our thread. If so, just return the real object. - - if (postQ && !(proxyType & PROXY_ASYNC) && !(proxyType & PROXY_ALWAYS)) + if (!(proxyType & NS_PROXY_ASYNC) && !(proxyType & NS_PROXY_ALWAYS)) { - PRBool aResult; - postQ->IsOnCurrentThread(&aResult); + PRBool result; + aTarget->IsOnCurrentThread(&result); - if (aResult) - { + if (result) return aObj->QueryInterface(aIID, aProxyObject); - } } // check to see if proxy is there or not. - *aProxyObject = nsProxyEventObject::GetNewOrUsedProxy(postQ, proxyType, aObj, aIID); - - if (*aProxyObject == nsnull) - return NS_ERROR_NO_INTERFACE; //fix error code? + *aProxyObject = nsProxyEventObject::GetNewOrUsedProxy(aTarget, proxyType, + aObj, aIID); + if (!*aProxyObject) + return NS_ERROR_UNEXPECTED; - return NS_OK; -} - - -NS_IMETHODIMP -nsProxyObjectManager::GetProxy( nsIEventQueue *destQueue, - const nsCID &aClass, - nsISupports *aDelegate, - const nsIID &aIID, - PRInt32 proxyType, - void** aProxyObject) -{ - if (!aProxyObject) return NS_ERROR_NULL_POINTER; - *aProxyObject = nsnull; - - // 1. Create a proxy for creating an instance on another thread. - - nsIProxyCreateInstance* ciProxy = nsnull; - - nsProxyCreateInstance* ciObject = new nsProxyCreateInstance(); - - if (ciObject == nsnull) - return NS_ERROR_NULL_POINTER; - - NS_ADDREF(ciObject); - - nsresult rv = GetProxyForObject(destQueue, - NS_GET_IID(nsIProxyCreateInstance), - ciObject, - PROXY_SYNC, - (void**)&ciProxy); - - if (NS_FAILED(rv)) - { - NS_RELEASE(ciObject); - return rv; - } - - // 2. now create a new instance of the request object via our proxy. - - nsISupports* aObj; - - rv = ciProxy->CreateInstanceByIID(aClass, - aDelegate, - aIID, - (void**)&aObj); - - - // 3. Delete the create instance proxy and its real object. - - NS_RELEASE(ciProxy); - NS_RELEASE(ciObject); - - // 4. Check to see if creating the requested instance failed. - if ( NS_FAILED(rv)) - { - return rv; - } - - // 5. Now create a proxy object for the requested object. - - rv = GetProxyForObject(destQueue, aIID, aObj, proxyType, aProxyObject); - - // 6. release ownership of aObj so that aProxyObject owns it. - - NS_RELEASE(aObj); - - // 7. return the error returned from GetProxyForObject. Either way, we our out of here. - - return rv; + return NS_OK; } /** @@ -301,7 +172,7 @@ nsProxyObjectManager::GetProxy( nsIEventQueue *destQueue, * readable. */ NS_COM nsresult -NS_GetProxyForObject(nsIEventQueue *destQueue, +NS_GetProxyForObject(nsIEventTarget *target, REFNSIID aIID, nsISupports* aObj, PRInt32 proxyType, @@ -309,18 +180,17 @@ NS_GetProxyForObject(nsIEventQueue *destQueue, { static NS_DEFINE_CID(proxyObjMgrCID, NS_PROXYEVENT_MANAGER_CID); - nsresult rv; // temp for return value + nsresult rv; // get the proxy object manager // nsCOMPtr proxyObjMgr = do_GetService(proxyObjMgrCID, &rv); - if (NS_FAILED(rv)) - return NS_ERROR_FAILURE; + return rv; // and try to get the proxy object // - return proxyObjMgr->GetProxyForObject(destQueue, aIID, aObj, + return proxyObjMgr->GetProxyForObject(target, aIID, aObj, proxyType, aProxyObject); } diff --git a/mozilla/xpcom/proxy/src/nsProxyRelease.cpp b/mozilla/xpcom/proxy/src/nsProxyRelease.cpp index 3ceeb6674bf..7d9c308cf1f 100644 --- a/mozilla/xpcom/proxy/src/nsProxyRelease.cpp +++ b/mozilla/xpcom/proxy/src/nsProxyRelease.cpp @@ -1,21 +1,65 @@ +/* vim:set ts=4 sw=4 sts=4 et cin: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + #include "nsProxyRelease.h" +#include "nsThreadUtils.h" +#include "nsAutoPtr.h" -PR_STATIC_CALLBACK(void*) -HandleProxyReleaseEvent(PLEvent *self) -{ - nsISupports* owner = (nsISupports*) self->owner; - NS_RELEASE(owner); - return nsnull; -} - -PR_STATIC_CALLBACK(void) -DestroyProxyReleaseEvent(PLEvent *self) +class nsProxyReleaseEvent : public nsRunnable { - delete self; -} +public: + nsProxyReleaseEvent(nsISupports *doomed) + : mDoomed(doomed) { + } + + NS_IMETHOD Run() + { + mDoomed->Release(); + return NS_OK; + } + +private: + nsISupports *mDoomed; +}; NS_COM nsresult -NS_ProxyRelease(nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy) +NS_ProxyRelease(nsIEventTarget *target, nsISupports *doomed, + PRBool alwaysProxy) { nsresult rv; @@ -33,21 +77,16 @@ NS_ProxyRelease(nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy) } } - PLEvent *ev = new PLEvent; + nsRefPtr ev = new nsProxyReleaseEvent(doomed); if (!ev) { // we do not release doomed here since it may cause a delete on the // wrong thread. better to leak than crash. return NS_ERROR_OUT_OF_MEMORY; } - PL_InitEvent(ev, doomed, - HandleProxyReleaseEvent, - DestroyProxyReleaseEvent); - - rv = target->PostEvent(ev); + rv = target->Dispatch(ev, NS_DISPATCH_NORMAL); if (NS_FAILED(rv)) { NS_WARNING("failed to post proxy release event"); - PL_DestroyEvent(ev); // again, it is better to leak the doomed object than risk crashing as // a result of deleting it on the wrong thread. } diff --git a/mozilla/xpcom/proxy/tests/proxytests.cpp b/mozilla/xpcom/proxy/tests/proxytests.cpp index 71346b24250..74ff7564b0f 100644 --- a/mozilla/xpcom/proxy/tests/proxytests.cpp +++ b/mozilla/xpcom/proxy/tests/proxytests.cpp @@ -39,10 +39,13 @@ #include #include "nsXPCOM.h" +#include "nsXPCOMCIDInternal.h" #include "nsIComponentManager.h" #include "nsIComponentRegistrar.h" #include "nsIServiceManager.h" +#include "nsAutoPtr.h" #include "nsCOMPtr.h" +#include "nsCOMArray.h" #include "nscore.h" #include "nspr.h" @@ -50,12 +53,29 @@ #include "nsITestProxy.h" +#include "nsIRunnable.h" #include "nsIProxyObjectManager.h" -#include "nsIEventQueueService.h" #include "nsComponentManagerUtils.h" #include "nsServiceManagerUtils.h" +#include "nsThreadUtils.h" -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); +#include "prlog.h" +#ifdef PR_LOGGING +static PRLogModuleInfo *sLog = PR_NewLogModule("Test"); +#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args) +#else +#define LOG(args) printf args +#endif + +static nsresult +GetThreadFromPRThread(PRThread *prthread, nsIThread **result) +{ + LOG(("TEST: GetThreadFromPRThread [%p]\n", prthread)); + + nsCOMPtr tm = do_GetService(NS_THREADMANAGER_CONTRACTID); + NS_ENSURE_STATE(tm); + return tm->GetThreadFromPRThread(prthread, result); +} /***************************************************************************/ /* nsTestXPCFoo */ @@ -79,7 +99,7 @@ NS_IMPL_ISUPPORTS1(nsTestXPCFoo, nsITestProxy) NS_IMETHODIMP nsTestXPCFoo::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval) { - printf("Thread (%d) Test Called successfully! Party on...\n", p1); + LOG(("TEST: Thread (%d) Test Called successfully! Party on...\n", p1)); *retval = p1+p2; return NS_OK; } @@ -87,7 +107,7 @@ NS_IMETHODIMP nsTestXPCFoo::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval) NS_IMETHODIMP nsTestXPCFoo::Test2() { - printf("The quick brown netscape jumped over the old lazy ie..\n"); + LOG(("TEST: The quick brown netscape jumped over the old lazy ie..\n")); return NS_OK; } @@ -103,7 +123,7 @@ NS_IMETHODIMP nsTestXPCFoo::Test3(nsISupports *p1, nsISupports **p2) test->Test2(); PRInt32 a; test->Test( 1, 2, &a); - printf("\n1+2=%d\n",a); + LOG(("TEST: \n1+2=%d\n",a)); } @@ -133,28 +153,31 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsTestXPCFoo2, nsITestProxy) NS_IMETHODIMP nsTestXPCFoo2::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval) { - printf("calling back to caller!\n\n"); + LOG(("TEST: calling back to caller!\n")); nsCOMPtr manager = do_GetService(NS_XPCOMPROXY_CONTRACTID); - printf("ProxyObjectManager: %p \n", (void *) manager.get()); + LOG(("TEST: ProxyObjectManager: %p \n", (void *) manager.get())); PR_ASSERT(manager); + nsCOMPtr thread; + GetThreadFromPRThread((PRThread *) p1, getter_AddRefs(thread)); + NS_ENSURE_STATE(thread); + nsCOMPtr proxyObject; - manager->GetProxyForObject((nsIEventQueue*)p1, NS_GET_IID(nsITestProxy), - this, PROXY_SYNC, (void**)&proxyObject); + manager->GetProxyForObject(thread, NS_GET_IID(nsITestProxy), this, NS_PROXY_SYNC, (void**)&proxyObject); proxyObject->Test3(nsnull, nsnull); - printf("Deleting Proxy Object\n"); + LOG(("TEST: Deleting Proxy Object\n")); return NS_OK; } NS_IMETHODIMP nsTestXPCFoo2::Test2() { - printf("nsTestXPCFoo2::Test2() called\n"); + LOG(("TEST: nsTestXPCFoo2::Test2() called\n")); return NS_OK; } @@ -162,17 +185,17 @@ NS_IMETHODIMP nsTestXPCFoo2::Test2() NS_IMETHODIMP nsTestXPCFoo2::Test3(nsISupports *p1, nsISupports **p2) { - printf("Got called"); + LOG(("TEST: Got called")); return NS_OK; } -typedef struct _ArgsStruct -{ - nsIEventQueue* queue; - PRInt32 threadNumber; -}ArgsStruct; +#if 0 +struct ArgsStruct { + nsIThread* thread; + PRInt32 threadNumber; +}; @@ -199,9 +222,9 @@ void TestCase_TwoClassesOneInterface(void *arg) PR_ASSERT(foo2); - manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject); + manager->GetProxyForObject(argsStruct->thread, NS_GET_IID(nsITestProxy), foo, NS_PROXY_SYNC, (void**)&proxyObject); - manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo2, PROXY_SYNC, (void**)&proxyObject2); + manager->GetProxyForObject(argsStruct->thread, NS_GET_IID(nsITestProxy), foo2, NS_PROXY_SYNC, (void**)&proxyObject2); @@ -242,17 +265,16 @@ void TestCase_TwoClassesOneInterface(void *arg) PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters } +#endif -void TestCase_NestedLoop(void *arg) +void TestCase_NestedLoop(nsIThread *thread, PRInt32 index) { - ArgsStruct *argsStruct = (ArgsStruct*) arg; - nsCOMPtr manager = do_GetService(NS_XPCOMPROXY_CONTRACTID); - printf("ProxyObjectManager: %p\n", (void *) manager.get()); + LOG(("TEST: ProxyObjectManager: %p\n", (void *) manager.get())); PR_ASSERT(manager); @@ -262,40 +284,30 @@ void TestCase_NestedLoop(void *arg) PR_ASSERT(foo); - manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject); + manager->GetProxyForObject(thread, NS_GET_IID(nsITestProxy), foo, NS_PROXY_SYNC, (void**)&proxyObject); if (proxyObject) { // release ownership of the real object. nsresult rv; - PRInt32 threadNumber = argsStruct->threadNumber; - printf("Deleting real Object (%d)\n", threadNumber); + LOG(("TEST: Deleting real Object (%d)\n", index)); NS_RELEASE(foo); PRInt32 retval; - printf("Getting EventQueue...\n"); + LOG(("TEST: Getting EventThread...\n")); - nsIEventQueue* eventQ; - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_SUCCEEDED(rv)) + //nsCOMPtr curThread = do_GetCurrentThread(); + PRThread *curThread = PR_GetCurrentThread(); + if (curThread) { - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ); - if (NS_FAILED(rv)) - rv = eventQService->CreateThreadEventQueue(); - if (NS_FAILED(rv)) - return; - else - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ); - - printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber); - rv = proxyObject->Test(NS_PTR_TO_INT32(eventQ), 0, &retval); - printf("Thread (%d) proxyObject error: %d.\n", threadNumber, rv); + LOG(("TEST: Thread (%d) Prior to calling proxyObject->Test.\n", index)); + rv = proxyObject->Test(NS_PTR_TO_INT32((void*)curThread), 0, &retval); // XXX broken on 64-bit arch + LOG(("TEST: Thread (%d) proxyObject error: %x.\n", index, rv)); - printf("Deleting Proxy Object (%d)\n", threadNumber ); + LOG(("TEST: Deleting Proxy Object (%d)\n", index)); NS_RELEASE(proxyObject); } @@ -304,34 +316,7 @@ void TestCase_NestedLoop(void *arg) } - -void TestCase_2(void *arg) -{ - - ArgsStruct *argsStruct = (ArgsStruct*) arg; - - nsCOMPtr manager = - do_GetService(NS_XPCOMPROXY_CONTRACTID); - - PR_ASSERT(manager); - - nsITestProxy *proxyObject; - - manager->GetProxy(argsStruct->queue, - NS_GET_IID(nsITestProxy), // should be CID! - nsnull, - NS_GET_IID(nsITestProxy), - PROXY_SYNC, - (void**)&proxyObject); - - if (proxyObject != nsnull) - { - NS_RELEASE(proxyObject); - } -} - - - +#if 0 void TestCase_nsISupports(void *arg) { @@ -347,7 +332,7 @@ void TestCase_nsISupports(void *arg) PR_ASSERT(foo); - manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject); + manager->GetProxyForObject(argsStruct->thread, NS_GET_IID(nsITestProxy), foo, NS_PROXY_SYNC, (void**)&proxyObject); if (proxyObject != nsnull) { @@ -365,96 +350,74 @@ void TestCase_nsISupports(void *arg) NS_RELEASE(proxyObject); } } - - - - +#endif /***************************************************************************/ /* ProxyTest */ /***************************************************************************/ -static void PR_CALLBACK ProxyTest( void *arg ) +class ProxyTest : public nsIRunnable { - //TestCase_TwoClassesOneInterface(arg); - // TestCase_2(arg); - //TestCase_nsISupports(arg); - TestCase_NestedLoop(arg); +public: + NS_DECL_ISUPPORTS - NS_RELEASE( ((ArgsStruct*) arg)->queue); - free((void*) arg); -} + ProxyTest(PRThread *eventLoopThread, PRInt32 index) + : mEventLoopThread(eventLoopThread) + , mIndex(index) + {} -nsIEventQueue *gEventQueue = nsnull; - -static void PR_CALLBACK EventLoop( void *arg ) -{ - nsresult rv; - printf("Creating EventQueue...\n"); - - nsIEventQueue* eventQ; - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ); - if (NS_FAILED(rv)) - rv = eventQService->CreateThreadEventQueue(); - if (NS_FAILED(rv)) - return; - else - rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ); - } - if (NS_FAILED(rv)) return; - - rv = eventQ->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&gEventQueue); - if (NS_FAILED(rv)) return; - - - printf("Verifing calling Proxy on eventQ thread.\n"); - - nsCOMPtr manager = - do_GetService(NS_XPCOMPROXY_CONTRACTID); - - PR_ASSERT(manager); - - nsITestProxy *proxyObject; - nsTestXPCFoo* foo = new nsTestXPCFoo(); - - PR_ASSERT(foo); - - manager->GetProxyForObject(gEventQueue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject); - - PRInt32 a; - proxyObject->Test(1, 2, &a); - proxyObject->Test2(); - - - NS_RELEASE(proxyObject); - delete foo; - - printf("End of Verification calling Proxy on eventQ thread.\n"); - - - printf("Looping for events.\n"); - - PLEvent* event = nsnull; - - while ( PR_SUCCESS == PR_Sleep( PR_MillisecondsToInterval(1)) ) + NS_IMETHOD Run() { - rv = gEventQueue->GetEvent(&event); - if (NS_FAILED(rv)) - return; - gEventQueue->HandleEvent(event); + //TestCase_TwoClassesOneInterface(arg); + //TestCase_nsISupports(arg); + nsCOMPtr thread; + GetThreadFromPRThread(mEventLoopThread, getter_AddRefs(thread)); + TestCase_NestedLoop(thread, mIndex); + + return NS_OK; } - gEventQueue->ProcessPendingEvents(); +private: + PRThread *mEventLoopThread; + PRInt32 mIndex; +}; +NS_IMPL_THREADSAFE_ISUPPORTS1(ProxyTest, nsIRunnable) - printf("Closing down Event Queue.\n"); - delete gEventQueue; - gEventQueue = nsnull; +class TestSyncProxyToSelf : public nsIRunnable +{ +public: + NS_DECL_ISUPPORTS - printf("End looping for events.\n\n"); -} + NS_IMETHOD Run() + { + LOG(("TEST: Verifing calling Proxy on eventQ thread.\n")); + + nsCOMPtr thread = do_GetCurrentThread(); + + nsITestProxy *proxyObject; + nsTestXPCFoo *foo = new nsTestXPCFoo(); + NS_ENSURE_STATE(foo); + + nsCOMPtr manager = + do_GetService(NS_XPCOMPROXY_CONTRACTID); + + manager->GetProxyForObject(thread, + NS_GET_IID(nsITestProxy), foo, + NS_PROXY_SYNC, (void**)&proxyObject); + + PRInt32 a; + proxyObject->Test(1, 2, &a); + proxyObject->Test2(); + + NS_RELEASE(proxyObject); + delete foo; + + LOG(("TEST: End of Verification calling Proxy on eventQ thread.\n")); + + return NS_OK; + } +}; +NS_IMPL_THREADSAFE_ISUPPORTS1(TestSyncProxyToSelf, nsIRunnable) int main(int argc, char **argv) @@ -464,72 +427,57 @@ main(int argc, char **argv) if (argc > 1) numberOfThreads = atoi(argv[1]); - nsCOMPtr servMan; - NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull); - nsCOMPtr registrar = do_QueryInterface(servMan); - NS_ASSERTION(registrar, "Null nsIComponentRegistrar"); - registrar->AutoRegister(nsnull); - - static PRThread** threads = (PRThread**) calloc(sizeof(PRThread*), numberOfThreads); - static PRThread* aEventThread; - - aEventThread = PR_CreateThread(PR_USER_THREAD, - EventLoop, - NULL, - PR_PRIORITY_NORMAL, - PR_GLOBAL_THREAD, - PR_JOINABLE_THREAD, - 0 ); + NS_InitXPCOM2(nsnull, nsnull, nsnull); - - PR_Sleep(PR_MillisecondsToInterval(1000)); - - NS_ASSERTION(gEventQueue, "no main event queue"); // BAD BAD BAD. EVENT THREAD DID NOT CREATE QUEUE. This may be a timing issue, set the - // sleep about longer, and try again. - - printf("Spawn Threads:\n"); - for (PRInt32 spawn = 0; spawn < numberOfThreads; spawn++) + // Scope code so everything is destroyed before we run call NS_ShutdownXPCOM { + nsCOMPtr registrar; + NS_GetComponentRegistrar(getter_AddRefs(registrar)); + registrar->AutoRegister(nsnull); - ArgsStruct *args = (ArgsStruct *) malloc (sizeof(ArgsStruct)); + nsCOMPtr eventLoopThread; + NS_NewThread(getter_AddRefs(eventLoopThread)); + + nsCOMPtr test = new TestSyncProxyToSelf(); + eventLoopThread->Dispatch(test, NS_DISPATCH_NORMAL); + + PRThread *eventLoopPRThread; + eventLoopThread->GetPRThread(&eventLoopPRThread); + PR_ASSERT(eventLoopPRThread); - args->queue = gEventQueue; - NS_ADDREF(args->queue); - args->threadNumber = spawn; + LOG(("TEST: Spawn Threads:\n")); + nsCOMArray threads; + for (PRInt32 spawn = 0; spawn < numberOfThreads; spawn++) + { + test = new ProxyTest(eventLoopPRThread, spawn); - threads[spawn] = PR_CreateThread(PR_USER_THREAD, - ProxyTest, - args, - PR_PRIORITY_NORMAL, - PR_GLOBAL_THREAD, - PR_JOINABLE_THREAD, - 0 ); + nsCOMPtr thread; + NS_NewThread(getter_AddRefs(thread), test); - printf("\tThread (%d) spawned\n", spawn); + threads.AppendObject(thread); - PR_Sleep( PR_MillisecondsToInterval(250) ); + LOG(("TEST: \tThread (%d) spawned\n", spawn)); + + PR_Sleep( PR_MillisecondsToInterval(250) ); + } + + LOG(("TEST: All Threads Spawned.\n")); + + LOG(("TEST: Wait for threads.\n")); + for (PRInt32 i = 0; i < numberOfThreads; i++) + { + LOG(("TEST: Thread (%d) Join...\n", i)); + nsresult rv = threads[i]->Shutdown(); + LOG(("TEST: Thread (%d) Joined. (error: %x).\n", i, rv)); + } + + LOG(("TEST: Shutting down event loop thread\n")); + eventLoopThread->Shutdown(); } - printf("All Threads Spawned.\n\n"); - - - - printf("Wait for threads.\n"); - for (PRInt32 i = 0; i < numberOfThreads; i++) - { - PRStatus rv; - printf("Thread (%d) Join...\n", i); - rv = PR_JoinThread(threads[i]); - printf("Thread (%d) Joined. (error: %d).\n", i, rv); - } + LOG(("TEST: Calling Cleanup.\n")); + NS_ShutdownXPCOM(nsnull); - PR_Interrupt(aEventThread); - PR_JoinThread(aEventThread); - - - printf("Calling Cleanup.\n"); - PR_Cleanup(); - - printf("Return zero.\n"); + LOG(("TEST: Return zero.\n")); return 0; } diff --git a/mozilla/xpcom/tests/Makefile.in b/mozilla/xpcom/tests/Makefile.in index 2e425474000..40ae0bbc763 100644 --- a/mozilla/xpcom/tests/Makefile.in +++ b/mozilla/xpcom/tests/Makefile.in @@ -84,6 +84,7 @@ CPPSRCS += \ TestPermanentAtoms.cpp \ TestPipes.cpp \ TestThreads.cpp \ + TestThreadPool.cpp \ TestXPIDLString.cpp \ TestDeque.cpp \ TestStrings.cpp \ diff --git a/mozilla/xpcom/tests/TestPipes.cpp b/mozilla/xpcom/tests/TestPipes.cpp index 644c8a9bf3d..7e60ba8dfd1 100644 --- a/mozilla/xpcom/tests/TestPipes.cpp +++ b/mozilla/xpcom/tests/TestPipes.cpp @@ -41,6 +41,7 @@ #include "nsIInputStream.h" #include "nsIOutputStream.h" #include "nsIServiceManager.h" +#include "nsThreadUtils.h" #include "prprf.h" #include "prinrval.h" #include "plstr.h" @@ -134,7 +135,7 @@ TestPipe(nsIInputStream* in, nsIOutputStream* out) if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(receiver); - rv = NS_NewThread(&thread, receiver, 0, PR_JOINABLE_THREAD); + rv = NS_NewThread(&thread, receiver); if (NS_FAILED(rv)) return rv; PRUint32 total = 0; @@ -160,7 +161,7 @@ TestPipe(nsIInputStream* in, nsIOutputStream* out) PRIntervalTime end = PR_IntervalNow(); - thread->Join(); + thread->Shutdown(); printf("wrote %d bytes, time = %dms\n", total, PR_IntervalToMilliseconds(end - start)); @@ -247,7 +248,7 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out) if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(receiver); - rv = NS_NewThread(&thread, receiver, 0, PR_JOINABLE_THREAD); + rv = NS_NewThread(&thread, receiver); if (NS_FAILED(rv)) return rv; PRUint32 total = 0; @@ -274,7 +275,7 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out) rv = out->Close(); if (NS_FAILED(rv)) return rv; - thread->Join(); + thread->Shutdown(); printf("wrote %d bytes\n", total); NS_RELEASE(thread); @@ -472,7 +473,7 @@ TestChainedPipes() if (pump == nsnull) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(pump); - rv = NS_NewThread(&thread, pump, 0, PR_JOINABLE_THREAD); + rv = NS_NewThread(&thread, pump); if (NS_FAILED(rv)) return rv; nsIThread* receiverThread; @@ -480,7 +481,7 @@ TestChainedPipes() if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(receiver); - rv = NS_NewThread(&receiverThread, receiver, 0, PR_JOINABLE_THREAD); + rv = NS_NewThread(&receiverThread, receiver); if (NS_FAILED(rv)) return rv; PRUint32 total = 0; @@ -504,8 +505,8 @@ TestChainedPipes() rv = out1->Close(); if (NS_FAILED(rv)) return rv; - thread->Join(); - receiverThread->Join(); + thread->Shutdown(); + receiverThread->Shutdown(); NS_RELEASE(thread); NS_RELEASE(pump); diff --git a/mozilla/netwerk/base/src/nsStreamListenerProxy.h b/mozilla/xpcom/tests/TestThreadPool.cpp similarity index 51% rename from mozilla/netwerk/base/src/nsStreamListenerProxy.h rename to mozilla/xpcom/tests/TestThreadPool.cpp index b856efcf6b2..9adfee8e3da 100644 --- a/mozilla/netwerk/base/src/nsStreamListenerProxy.h +++ b/mozilla/xpcom/tests/TestThreadPool.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -12,15 +13,14 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is mozilla.org code. + * The Original Code is Mozilla code. * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2001 + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Darin Fisher (original author) + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -36,48 +36,59 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef nsStreamListenerProxy_h__ -#define nsStreamListenerProxy_h__ - -#include "nsRequestObserverProxy.h" -#include "nsIStreamListenerProxy.h" -#include "nsIInputStream.h" -#include "nsIOutputStream.h" -#include "nsIObservableInputStream.h" -#include "nsIRequest.h" +#include +#include +#include "nsXPCOM.h" +#include "nsXPCOMCIDInternal.h" +#include "nsIThreadPool.h" +#include "nsComponentManagerUtils.h" #include "nsCOMPtr.h" +#include "nsIRunnable.h" -class nsStreamListenerProxy : public nsIStreamListenerProxy - , public nsIInputStreamObserver +class Task : public nsIRunnable { public: - NS_DECL_ISUPPORTS - NS_DECL_NSIREQUESTOBSERVER - NS_DECL_NSISTREAMLISTENER - NS_DECL_NSISTREAMLISTENERPROXY - NS_DECL_NSIINPUTSTREAMOBSERVER + NS_DECL_ISUPPORTS - nsStreamListenerProxy(); - virtual ~nsStreamListenerProxy(); + Task(int i) : mIndex(i) {} - nsresult GetListener(nsIStreamListener **); + NS_IMETHOD Run() + { + printf("###(%d) running from thread: %p\n", mIndex, (void *) PR_GetCurrentThread()); + int r = (int) ((float) rand() * 200 / RAND_MAX); + PR_Sleep(PR_MillisecondsToInterval(r)); + printf("###(%d) exiting from thread: %p\n", mIndex, (void *) PR_GetCurrentThread()); + return NS_OK; + } - void SetListenerStatus(nsresult status) { mListenerStatus = status; } - nsresult GetListenerStatus() { return mListenerStatus; } - - PRUint32 GetPendingCount(); - -protected: - nsRequestObserverProxy *mObserverProxy; - - nsCOMPtr mPipeIn; - nsCOMPtr mPipeOut; - - nsCOMPtr mRequestToResume; - PRLock *mLock; - PRUint32 mPendingCount; - PRBool mPipeEmptied; - nsresult mListenerStatus; +private: + int mIndex; }; +NS_IMPL_THREADSAFE_ISUPPORTS1(Task, nsIRunnable) -#endif // nsStreamListenerProxy_h__ +static nsresult +RunTests() +{ + nsCOMPtr pool = do_CreateInstance(NS_THREADPOOL_CONTRACTID); + NS_ENSURE_STATE(pool); + + for (int i = 0; i < 100; ++i) { + nsCOMPtr task = new Task(i); + NS_ENSURE_TRUE(task, NS_ERROR_OUT_OF_MEMORY); + + pool->Dispatch(task, NS_DISPATCH_NORMAL); + } + + pool->Shutdown(); + return NS_OK; +} + +int +main(int argc, char **argv) +{ + if (NS_FAILED(NS_InitXPCOM2(nsnull, nsnull, nsnull))) + return -1; + RunTests(); + NS_ShutdownXPCOM(nsnull); + return 0; +} diff --git a/mozilla/xpcom/tests/TestThreads.cpp b/mozilla/xpcom/tests/TestThreads.cpp index 4caac3ae73d..3f12cca748e 100644 --- a/mozilla/xpcom/tests/TestThreads.cpp +++ b/mozilla/xpcom/tests/TestThreads.cpp @@ -36,8 +36,7 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsIThread.h" -#include "nsIRunnable.h" +#include "nsThreadUtils.h" #include #include #include "nspr.h" @@ -51,7 +50,7 @@ public: NS_IMETHOD Run() { nsCOMPtr thread; - nsresult rv = nsIThread::GetCurrent(getter_AddRefs(thread)); + nsresult rv = NS_GetCurrentThread(getter_AddRefs(thread)); if (NS_FAILED(rv)) { printf("failed to get current thread\n"); return rv; @@ -79,54 +78,29 @@ TestThreads() { nsresult rv; + nsCOMPtr event = new nsRunner(0); + if (!event) + return NS_ERROR_OUT_OF_MEMORY; + nsCOMPtr runner; - rv = NS_NewThread(getter_AddRefs(runner), new nsRunner(0), 0, PR_JOINABLE_THREAD); + rv = NS_NewThread(getter_AddRefs(runner), event); if (NS_FAILED(rv)) { printf("failed to create thread\n"); return rv; } nsCOMPtr thread; - rv = nsIThread::GetCurrent(getter_AddRefs(thread)); + rv = NS_GetCurrentThread(getter_AddRefs(thread)); if (NS_FAILED(rv)) { printf("failed to get current thread\n"); return rv; } - PRThreadScope scope; - rv = runner->GetScope(&scope); - if (NS_FAILED(rv)) { - printf("runner already exited\n"); - } - - rv = runner->Join(); // wait for the runner to die before quitting + rv = runner->Shutdown(); // wait for the runner to die before quitting if (NS_FAILED(rv)) { printf("join failed\n"); } - rv = runner->GetScope(&scope); // this should fail after Join - if (NS_SUCCEEDED(rv)) { - printf("get scope failed\n"); - } - - rv = runner->Interrupt(); // this should fail after Join - if (NS_SUCCEEDED(rv)) { - printf("interrupt failed\n"); - } - - //////////////////////////////////////////////////////////////////////////// - // try an unjoinable thread - rv = NS_NewThread(getter_AddRefs(runner), new nsRunner(1)); - if (NS_FAILED(rv)) { - printf("failed to create thread\n"); - return rv; - } - - rv = runner->Join(); // wait for the runner to die before quitting - if (NS_SUCCEEDED(rv)) { - printf("shouldn't have been able to join an unjoinable thread\n"); - } - PR_Sleep(PR_MillisecondsToInterval(100)); // hopefully the runner will quit here return NS_OK; @@ -181,15 +155,16 @@ static int Stress(int loops, int threads) for (k = 0; k < threads; k++) { nsCOMPtr t; - nsresult rv = NS_NewThread(getter_AddRefs(t), - new nsStressRunner(k), - 0, PR_JOINABLE_THREAD); - NS_ASSERTION(NS_SUCCEEDED(rv), "can't create thread"); + nsresult rv = NS_NewThread(getter_AddRefs(t), new nsStressRunner(k)); + if (NS_FAILED(rv)) { + NS_ERROR("can't create thread"); + return -1; + } NS_ADDREF(array[k] = t); } for (k = threads-1; k >= 0; k--) { - array[k]->Join(); + array[k]->Shutdown(); NS_RELEASE(array[k]); } delete [] array; diff --git a/mozilla/xpcom/threads/Makefile.in b/mozilla/xpcom/threads/Makefile.in index 2cb9bc61a04..f6d0018d948 100644 --- a/mozilla/xpcom/threads/Makefile.in +++ b/mozilla/xpcom/threads/Makefile.in @@ -55,37 +55,34 @@ MOZILLA_INTERNAL_API = 1 REQUIRES = string \ $(NULL) -CSRCS = \ - plevent.c \ - $(NULL) - CPPSRCS = \ nsAutoLock.cpp \ - nsEnvironment.cpp \ nsEventQueue.cpp \ - nsEventQueueService.cpp \ + nsEnvironment.cpp \ nsThread.cpp \ - nsTimerImpl.cpp \ + nsThreadManager.cpp \ + nsThreadPool.cpp \ nsProcessCommon.cpp \ + nsTimerImpl.cpp \ TimerThread.cpp \ $(NULL) EXPORTS = \ nsAutoLock.h \ - plevent.h \ nsProcess.h \ - nsEventQueueUtils.h \ + nsEventQueue.h \ $(NULL) XPIDLSRCS = \ + nsIEventTarget.idl \ nsIThread.idl \ + nsIThreadInternal.idl \ + nsIThreadManager.idl \ + nsIThreadPool.idl \ nsITimer.idl \ nsITimerInternal.idl \ nsITimerManager.idl \ nsIRunnable.idl \ - nsIEventTarget.idl \ - nsIEventQueue.idl \ - nsIEventQueueService.idl \ nsIEnvironment.idl \ nsIProcess.idl \ nsISupportsPriority.idl \ diff --git a/mozilla/xpcom/threads/TimerThread.cpp b/mozilla/xpcom/threads/TimerThread.cpp index 1fc949cb0fb..d03dbf3116d 100644 --- a/mozilla/xpcom/threads/TimerThread.cpp +++ b/mozilla/xpcom/threads/TimerThread.cpp @@ -42,10 +42,12 @@ #include "TimerThread.h" #include "nsAutoLock.h" +#include "nsThreadUtils.h" #include "pratom.h" #include "nsIObserverService.h" #include "nsIServiceManager.h" +#include "nsIProxyObjectManager.h" NS_IMPL_THREADSAFE_ISUPPORTS2(TimerThread, nsIRunnable, nsIObserver) @@ -96,6 +98,8 @@ TimerThread::InitLocks() nsresult TimerThread::Init() { + PR_LOG(gTimerLog, PR_LOG_DEBUG, ("TimerThread::Init [%d]\n", mInitialized)); + if (mInitialized) { if (!mThread) return NS_ERROR_FAILURE; @@ -105,26 +109,26 @@ nsresult TimerThread::Init() if (PR_AtomicSet(&mInitInProgress, 1) == 0) { nsresult rv; - - mEventQueueService = do_GetService("@mozilla.org/event-queue-service;1", &rv); if (NS_SUCCEEDED(rv)) { - nsCOMPtr observerService - (do_GetService("@mozilla.org/observer-service;1", &rv)); - - if (NS_SUCCEEDED(rv)) { - // We hold on to mThread to keep the thread alive. - rv = NS_NewThread(getter_AddRefs(mThread), - NS_STATIC_CAST(nsIRunnable*, this), - 0, - PR_JOINABLE_THREAD, - PR_PRIORITY_NORMAL, - PR_GLOBAL_THREAD); - - if (NS_FAILED(rv)) { - mThread = nsnull; + // We hold on to mThread to keep the thread alive. + rv = NS_NewThread(getter_AddRefs(mThread), this); + if (NS_FAILED(rv)) { + mThread = nsnull; + } + else { + nsCOMPtr observerService = + do_GetService("@mozilla.org/observer-service;1"); + // We must not use the observer service from a background thread! + if (observerService && !NS_IsMainThread()) { + nsCOMPtr result = nsnull; + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIObserverService), + observerService, NS_PROXY_ASYNC, + getter_AddRefs(result)); + observerService.swap(result); } - else { - // We'll be released at xpcom shutdown + // We'll be released at xpcom shutdown + if (observerService) { observerService->AddObserver(this, "sleep_notification", PR_FALSE); observerService->AddObserver(this, "wake_notification", PR_FALSE); } @@ -152,6 +156,8 @@ nsresult TimerThread::Init() nsresult TimerThread::Shutdown() { + PR_LOG(gTimerLog, PR_LOG_DEBUG, ("TimerThread::Shutdown begin\n")); + if (!mThread) return NS_ERROR_NOT_INITIALIZED; @@ -171,7 +177,9 @@ nsresult TimerThread::Shutdown() } } - mThread->Join(); // wait for the thread to die + mThread->Shutdown(); // wait for the thread to die + + PR_LOG(gTimerLog, PR_LOG_DEBUG, ("TimerThread::Shutdown end\n")); return NS_OK; } @@ -222,11 +230,9 @@ void TimerThread::UpdateFilter(PRUint32 aDelay, PRIntervalTime aTimeout, } #ifdef DEBUG_TIMERS - if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) { - PR_LOG(gTimerLog, PR_LOG_DEBUG, - ("UpdateFilter: smoothSlack = %g, filterLength = %u\n", - smoothSlack, filterLength)); - } + PR_LOG(gTimerLog, PR_LOG_DEBUG, + ("UpdateFilter: smoothSlack = %g, filterLength = %u\n", + smoothSlack, filterLength)); #endif } diff --git a/mozilla/xpcom/threads/TimerThread.h b/mozilla/xpcom/threads/TimerThread.h index 039eea68c5c..367f50aff86 100644 --- a/mozilla/xpcom/threads/TimerThread.h +++ b/mozilla/xpcom/threads/TimerThread.h @@ -41,7 +41,6 @@ #ifndef TimerThread_h___ #define TimerThread_h___ -#include "nsIEventQueueService.h" #include "nsIObserver.h" #include "nsIRunnable.h" #include "nsIThread.h" @@ -78,9 +77,6 @@ public: void UpdateFilter(PRUint32 aDelay, PRIntervalTime aTimeout, PRIntervalTime aNow); - // For use by nsTimerImpl::Fire() - nsCOMPtr mEventQueueService; - void DoBeforeSleep(); void DoAfterSleep(); diff --git a/mozilla/xpcom/threads/nsEventQueue.cpp b/mozilla/xpcom/threads/nsEventQueue.cpp index 66e0bcd28f9..9d294fc7121 100644 --- a/mozilla/xpcom/threads/nsEventQueue.cpp +++ b/mozilla/xpcom/threads/nsEventQueue.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -12,18 +13,18 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is Mozilla Communicator client code. + * The Original Code is Mozilla code. * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to @@ -35,635 +36,96 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsCOMPtr.h" #include "nsEventQueue.h" -#include "nsIEventQueueService.h" -#include "nsIThread.h" - -#include "nsIServiceManager.h" -#include "nsIObserverService.h" - -#include "nsString.h" - +#include "nsAutoLock.h" +#include "nsCOMPtr.h" #include "prlog.h" -#ifdef NS_DEBUG -#include "prprf.h" +#ifdef PR_LOGGING +static PRLogModuleInfo *sLog = PR_NewLogModule("nsEventQueue"); #endif +#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args) -#if defined(PR_LOGGING) && defined(DEBUG_danm) -/* found these logs useful in conjunction with netlibStreamEvent logging - from netwerk. */ -PRLogModuleInfo* gEventQueueLog = 0; -PRUint32 gEventQueueLogCount = 0; -PRUint32 gEventQueueLogPPCount = 0; -static int gEventQueueLogPPLevel = 0; -static PLEventQueue *gEventQueueLogQueue = 0; -static PRThread *gEventQueueLogThread = 0; -#endif - -// in a real system, these would be members in a header class... -static const char gActivatedNotification[] = "nsIEventQueueActivated"; -static const char gDestroyedNotification[] = "nsIEventQueueDestroyed"; - -nsEventQueueImpl::nsEventQueueImpl() +nsEventQueue::nsEventQueue() + : mMonitor(nsAutoMonitor::NewMonitor("xpcom.eventqueue")) + , mHead(nsnull) + , mTail(nsnull) + , mOffsetHead(0) + , mOffsetTail(0) { - NS_ADDREF_THIS(); - /* The slightly weird ownership model for eventqueues goes like this: - - General: - There's an addref from the factory generally held by whoever asked for - the queue. The queue addrefs itself (right here) and releases itself - after someone calls StopAcceptingEvents() on the queue and when it is - dark and empty (in CheckForDeactivation()). - - Chained queues: - - Eldest queue: - The eldest queue in a chain is held on to by the EventQueueService - in a hash table, so it is possible that the eldest queue may not be - released until the EventQueueService is shutdown. - You may not call StopAcceptingEvents() on this queue until you have - done so on all younger queues. - - General: - Each queue holds a reference to their immediate elder link and a weak - reference to their immediate younger link. Because you must shut down - queues from youngest to eldest, all the references will be removed. - - It happens something like: - queue->StopAcceptingEvents() - { - CheckForDeactivation() - { - -- hopefully we are able to shutdown now -- - Unlink() - { - -- remove the reference we hold to our elder queue -- - -- NULL out our elder queues weak reference to us -- - } - RELEASE ourself (to balance the ADDREF here in the constructor) - -- and we should go away. -- - } - } - - - Notes: - A dark queue no longer accepts events. An empty queue simply has no events. - */ - -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Created [queue=%lx]",(long)mEventQueue)); - ++gEventQueueLogCount; -#endif - - mYoungerQueue = nsnull; - mEventQueue = nsnull; - mAcceptingEvents = PR_TRUE; - mCouldHaveEvents = PR_TRUE; } -nsEventQueueImpl::~nsEventQueueImpl() +nsEventQueue::~nsEventQueue() { - Unlink(); + if (mMonitor) + nsAutoMonitor::DestroyMonitor(mMonitor); +} -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Destroyed [queue=%lx]",(long)mEventQueue)); - ++gEventQueueLogCount; -#endif +PRBool +nsEventQueue::GetEvent(PRBool mayWait, nsIRunnable **result) +{ + nsAutoMonitor mon(mMonitor); - if (mEventQueue) { - // Perhaps CheckForDeactivation wasn't called... - if (mCouldHaveEvents) - NotifyObservers(gDestroyedNotification); - PL_DestroyEventQueue(mEventQueue); + while (IsEmpty()) { + if (!mayWait) { + if (result) + *result = nsnull; + return PR_FALSE; + } + LOG(("EVENTQ(%p): wait begin\n", this)); + mon.Wait(); + LOG(("EVENTQ(%p): wait end\n", this)); } + + if (result) { + *result = mHead->mEvents[mOffsetHead++]; + + // Check if mHead points to empty Page + if (mOffsetHead == EVENTS_PER_PAGE) { + Page *dead = mHead; + mHead = mHead->mNext; + FreePage(dead); + mOffsetHead = 0; + } + } + + return PR_TRUE; } -NS_IMETHODIMP -nsEventQueueImpl::Init(PRBool aNative) +PRBool +nsEventQueue::PutEvent(nsIRunnable *runnable) { - PRThread *thread = PR_GetCurrentThread(); - if (aNative) - mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", thread); - else - mEventQueue = PL_CreateMonitoredEventQueue("Thread event queue...", thread); - if (!mEventQueue) - return NS_ERROR_FAILURE; - NotifyObservers(gActivatedNotification); - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::InitFromPRThread(PRThread* thread, PRBool aNative) -{ - if (thread == NS_CURRENT_THREAD) + // Avoid calling AddRef+Release while holding our monitor. + nsCOMPtr event(runnable); + PRBool rv = PR_TRUE; { - thread = PR_GetCurrentThread(); - } - else if (thread == NS_UI_THREAD) - { - nsCOMPtr mainIThread; - nsresult rv; + nsAutoMonitor mon(mMonitor); - // Get the primordial thread - rv = nsIThread::GetMainThread(getter_AddRefs(mainIThread)); - if (NS_FAILED(rv)) return rv; - - rv = mainIThread->GetPRThread(&thread); - if (NS_FAILED(rv)) return rv; - } - - if (aNative) - mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", thread); - else - mEventQueue = PL_CreateMonitoredEventQueue("Thread event queue...", thread); - if (!mEventQueue) - return NS_ERROR_FAILURE; - - NotifyObservers(gActivatedNotification); - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::InitFromPLQueue(PLEventQueue* aQueue) -{ - mEventQueue = aQueue; - NotifyObservers(gActivatedNotification); - return NS_OK; -} - -/* nsISupports interface implementation... */ -NS_IMPL_THREADSAFE_ISUPPORTS3(nsEventQueueImpl, - nsIEventQueue, - nsIEventTarget, - nsPIEventQueueChain) - -/* nsIEventQueue interface implementation... */ - -NS_IMETHODIMP -nsEventQueueImpl::StopAcceptingEvents() -{ - if (mYoungerQueue) { - NS_ERROR("Should not shut down eventq while child queues are active"); - mYoungerQueue->StopAcceptingEvents(); - } - - // XXXThis method can be called from any thread: do we need to protect this - // with a lock? - mAcceptingEvents = PR_FALSE; - CheckForDeactivation(); -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: StopAccepting [queue=%lx, accept=%d, could=%d]", - (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents)); - ++gEventQueueLogCount; -#endif - return NS_OK; -} - -// utility funtion to send observers a notification -void -nsEventQueueImpl::NotifyObservers(const char *aTopic) -{ - // only send out this notification for native event queues - if (!PL_IsQueueNative(mEventQueue)) - return; - - // we should not call out to the observer service from background threads! - NS_ASSERTION(nsIThread::IsMainThread(), - "Native event queues should only be used on the main thread"); - - nsresult rv; - nsCOMPtr os = do_GetService("@mozilla.org/observer-service;1", &rv); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr kungFuDeathGrip(this); - nsCOMPtr us(do_QueryInterface(kungFuDeathGrip)); - os->NotifyObservers(us, aTopic, NULL); - } -} - -void -nsEventQueueImpl::CheckForDeactivation() -{ - if (mCouldHaveEvents && !mAcceptingEvents && !PL_EventAvailable(mEventQueue)) { - if (PL_IsQueueOnCurrentThread(mEventQueue)) { - mCouldHaveEvents = PR_FALSE; - NotifyObservers(gDestroyedNotification); - NS_RELEASE_THIS(); // balance ADDREF from the constructor - } else - NS_ERROR("CheckForDeactivation called from wrong thread!"); - } -} - - -NS_IMETHODIMP -nsEventQueueImpl::InitEvent(PLEvent* aEvent, - void* owner, - PLHandleEventProc handler, - PLDestroyEventProc destructor) -{ - PL_InitEvent(aEvent, owner, handler, destructor); - return NS_OK; -} - - -NS_IMETHODIMP -nsEventQueueImpl::PostEvent(PLEvent* aEvent) -{ - if (!mAcceptingEvents) { -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Punt posted event [queue=%lx, accept=%d, could=%d]", - (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents)); - ++gEventQueueLogCount; -#endif - nsresult rv = NS_ERROR_FAILURE; - NS_ASSERTION(mElderQueue, "event dropped because event chain is dead"); - if (mElderQueue) { - nsCOMPtr elder(do_QueryInterface(mElderQueue)); - if (elder) - rv = elder->PostEvent(aEvent); + if (!mHead) { + mHead = NewPage(); + if (!mHead) { + rv = PR_FALSE; + } else { + mTail = mHead; + mOffsetHead = 0; + mOffsetTail = 0; + } + } else if (mOffsetTail == EVENTS_PER_PAGE) { + Page *page = NewPage(); + if (!page) { + rv = PR_FALSE; + } else { + mTail->mNext = page; + mTail = page; + mOffsetTail = 0; + } } - return rv; - } -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Posting event [queue=%lx]", (long)mEventQueue)); - ++gEventQueueLogCount; -#endif - return PL_PostEvent(mEventQueue, aEvent) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -nsEventQueueImpl::PostSynchronousEvent(PLEvent* aEvent, void** aResult) -{ - if (!mAcceptingEvents) { -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Punt posted synchronous event [queue=%lx, accept=%d, could=%d]", - (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents)); - ++gEventQueueLogCount; -#endif - nsresult rv = NS_ERROR_NO_INTERFACE; - NS_ASSERTION(mElderQueue, "event dropped because event chain is dead"); - if (mElderQueue) { - nsCOMPtr elder(do_QueryInterface(mElderQueue)); - if (elder) - rv = elder->PostSynchronousEvent(aEvent, aResult); - return rv; + if (rv) { + event.swap(mTail->mEvents[mOffsetTail]); + ++mOffsetTail; + LOG(("EVENTQ(%p): notify\n", this)); + mon.NotifyAll(); } - return NS_ERROR_ABORT; - } - -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Posting synchronous event [queue=%lx]", (long)mEventQueue)); - ++gEventQueueLogCount; -#endif - void* result = PL_PostSynchronousEvent(mEventQueue, aEvent); - if (aResult) - *aResult = result; - - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::EnterMonitor() -{ - PL_ENTER_EVENT_QUEUE_MONITOR(mEventQueue); - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::ExitMonitor() -{ - PL_EXIT_EVENT_QUEUE_MONITOR(mEventQueue); - return NS_OK; -} - - -NS_IMETHODIMP -nsEventQueueImpl::RevokeEvents(void* owner) -{ - nsCOMPtr youngest; - GetYoungest(getter_AddRefs(youngest)); - NS_ASSERTION(youngest, "How could we possibly not have a youngest queue?"); - nsCOMPtr youngestAsChain(do_QueryInterface(youngest)); - NS_ASSERTION(youngestAsChain, "RevokeEvents won't work; expect crashes"); - return youngestAsChain->RevokeEventsInternal(owner); -} - - -NS_IMETHODIMP -nsEventQueueImpl::GetPLEventQueue(PLEventQueue** aEventQueue) -{ - if (!mEventQueue) - return NS_ERROR_NULL_POINTER; - - *aEventQueue = mEventQueue; - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::IsOnCurrentThread(PRBool *aResult) -{ - *aResult = PL_IsQueueOnCurrentThread( mEventQueue ); - return NS_OK; -} - - -NS_IMETHODIMP -nsEventQueueImpl::IsQueueNative(PRBool *aResult) -{ - *aResult = PL_IsQueueNative(mEventQueue); - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::PendingEvents(PRBool *aResult) -{ - *aResult = PL_EventAvailable(mEventQueue); - if (!*aResult && mElderQueue) { - nsCOMPtr elder(do_QueryInterface(mElderQueue)); - if (elder) - return elder->EventAvailable(*aResult); - } - return NS_OK; -} - - -NS_IMETHODIMP -nsEventQueueImpl::ProcessPendingEvents() -{ - PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue); - - NS_ASSERTION(correctThread, "attemping to process events on the wrong thread"); - - if (!correctThread) - return NS_ERROR_FAILURE; -#if defined(PR_LOGGING) && defined(DEBUG_danm) - ++gEventQueueLogPPLevel; - if ((gEventQueueLogQueue != mEventQueue || gEventQueueLogThread != PR_GetCurrentThread() || - gEventQueueLogCount != gEventQueueLogPPCount) && gEventQueueLogPPLevel == 1) { - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Process pending [queue=%lx, accept=%d, could=%d]", - (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents)); - gEventQueueLogPPCount = ++gEventQueueLogCount; - gEventQueueLogQueue = mEventQueue; - gEventQueueLogThread = PR_GetCurrentThread(); - } -#endif - PL_ProcessPendingEvents(mEventQueue); - - // if we're no longer accepting events and there are still events in the - // queue, then process remaining events. - if (!mAcceptingEvents && PL_EventAvailable(mEventQueue)) - PL_ProcessPendingEvents(mEventQueue); - - CheckForDeactivation(); - - if (mElderQueue) { - nsCOMPtr elder(do_QueryInterface(mElderQueue)); - if (elder) - elder->ProcessPendingEvents(); - } -#if defined(PR_LOGGING) && defined(DEBUG_danm) - --gEventQueueLogPPLevel; -#endif - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::EventLoop() -{ - PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue); - - NS_ASSERTION(correctThread, "attemping to process events on the wrong thread"); - - if (!correctThread) - return NS_ERROR_FAILURE; - - PL_EventLoop(mEventQueue); - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::EventAvailable(PRBool& aResult) -{ - aResult = PL_EventAvailable(mEventQueue); - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::GetEvent(PLEvent** aResult) -{ - *aResult = PL_GetEvent(mEventQueue); - CheckForDeactivation(); - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::HandleEvent(PLEvent* aEvent) -{ - PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue); - NS_ASSERTION(correctThread, "attemping to process events on the wrong thread"); - if (!correctThread) - return NS_ERROR_FAILURE; - -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: handle event [queue=%lx, accept=%d, could=%d]", - (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents)); - ++gEventQueueLogCount; -#endif - PL_HandleEvent(aEvent); - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::WaitForEvent(PLEvent** aResult) -{ - PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue); - NS_ASSERTION(correctThread, "attemping to process events on the wrong thread"); - if (!correctThread) - return NS_ERROR_FAILURE; - -#if defined(PR_LOGGING) && defined(DEBUG_danm) -PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: wait for event [queue=%lx, accept=%d, could=%d]", - (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents)); -++gEventQueueLogCount; -#endif - *aResult = PL_WaitForEvent(mEventQueue); - CheckForDeactivation(); - return NS_OK; -} - -NS_IMETHODIMP_(PRInt32) -nsEventQueueImpl::GetEventQueueSelectFD() -{ - return PL_GetEventQueueSelectFD(mEventQueue); -} - -NS_METHOD -nsEventQueueImpl::Create(nsISupports *aOuter, - REFNSIID aIID, - void **aResult) -{ - nsEventQueueImpl* evt = new nsEventQueueImpl(); - if (evt == NULL) - return NS_ERROR_OUT_OF_MEMORY; - nsresult rv = evt->QueryInterface(aIID, aResult); - if (NS_FAILED(rv)) { - delete evt; } return rv; } - -// ---------------- nsPIEventQueueChain ----------------- - -NS_IMETHODIMP -nsEventQueueImpl::AppendQueue(nsIEventQueue *aQueue) -{ - nsresult rv; - nsCOMPtr end; - nsCOMPtr queueChain(do_QueryInterface(aQueue)); - - if (!aQueue) - return NS_ERROR_NO_INTERFACE; - -/* this would be nice - NS_ASSERTION(aQueue->mYoungerQueue == NULL && aQueue->mElderQueue == NULL, - "event queue repeatedly appended to queue chain"); -*/ - rv = NS_ERROR_NO_INTERFACE; - -#ifdef NS_DEBUG - int depth = 0; - nsEventQueueImpl *next = this; - while (next && depth < 100) { - next = NS_STATIC_CAST(nsEventQueueImpl *, next->mYoungerQueue); - ++depth; - } - if (depth > 5) { - char warning[80]; - PR_snprintf(warning, sizeof(warning), - "event queue chain length is %d. this is almost certainly a leak.", depth); - NS_WARNING(warning); - } -#endif - - // (be careful doing this outside nsEventQueueService's mEventQMonitor) - - GetYoungest(getter_AddRefs(end)); - nsCOMPtr endChain(do_QueryInterface(end)); - if (endChain) { - endChain->SetYounger(queueChain); - queueChain->SetElder(endChain); - rv = NS_OK; - } - return rv; -} - -NS_IMETHODIMP -nsEventQueueImpl::Unlink() -{ - nsCOMPtr young = mYoungerQueue, - old = mElderQueue; - -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: unlink [queue=%lx, younger=%lx, elder=%lx]", - (long)mEventQueue,(long)mYoungerQueue, (long)mElderQueue.get())); - ++gEventQueueLogCount; -#endif - - // this is probably OK, but shouldn't happen by design, so tell me if it does - NS_ASSERTION(!mYoungerQueue, "event queue chain broken in middle"); - - // break links early in case the Release cascades back onto us - mYoungerQueue = nsnull; - mElderQueue = nsnull; - - if (young) - young->SetElder(old); - if (old) { - old->SetYounger(young); - } - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::GetYoungest(nsIEventQueue **aQueue) -{ - if (mYoungerQueue) - return mYoungerQueue->GetYoungest(aQueue); - - nsIEventQueue *answer = NS_STATIC_CAST(nsIEventQueue *, this); - NS_ADDREF(answer); - *aQueue = answer; - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::GetYoungestActive(nsIEventQueue **aQueue) -{ - nsCOMPtr answer; - - if (mYoungerQueue) - mYoungerQueue->GetYoungestActive(getter_AddRefs(answer)); - if (!answer) { - if (mAcceptingEvents && mCouldHaveEvents) - answer = NS_STATIC_CAST(nsIEventQueue *, this); - } - *aQueue = answer; - NS_IF_ADDREF(*aQueue); - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::SetYounger(nsPIEventQueueChain *aQueue) -{ - mYoungerQueue = aQueue; - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::SetElder(nsPIEventQueueChain *aQueue) -{ - mElderQueue = aQueue; - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueImpl::GetYounger(nsIEventQueue **aQueue) -{ - if (!mYoungerQueue) { - *aQueue = nsnull; - return NS_OK; - } - return mYoungerQueue->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&aQueue); -} - -NS_IMETHODIMP -nsEventQueueImpl::GetElder(nsIEventQueue **aQueue) -{ - if (!mElderQueue) { - *aQueue = nsnull; - return NS_OK; - } - return mElderQueue->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&aQueue); -} - -NS_IMETHODIMP -nsEventQueueImpl::RevokeEventsInternal(void* aOwner) -{ - PL_RevokeEvents(mEventQueue, aOwner); - if (mElderQueue) { - mElderQueue->RevokeEventsInternal(aOwner); - } - return NS_OK; -} diff --git a/mozilla/xpcom/threads/nsEventQueue.h b/mozilla/xpcom/threads/nsEventQueue.h index 8cffe436667..cfe01d50398 100644 --- a/mozilla/xpcom/threads/nsEventQueue.h +++ b/mozilla/xpcom/threads/nsEventQueue.h @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -12,19 +13,18 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is Mozilla Communicator client code. + * The Original Code is Mozilla code. * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Pierre Phaneuf + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to @@ -36,44 +36,87 @@ * * ***** END LICENSE BLOCK ***** */ -#include "prmon.h" -#include "nsIEventQueue.h" -#include "nsPIEventQueueChain.h" +#ifndef nsEventQueue_h__ +#define nsEventQueue_h__ -class nsEventQueueImpl : public nsPIEventQueueChain +#include +#include "prmon.h" +#include "nsIRunnable.h" + +// A threadsafe FIFO event queue... +class NS_COM nsEventQueue { public: - nsEventQueueImpl(); + nsEventQueue(); + ~nsEventQueue(); - NS_DECL_ISUPPORTS - NS_DECL_NSIEVENTTARGET - NS_DECL_NSIEVENTQUEUE + // Returns "true" if the event queue has been completely constructed. + PRBool IsInitialized() { return mMonitor != nsnull; } - // Helpers - static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + // This method adds a new event to the pending event queue. The event object + // is AddRef'd if this method succeeds. This method returns PR_TRUE if the + // event was stored in the event queue, and it returns PR_FALSE if it could + // not allocate sufficient memory. + PRBool PutEvent(nsIRunnable *event); - static const nsCID& CID() { static nsCID cid = NS_EVENTQUEUE_CID; return cid; } + // This method gets an event from the event queue. If mayWait is true, then + // the method will block the calling thread until an event is available. If + // the event is null, then the method returns immediately indicating whether + // or not an event is pending. When the resulting event is non-null, the + // caller is responsible for releasing the event object. This method does + // not alter the reference count of the resulting event. + PRBool GetEvent(PRBool mayWait, nsIRunnable **event); - // nsPIEventQueueChain interface - NS_IMETHOD AppendQueue(nsIEventQueue *aQueue); - NS_IMETHOD Unlink(); - NS_IMETHOD GetYoungest(nsIEventQueue **aQueue); - NS_IMETHOD GetYoungestActive(nsIEventQueue **aQueue); - NS_IMETHOD SetYounger(nsPIEventQueueChain *aQueue); - NS_IMETHOD GetYounger(nsIEventQueue **aQueue); - NS_IMETHOD SetElder(nsPIEventQueueChain *aQueue); - NS_IMETHOD GetElder(nsIEventQueue **aQueue); - NS_IMETHOD RevokeEventsInternal(void* aOwner); + // This method returns true if there is a pending event. + PRBool HasPendingEvent() { + return GetEvent(PR_FALSE, nsnull); + } + + // This method returns the next pending event or null. + PRBool GetPendingEvent(nsIRunnable **runnable) { + return GetEvent(PR_FALSE, runnable); + } + + // This method waits for and returns the next pending event. + PRBool WaitPendingEvent(nsIRunnable **runnable) { + return GetEvent(PR_TRUE, runnable); + } + + // Expose the event queue's monitor for "power users" + PRMonitor *Monitor() { + return mMonitor; + } private: - ~nsEventQueueImpl(); - PLEventQueue *mEventQueue; - PRBool mAcceptingEvents, // accept new events or pass them on? - mCouldHaveEvents; // accepting new ones, or still have old ones? - nsCOMPtr mElderQueue; // younger can hold on to elder - nsPIEventQueueChain *mYoungerQueue; // but elder can't hold on to younger + PRBool IsEmpty() { + return !mHead || (mHead == mTail && mOffsetHead == mOffsetTail); + } - void NotifyObservers(const char *aTopic); - void CheckForDeactivation(); + enum { EVENTS_PER_PAGE = 250 }; + + // Page objects are linked together to form a simple deque. + + struct Page { + struct Page *mNext; + nsIRunnable *mEvents[EVENTS_PER_PAGE]; + }; + + static Page *NewPage() { + return NS_STATIC_CAST(Page *, calloc(1, sizeof(Page))); + } + + static void FreePage(Page *p) { + free(p); + } + + PRMonitor *mMonitor; + + Page *mHead; + Page *mTail; + + PRUint16 mOffsetHead; // offset into mHead where next item is removed + PRUint16 mOffsetTail; // offset into mTail where next item is added }; + +#endif // nsEventQueue_h__ diff --git a/mozilla/xpcom/threads/nsEventQueueService.cpp b/mozilla/xpcom/threads/nsEventQueueService.cpp deleted file mode 100644 index afb9b34dd1c..00000000000 --- a/mozilla/xpcom/threads/nsEventQueueService.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Rick Potts - * Ramiro Estrugo - * Warren Harris - * Leaf Nunes - * David Matiskella - * David Hyatt - * Seth Spitzer - * Suresh Duddi - * Bruce Mitchener - * Scott Collins - * Daniel Matejka - * Doug Turner - * Stuart Parmenter - * Mike Kaply - * Dan Mosedale - * Benjamin Smedberg - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsEventQueueService.h" -#include "prmon.h" -#include "nsIComponentManager.h" -#include "nsIThread.h" -#include "nsPIEventQueueChain.h" -#include "nsAutoLock.h" - -#include "prlog.h" - -#if defined(PR_LOGGING) || defined(DEBUG_danm) -extern PRLogModuleInfo* gEventQueueLog; -extern PRUint32 gEventQueueLogCount; -#endif - -static NS_DEFINE_CID(kEventQueueCID, NS_EVENTQUEUE_CID); - -nsEventQueueServiceImpl::nsEventQueueServiceImpl() - : mEventQMonitor(PR_NewMonitor()) - , mIsShuttingDown(PR_FALSE) -{ -#if defined(PR_LOGGING) && defined(DEBUG_danm) - if (!gEventQueueLog) - gEventQueueLog = PR_NewLogModule("nseventqueue"); -#endif -} - -PR_STATIC_CALLBACK(PLDHashOperator) -hash_enum_remove_queues(const void *aThread_ptr, - nsCOMPtr& aEldestQueue, - void* closure) -{ - aEldestQueue->StopAcceptingEvents(); - return PL_DHASH_REMOVE; -} - -void -nsEventQueueServiceImpl::Shutdown() -{ - NS_ASSERTION(mEventQTable.Count() <= 1, - "Event queues for secondary threads exist during shutdown."); - - nsAutoMonitor mon(mEventQMonitor); - mIsShuttingDown = PR_TRUE; - - // Call StopAcceptingEvents on any queues that are left: this should be only - // the main-thread event queue at this point, since xpcom-shutdown-threads has - // already been notified. - mEventQTable.Enumerate(hash_enum_remove_queues, nsnull); -} - -nsEventQueueServiceImpl::~nsEventQueueServiceImpl() -{ - if (mEventQMonitor) - PR_DestroyMonitor(mEventQMonitor); -} - -nsresult -nsEventQueueServiceImpl::Init() -{ - NS_ENSURE_TRUE(mEventQMonitor, NS_ERROR_OUT_OF_MEMORY); - - // This will only be called once on the main thread, so it's safe to - // not enter the monitor here. - if (!mEventQTable.Init()) { - return NS_ERROR_OUT_OF_MEMORY; - } - - // ensure that a main thread event queue exists! - nsresult rv; - nsCOMPtr mainThread; - rv = nsIThread::GetMainThread(getter_AddRefs(mainThread)); - if (NS_SUCCEEDED(rv)) { - PRThread *thr; - rv = mainThread->GetPRThread(&thr); - if (NS_SUCCEEDED(rv)) - rv = CreateEventQueue(thr, PR_TRUE); - } - return rv; -} - -/* nsISupports interface implementation... */ -// QI to our CID so that NS_ShutdownXPCOM can call our internal methods -NS_IMPL_THREADSAFE_ISUPPORTS2(nsEventQueueServiceImpl, - nsIEventQueueService, - nsEventQueueServiceImpl) - -/* nsIEventQueueService interface implementation... */ - -NS_IMETHODIMP -nsEventQueueServiceImpl::CreateThreadEventQueue() -{ - return CreateEventQueue(PR_GetCurrentThread(), PR_TRUE); -} - -NS_IMETHODIMP -nsEventQueueServiceImpl::CreateMonitoredThreadEventQueue() -{ - return CreateEventQueue(PR_GetCurrentThread(), PR_FALSE); -} - -NS_IMETHODIMP -nsEventQueueServiceImpl::CreateFromIThread(nsIThread *aThread, PRBool aNative, - nsIEventQueue **aResult) -{ - nsresult rv; - PRThread *prThread; - - rv = aThread->GetPRThread(&prThread); - if (NS_SUCCEEDED(rv)) { - rv = CreateEventQueue(prThread, aNative); // addrefs - if (NS_SUCCEEDED(rv)) - rv = GetThreadEventQueue(prThread, aResult); // addrefs - } - return rv; -} - -// private method -NS_IMETHODIMP -nsEventQueueServiceImpl::MakeNewQueue(PRThread* thread, - PRBool aNative, - nsPIEventQueueChain **aQueue) -{ - nsresult rv; - nsCOMPtr queue(do_CreateInstance(kEventQueueCID, &rv)); - - if (NS_SUCCEEDED(rv)) { - rv = queue->InitFromPRThread(thread, aNative); - if (NS_FAILED(rv)) - queue = nsnull; - } - *aQueue = queue; - NS_IF_ADDREF(*aQueue); - return rv; -} - -// private method -NS_IMETHODIMP -nsEventQueueServiceImpl::CreateEventQueue(PRThread *aThread, PRBool aNative) -{ - nsresult rv; - - nsAutoMonitor mon(mEventQMonitor); - - if (mIsShuttingDown) - return NS_ERROR_ILLEGAL_DURING_SHUTDOWN; - - /* create only one event queue chain per thread... */ - if (mEventQTable.GetWeak(aThread)) - return NS_OK; - - nsCOMPtr queue; - - // we don't have one in the table, create new queue - rv = MakeNewQueue(aThread, aNative, getter_AddRefs(queue)); - if (NS_SUCCEEDED(rv)) - mEventQTable.Put(aThread, queue); // add to the table (initial addref) - - return rv; -} - - -NS_IMETHODIMP -nsEventQueueServiceImpl::DestroyThreadEventQueue(void) -{ - /* Enter the lock that protects the EventQ hashtable... */ - nsAutoMonitor mon(mEventQMonitor); - - PRThread* currentThread = PR_GetCurrentThread(); - nsPIEventQueueChain* queue = mEventQTable.GetWeak(currentThread); - if (queue) { - queue->StopAcceptingEvents(); // tell the queue to stop accepting events - queue = nsnull; // Queue may die on the next line - mEventQTable.Remove(currentThread); // remove nsIEventQueue from hash table (releases) - } - - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueServiceImpl::CreateFromPLEventQueue(PLEventQueue* aPLEventQueue, - nsIEventQueue** aResult) -{ - // Create our thread queue using the component manager - nsresult rv; - nsCOMPtr queue = do_CreateInstance(kEventQueueCID, &rv); - if (NS_FAILED(rv)) return rv; - - rv = queue->InitFromPLQueue(aPLEventQueue); - if (NS_FAILED(rv)) return rv; - - *aResult = queue; - NS_IF_ADDREF(*aResult); - return NS_OK; -} - - -// Return the active event queue on our chain -/* inline */ -nsresult nsEventQueueServiceImpl::GetYoungestEventQueue(nsIEventQueue *queue, nsIEventQueue **aResult) -{ - nsCOMPtr answer; - - if (queue) { - nsCOMPtr ourChain(do_QueryInterface(queue)); - if (ourChain) - ourChain->GetYoungestActive(getter_AddRefs(answer)); - else - answer = queue; - } - - *aResult = answer; - NS_IF_ADDREF(*aResult); - return NS_OK; -} - - -// create new event queue, append it to the current thread's chain of event queues. -// return it, addrefed. -NS_IMETHODIMP -nsEventQueueServiceImpl::PushThreadEventQueue(nsIEventQueue **aNewQueue) -{ - nsresult rv; - - PRThread* currentThread = PR_GetCurrentThread(); - PRBool native = PR_TRUE; // native by default as per old comment - - NS_ASSERTION(aNewQueue, "PushThreadEventQueue called with null param"); - - /* Enter the lock that protects the EventQ hashtable... */ - nsAutoMonitor mon(mEventQMonitor); - - nsPIEventQueueChain* queue = mEventQTable.GetWeak(currentThread); - - NS_ASSERTION(queue, "pushed event queue on top of nothing"); - - if (queue) { // find out what kind of queue our relatives are - nsCOMPtr youngQueue; - GetYoungestEventQueue(queue, getter_AddRefs(youngQueue)); - if (youngQueue) { - youngQueue->IsQueueNative(&native); - } - } - - nsPIEventQueueChain* newQueue = nsnull; - rv = MakeNewQueue(currentThread, native, &newQueue); // AddRefs on success - NS_ENSURE_SUCCESS(rv, rv); - - if (!queue) { - // shouldn't happen. as a fallback, we guess you wanted a native queue - mEventQTable.Put(currentThread, newQueue); - } - - // append the new queue to the event queue chain - queue->AppendQueue(newQueue); - - *aNewQueue = newQueue; - -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PLEventQueue *equeue; - (*aNewQueue)->GetPLEventQueue(&equeue); - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Service push queue [queue=%lx]",(long)equeue)); - ++gEventQueueLogCount; -#endif - - return NS_OK; -} - -// disable and release the given queue (though the last one won't be released) -NS_IMETHODIMP -nsEventQueueServiceImpl::PopThreadEventQueue(nsIEventQueue *aQueue) -{ - PRThread* currentThread = PR_GetCurrentThread(); - - nsCOMPtr eldestQueue; - - { - nsAutoMonitor mon(mEventQMonitor); - mEventQTable.Get(currentThread, getter_AddRefs(eldestQueue)); - - // If we are popping the eldest queue, remove its mEventQTable entry. - if (aQueue == eldestQueue) - mEventQTable.Remove(currentThread); - } - - // Exit the monitor before processing pending events to avoid deadlock. - // Our reference from the eldestQueue nsCOMPtr will keep that object alive. - // Since it is thread-private, no one else can race with us here. - if (!eldestQueue) - return NS_ERROR_FAILURE; - -#if defined(PR_LOGGING) && defined(DEBUG_danm) - PLEventQueue *equeue; - aQueue->GetPLEventQueue(&equeue); - PR_LOG(gEventQueueLog, PR_LOG_DEBUG, - ("EventQueue: Service pop queue [queue=%lx]",(long)equeue)); - ++gEventQueueLogCount; -#endif - aQueue->StopAcceptingEvents(); - aQueue->ProcessPendingEvents(); // make sure we don't orphan any events - - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueServiceImpl::GetThreadEventQueue(PRThread* aThread, nsIEventQueue** aResult) -{ - /* Parameter validation... */ - if (NULL == aResult) return NS_ERROR_NULL_POINTER; - - PRThread* keyThread = aThread; - - if (keyThread == NS_CURRENT_THREAD) - { - keyThread = PR_GetCurrentThread(); - } - else if (keyThread == NS_UI_THREAD) - { - nsCOMPtr mainIThread; - - // Get the primordial thread - nsresult rv = nsIThread::GetMainThread(getter_AddRefs(mainIThread)); - if (NS_FAILED(rv)) return rv; - - rv = mainIThread->GetPRThread(&keyThread); - if (NS_FAILED(rv)) return rv; - } - - nsCOMPtr queue; - - { - nsAutoMonitor mon(mEventQMonitor); - mEventQTable.Get(keyThread, getter_AddRefs(queue)); - } - - if (queue) { - GetYoungestEventQueue(queue, aResult); // get the youngest active queue - } else { - *aResult = nsnull; - } - // XXX: Need error code for requesting an event queue when none exists... - if (!*aResult) { - return NS_ERROR_NOT_AVAILABLE; - } - return NS_OK; -} - - -NS_IMETHODIMP -nsEventQueueServiceImpl::ResolveEventQueue(nsIEventQueue* queueOrConstant, nsIEventQueue* *resultQueue) -{ - if (queueOrConstant == NS_CURRENT_EVENTQ) { - return GetThreadEventQueue(NS_CURRENT_THREAD, resultQueue); - } - else if (queueOrConstant == NS_UI_THREAD_EVENTQ) { - return GetThreadEventQueue(NS_UI_THREAD, resultQueue); - } - - *resultQueue = queueOrConstant; - NS_ADDREF(*resultQueue); - return NS_OK; -} - -NS_IMETHODIMP -nsEventQueueServiceImpl::GetSpecialEventQueue(PRInt32 aQueue, - nsIEventQueue* *_retval) -{ - nsresult rv; - - // barf if someone gave us a zero pointer - // - if (!_retval) { - return NS_ERROR_NULL_POINTER; - } - - // try and get the requested event queue, returning NS_ERROR_FAILURE if there - // is a problem. GetThreadEventQueue() does the AddRef() for us. - // - switch (aQueue) { - case CURRENT_THREAD_EVENT_QUEUE: - rv = GetThreadEventQueue(NS_CURRENT_THREAD, _retval); - if (NS_FAILED(rv)) { - return NS_ERROR_FAILURE; - } - break; - - case UI_THREAD_EVENT_QUEUE: - rv = GetThreadEventQueue(NS_UI_THREAD, _retval); - if (NS_FAILED(rv)) { - return NS_ERROR_FAILURE; - } - break; - - // somebody handed us a bogus constant - // - default: - return NS_ERROR_ILLEGAL_VALUE; - } - - return NS_OK; -} - diff --git a/mozilla/xpcom/threads/nsEventQueueService.h b/mozilla/xpcom/threads/nsEventQueueService.h deleted file mode 100644 index 91422fd8a1e..00000000000 --- a/mozilla/xpcom/threads/nsEventQueueService.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsEventQueueService_h__ -#define nsEventQueueService_h__ - -#include "nsIEventQueueService.h" -#include "nsInterfaceHashtable.h" -#include "nsHashKeys.h" -#include "nsIEventQueue.h" -#include "nsPIEventQueueChain.h" - -//////////////////////////////////////////////////////////////////////////////// - -class nsEventQueueServiceImpl : public nsIEventQueueService -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_EVENTQUEUESERVICE_CID) - - nsEventQueueServiceImpl(); - - nsresult Init(); - - // During XPCOM shutdown: stop accepting events on all event queues - void Shutdown(); - - // nsISupports interface... - NS_DECL_ISUPPORTS - - // nsIEventQueueService interface... - NS_DECL_NSIEVENTQUEUESERVICE - -private: - ~nsEventQueueServiceImpl(); - - /* Create a queue for the given thread if one does not exist. - Addref the descriptor in any case. parameter aNative is - ignored if the queue already exists. */ - NS_IMETHOD CreateEventQueue(PRThread *aThread, PRBool aNative); - NS_IMETHOD MakeNewQueue(PRThread* thread, PRBool aNative, - nsPIEventQueueChain **aQueue); - inline nsresult GetYoungestEventQueue(nsIEventQueue *queue, - nsIEventQueue **aResult); - - nsInterfaceHashtable mEventQTable; - PRMonitor *mEventQMonitor; - PRBool mIsShuttingDown; -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsEventQueueServiceImpl, NS_EVENTQUEUESERVICE_CID) - -//////////////////////////////////////////////////////////////////////////////// - -#endif // nsEventQueueService_h__ diff --git a/mozilla/xpcom/threads/nsIEventQueue.idl b/mozilla/xpcom/threads/nsIEventQueue.idl deleted file mode 100644 index 5761c629546..00000000000 --- a/mozilla/xpcom/threads/nsIEventQueue.idl +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * David Hyatt - * Suresh Duddi - * Doug Turner - * Judson Valeski - * Dan Matejka - * Ray Whitmer - * Dan Mosedale - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsIEventTarget.idl" - -%{C++ -#include "prthread.h" - -// {13D86C61-00A9-11d3-9F2A-00400553EEF0} -#define NS_EVENTQUEUE_CID \ -{ 0x13d86c61, 0xa9, 0x11d3, { 0x9f, 0x2a, 0x0, 0x40, 0x5, 0x53, 0xee, 0xf0 } } - -#define NS_EVENTQUEUE_CONTRACTID "@mozilla.org/event-queue;1" -#define NS_EVENTQUEUE_CLASSNAME "Event Queue" - -%} - -// some forward decls -// -[ptr] native PLEventQueuePtr(PLEventQueue); -[ptr] native PRThreadPtr(PRThread); -native PRStatus(PRStatus); -[ref] native PRBoolRef(PRBool); -native PLHandleEventProc(PLHandleEventProc); -native PLDestroyEventProc(PLDestroyEventProc); - -[scriptable, uuid(176AFB41-00A4-11d3-9F2A-00400553EEF0)] -interface nsIEventQueue : nsIEventTarget -{ - [noscript] void initEvent(in PLEventPtr aEvent, - in voidPtr owner, - in PLHandleEventProc handler, - in PLDestroyEventProc destructor); - - [noscript] void postSynchronousEvent(in PLEventPtr aEvent, - out voidPtr aResult); - - boolean pendingEvents(); - void processPendingEvents(); - void eventLoop(); - - [noscript] void eventAvailable(in PRBoolRef aResult); - [noscript] PLEventPtr getEvent(); - [noscript] void handleEvent(in PLEventPtr aEvent); - [noscript] PLEventPtr waitForEvent(); - - [notxpcom] PRInt32 getEventQueueSelectFD(); - - void init(in boolean aNative); - [noscript] void initFromPRThread(in PRThreadPtr thread, - in boolean aNative); - [noscript] void initFromPLQueue(in PLEventQueuePtr aQueue); - - void enterMonitor(); - void exitMonitor(); - - /** - * Revoke events in this event queue and all other event queues - * for this thread that have |owner| as the event owner. - */ - [noscript] void revokeEvents(in voidPtr owner); - [noscript] PLEventQueuePtr getPLEventQueue(); - - boolean isQueueNative(); - - /** - * Stop accepting events on this queue. - */ - void stopAcceptingEvents(); -}; - diff --git a/mozilla/xpcom/threads/nsIEventQueueService.idl b/mozilla/xpcom/threads/nsIEventQueueService.idl deleted file mode 100644 index e9c93e8671b..00000000000 --- a/mozilla/xpcom/threads/nsIEventQueueService.idl +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Rick Potts - * David Matiskella - * David Hyatt - * Suresh Duddi - * Scott Collins - * Dan Matejka - * Doug Turner - * Ray Whitmer - * Dan Mosedale - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsISupports.idl" -#include "nsIEventQueue.idl" - -%{C++ -#include "prthread.h" -#include "plevent.h" - -/* be761f00-a3b0-11d2-996c-0080c7cb1080 */ -#define NS_EVENTQUEUESERVICE_CID \ -{ 0xbe761f00, 0xa3b0, 0x11d2, \ - {0x99, 0x6c, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x80} } - -#define NS_EVENTQUEUESERVICE_CONTRACTID "@mozilla.org/event-queue-service;1" -#define NS_EVENTQUEUESERVICE_CLASSNAME "Event Queue Service" - -#define NS_CURRENT_THREAD ((PRThread*)0) -#define NS_CURRENT_EVENTQ ((nsIEventQueue*)0) - -#define NS_UI_THREAD ((PRThread*)1) -#define NS_UI_THREAD_EVENTQ ((nsIEventQueue*)1) - -%} - -/* a forward decl */ -interface nsIThread; - -[scriptable, uuid(a6cf90dc-15b3-11d2-932e-00805f8add32)] -interface nsIEventQueueService : nsISupports -{ - /** - * Creates and holds a native event queue for the current thread. - * "Native" queues have an associated callback mechanism which is - * automatically triggered when an event is posted. See plevent.c for - * details. - * @return NS_OK on success, or a host of failure indications - */ - void createThreadEventQueue(); - - /** - * Creates and hold a monitored event queue for the current thread. - * "Monitored" queues have no callback processing mechanism. - * @return NS_OK on success, or a host of failure indications - */ - void createMonitoredThreadEventQueue(); - - /** - * Somewhat misnamed, this method releases the service's hold on the event - * queue(s) for this thread. Subsequent attempts to access this thread's - * queue (GetThreadEventQueue, for example) may fail, though the queue itself - * will be destroyed only after all references to it are released and the - * queue itself is no longer actively processing events. - * @return nonsense. - */ - void destroyThreadEventQueue(); - - nsIEventQueue createFromIThread(in nsIThread aThread, - in boolean aNative); - - [noscript] nsIEventQueue createFromPLEventQueue(in PLEventQueuePtr - aPLEventQueue); - - // Add a new event queue for the current thread, making it the "current" - // queue. Return that queue, addrefed. - nsIEventQueue pushThreadEventQueue(); - - // release and disable the queue - void popThreadEventQueue(in nsIEventQueue aQueue); - - [noscript] nsIEventQueue getThreadEventQueue(in PRThreadPtr aThread); - - /** - * @deprecated in favor of getSpecialEventQueue, since that's - * scriptable and this isn't. - * - * Check for any "magic" event queue constants (NS_CURRENT_EVENTQ, - * NS_UI_THREAD_EVENTQ) and return the real event queue that they - * represent, AddRef()ed. Otherwise, return the event queue passed - * in, AddRef()ed. This is not scriptable because the arguments in - * question may be magic constants rather than real nsIEventQueues. - * - * @arg queueOrConstant either a real event queue or a magic - * constant to be resolved - * - * @return a real event queue, AddRef()ed - */ - [noscript] nsIEventQueue resolveEventQueue(in nsIEventQueue queueOrConstant); - - /** - * Returns the appropriate special event queue, AddRef()ed. Really - * just a scriptable version of ResolveEventQueue. - * - * @arg aQueue Either CURRENT_THREAD_EVENT_QUEUE or - * UI_THREAD_EVENT_QUEUE - * @return The requested nsIEventQueue, AddRef()ed - * @exception NS_ERROR_NULL_POINTER Zero pointer passed in for return value - * @exception NS_ERROR_ILLEGAL_VALUE Bogus constant passed in aQueue - * @exception NS_ERROR_FAILURE Error while calling - * GetThreadEventQueue() - */ - nsIEventQueue getSpecialEventQueue(in long aQueue); - - const long CURRENT_THREAD_EVENT_QUEUE = 0; - const long UI_THREAD_EVENT_QUEUE = 1; - -}; diff --git a/mozilla/xpcom/threads/nsIEventTarget.idl b/mozilla/xpcom/threads/nsIEventTarget.idl index 3b19d9ca0a7..37999ac7228 100644 --- a/mozilla/xpcom/threads/nsIEventTarget.idl +++ b/mozilla/xpcom/threads/nsIEventTarget.idl @@ -1,3 +1,5 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -11,14 +13,14 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is Mozilla. + * The Original Code is Mozilla code. * - * The Initial Developer of the Original Code is IBM Corporation. - * Portions created by IBM Corporation are Copyright (C) 2003 - * IBM Corporation. All Rights Reserved. + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. * * Contributor(s): - * IBM Corp. + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -36,32 +38,56 @@ #include "nsISupports.idl" -%{C++ -#include "plevent.h" -%} +interface nsIRunnable; -[ptr] native PLEventPtr(PLEvent); - -/** - * nsIEventTarget - * - * This interface is used to dispatch events to a particular thread. In many - * cases the event target also supports nsIEventQueue. - */ -[scriptable, uuid(ea99ad5b-cc67-4efb-97c9-2ef620a59f2a)] +[scriptable, uuid(4e8febe4-6631-49dc-8ac9-308c1cb9b09c)] interface nsIEventTarget : nsISupports { - /** - * Method for posting an asynchronous event to the event target. If this - * method succeeds, then the event will be dispatched on the target thread. - * - * @param aEvent - * The event to dispatched. - */ - [noscript] void postEvent(in PLEventPtr aEvent); + /** + * Dispatch an event to this event target. This function may be called from + * any thread, and it may be called re-entrantly. + * + * @param event + * The event to dispatch. + * @param flags + * The flags modifying event dispatch. The flags are described in detail + * below. + * + * @throws NS_ERROR_INVALID_ARG + * Indicates that event is null. + */ + void dispatch(in nsIRunnable event, in unsigned long flags); - /** - * This method returns true if the event target is the current thread. - */ - boolean isOnCurrentThread(); + /** + * This flag specifies the default mode of event dispatch, whereby the event + * is simply queued for later processing. When this flag is specified, + * dispatch returns immediately after the event is queued. + */ + const unsigned long DISPATCH_NORMAL = 0; + + /** + * This flag specifies the synchronous mode of event dispatch, in which the + * dispatch method does not return until the event has been processed. + * + * NOTE: passing this flag to dispatch may have the side-effect of causing + * other events on the current thread to be processed while waiting for the + * given event to be processed. + */ + const unsigned long DISPATCH_SYNC = 1; + + /** + * Check to see if this event target is associated with the current thread. + * + * @returns + * A boolean value that if "true" indicates that events dispatched to this + * event target will run on the current thread (i.e., the thread calling + * this method). + */ + boolean isOnCurrentThread(); }; + +%{C++ +// convenient aliases: +#define NS_DISPATCH_NORMAL nsIEventTarget::DISPATCH_NORMAL +#define NS_DISPATCH_SYNC nsIEventTarget::DISPATCH_SYNC +%} diff --git a/mozilla/xpcom/threads/nsIThread.idl b/mozilla/xpcom/threads/nsIThread.idl index f28d6ec942b..8261f2d7b1f 100644 --- a/mozilla/xpcom/threads/nsIThread.idl +++ b/mozilla/xpcom/threads/nsIThread.idl @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -12,18 +13,18 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is mozilla.org code. + * The Original Code is Mozilla code. * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to @@ -35,110 +36,82 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsISupports.idl" - -%{C++ -#include "prthread.h" - -#define NS_THREAD_CID \ -{ /* 85CE5510-7808-11d3-A181-0050041CAF44 */ \ - 0x85ce5510, \ - 0x7808, \ - 0x11d3, \ - {0xa1, 0x81, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \ -} - -#define NS_THREAD_CONTRACTID "@mozilla.org/thread;1" -#define NS_THREAD_CLASSNAME "Thread" -#if 0 -%} - -typedef PRUint32 PRThreadPriority; -typedef PRUint32 PRThreadScope; -typedef PRUint32 PRThreadState; - -%{C++ -#endif -%} - -interface nsIRunnable; +#include "nsIEventTarget.idl" [ptr] native PRThread(PRThread); -[scriptable, uuid(6be5e380-6886-11d3-9382-00104ba0fd40)] -interface nsIThread : nsISupports +/** + * This interface provides a high-level abstraction for an operating system + * thread. + * + * Threads have a built-in event queue, and a thread is an event target that + * can receive nsIRunnable objects (events) to be processed on the thread. + * + * See nsIThreadManager for the API used to create and locate threads. + */ +[scriptable, uuid(9c889946-a73a-4af3-ae9a-ea64f7d4e3ca)] +interface nsIThread : nsIEventTarget { - // These must all match the values used in prthread.h - const PRUint32 PRIORITY_LOW = 0; - const PRUint32 PRIORITY_NORMAL = 1; - const PRUint32 PRIORITY_HIGH = 2; - const PRUint32 PRIORITY_URGENT = 3; + /** + * @returns + * The NSPR thread object corresponding to this nsIThread. + */ + [noscript] readonly attribute PRThread PRThread; - const PRUint32 SCOPE_LOCAL = 0; - const PRUint32 SCOPE_GLOBAL = 1; - const PRUint32 SCOPE_BOUND = 2; + /** + * Shutdown the thread. This method prevents further dispatch of events to + * the thread, and it causes any pending events to run to completion before + * the thread joins (see PR_JoinThread) with the current thread. During this + * method call, events for the current thread may be processed. + * + * This method MAY NOT be executed from the thread itself. Instead, it is + * meant to be executed from another thread (usually the thread that created + * this thread or the main application thread). When this function returns, + * the thread will be shutdown, and it will no longer be possible to dispatch + * events to the thread. + * + * @throws NS_ERROR_UNEXPECTED + * Indicates that this method was erroneously called when this thread was + * the current thread, that this thread was not created with a call to + * nsIThreadManager::NewThread, or if this method was called more than once + * on the thread object. + */ + void shutdown(); - const PRUint32 STATE_JOINABLE = 0; - const PRUint32 STATE_UNJOINABLE = 1; + /** + * This method may be called to determine if there are any events ready to be + * processed. It may only be called when this thread is the current thread. + * + * Because events may be added to this thread by another thread, a "false" + * result does not mean that this thread has no pending events. It only + * means that there were no pending events when this method was called. + * + * @returns + * A boolean value that if "true" indicates that this thread has one or + * more pending events. + * + * @throws NS_ERROR_UNEXPECTED + * Indicates that this method was erroneously called when this thread was + * not the current thread. + */ + boolean hasPendingEvents(); - void join(); - void interrupt(); - - attribute PRThreadPriority priority; - readonly attribute PRThreadScope scope; - readonly attribute PRThreadState state; - - [noscript] PRThread GetPRThread(); - - void init(in nsIRunnable aRunnable, - in PRUint32 aStackSize, - in PRThreadPriority aPriority, - in PRThreadScope aScope, - in PRThreadState aState); - - /* - * Get the currently running thread (really a static method sort of thing). - */ - readonly attribute nsIThread currentThread; - - /* - * Sleep to at least this many milliseconds (only works on currrent thread). - */ - void sleep(in PRUint32 msec); - -%{C++ - // returns the nsIThread for the current thread: - static NS_COM nsresult GetCurrent(nsIThread* *result); - - // returns the nsIThread for an arbitrary PRThread: - static NS_COM nsresult GetIThread(PRThread* prthread, nsIThread* *result); - - // initializes the "main" thread (really, just saves the current thread - // at time of calling. meant to be called once at app startup, in lieu - // of proper static initializers, to save the primordial thread - // for later recall.) - static NS_COM nsresult SetMainThread(); - - // return the "main" thread - static NS_COM nsresult GetMainThread(nsIThread **result); - - static NS_COM PRBool IsMainThread(); -%} + /** + * Process the next event. If there are no pending events, then this method + * may wait -- depending on the value of the mayWait parameter -- until an + * event is dispatched to this thread. This method is re-entrant but may + * only be called if this thread is the current thread. + * + * @param mayWait + * A boolean parameter that if "true" indicates that the method may block + * the calling thread to wait for a pending event. + * + * @returns + * A boolean value that if "true" indicates that an event was processed. + * + * @throws NS_ERROR_UNEXPECTED + * Indicates that this method was erroneously called when this thread was + * not the current thread. + */ + boolean processNextEvent(in boolean mayWait); }; - -%{C++ -extern NS_COM nsresult -NS_NewThread(nsIThread* *result, - nsIRunnable* runnable, - PRUint32 stackSize = 0, - PRThreadState state = PR_UNJOINABLE_THREAD, - PRThreadPriority priority = PR_PRIORITY_NORMAL, - PRThreadScope scope = PR_GLOBAL_THREAD); - -extern NS_COM nsresult -NS_NewThread(nsIThread* *result, - PRUint32 stackSize = 0, - PRThreadState state = PR_UNJOINABLE_THREAD, - PRThreadPriority priority = PR_PRIORITY_NORMAL, - PRThreadScope scope = PR_GLOBAL_THREAD); -%} diff --git a/mozilla/xpcom/threads/nsIThreadInternal.idl b/mozilla/xpcom/threads/nsIThreadInternal.idl new file mode 100644 index 00000000000..7e84dcc2477 --- /dev/null +++ b/mozilla/xpcom/threads/nsIThreadInternal.idl @@ -0,0 +1,149 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIThread.idl" + +interface nsIThreadObserver; +interface nsIThreadEventFilter; + +/** + * The XPCOM thread object implements this interface, which allows a consumer + * to observe dispatch activity on the thread. + */ +[scriptable, uuid(f89b5063-b06d-42f8-bf23-4dfcf2d80d6a)] +interface nsIThreadInternal : nsIThread +{ + /** + * Get/set the current thread observer (may be null). This attribute may be + * read from any thread, but must only be set on the thread corresponding to + * this thread object. + */ + attribute nsIThreadObserver observer; + + /** + * This method causes any events currently enqueued on the thread to be + * suppressed until PopEventQueue is called. Additionally, any new events + * dispatched to the thread will only be processed if they are accepted by + * the given filter. If the filter is null, then new events are accepted. + * Calls to PushEventQueue may be nested and must each be paired with a call + * to PopEventQueue in order to restore the original state of the thread. + * + * @param filter + * The thread event filter to apply to dispatched events, or null to accept + * all dispatched events. + */ + void pushEventQueue(in nsIThreadEventFilter filter); + + /** + * Revert a call to PushEventQueue. When an event queue is popped, any + * events remaining in the queue are appended to the elder queue. + */ + void popEventQueue(); +}; + +/** + * This interface provides the observer with hooks to implement a layered + * event queue. For example, it is possible to overlay processing events + * for a GUI toolkit on top of the events for a thread: + * + * var NativeQueue; + * Observer = { + * onDispatchedEvent(thread) { + * NativeQueue.signal(); + * } + * onProcessNextEvent(thread, mayWait, recursionDepth) { + * if (NativeQueue.hasNextEvent()) + * NativeQueue.processNextEvent(); + * while (mayWait && !thread.hasPendingEvent()) { + * NativeQueue.wait(); + * NativeQueue.processNextEvent(); + * } + * } + * }; + * + * NOTE: The implementation of this interface must be threadsafe. + * + * NOTE: It is valid to change the thread's observer during a call to an + * observer method. + */ +[scriptable, uuid(719d2fb9-54ce-4847-b15b-fa9960e22f9f)] +interface nsIThreadObserver : nsISupports +{ + /** + * This method is called after an event has been dispatched to the thread. + * This method may be called from any thread. + * + * @param thread + * The thread where the event is being dispatched. + */ + void onDispatchedEvent(in nsIThreadInternal thread); + + /** + * This method is called (from nsIThread::ProcessNextEvent) before an event + * is processed. This method is only called on the target thread. + * + * @param thread + * The thread being asked to process another event. + * @param mayWait + * Indicates whether or not the method is allowed to block the calling + * thread. For example, this parameter is false during thread shutdown. + * @param recursionDepth + * Indicates the number of calls to ProcessNextEvent on the call stack in + * addition to the current call. + */ + void onProcessNextEvent(in nsIThreadInternal thread, in boolean mayWait, + in unsigned long recursionDepth); +}; + +/** + * Interface passed to the nsIThreadInternal::PushEventQueue method. + */ +[scriptable, uuid(a0605c0b-17f5-4681-b8cd-a1cd75d42559)] +interface nsIThreadEventFilter : nsISupports +{ + /** + * This method is called to determine whether or not an event may be accepted + * by a "nested" event queue (see nsIThreadInternal::PushEventQueue). + * + * @param event + * The event being dispatched. + * + * WARNING: This method must not make any calls on the thread object. + */ + [notxpcom] boolean acceptEvent(in nsIRunnable event); +}; diff --git a/mozilla/xpcom/threads/nsIThreadManager.idl b/mozilla/xpcom/threads/nsIThreadManager.idl new file mode 100644 index 00000000000..1e4bcfa6547 --- /dev/null +++ b/mozilla/xpcom/threads/nsIThreadManager.idl @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +[ptr] native PRThread(PRThread); + +interface nsIThread; + +/** + * An interface for creating and locating nsIThread instances. + */ +[scriptable, uuid(056216f5-8803-46b4-9199-d95bc1f0446f)] +interface nsIThreadManager : nsISupports +{ + /** + * Create a new thread (a global, user PRThread). + * + * @param creationFlags + * Reserved for future use. Pass 0. + * + * @returns + * The newly created nsIThread object. + */ + nsIThread newThread(in unsigned long creationFlags); + + /** + * Get the nsIThread object (if any) corresponding to the given PRThread. + * This method returns null if there is no corresponding nsIThread. + * + * @param prthread + * The PRThread of the nsIThread being requested. + * + * @returns + * The nsIThread object corresponding to the given PRThread or null if no + * such nsIThread exists. + */ + [noscript] nsIThread getThreadFromPRThread(in PRThread prthread); + + /** + * Get the main thread. + */ + readonly attribute nsIThread mainThread; + + /** + * Get the current thread. If the calling thread does not already have a + * nsIThread associated with it, then a new nsIThread will be created and + * associated with the current PRThread. + */ + readonly attribute nsIThread currentThread; + + /** + * This attribute is true if the calling thread is the main thread of the + * application process. + */ + readonly attribute boolean isMainThread; +}; diff --git a/mozilla/xpcom/threads/nsIThreadPool.idl b/mozilla/xpcom/threads/nsIThreadPool.idl new file mode 100644 index 00000000000..e0fc0ce086f --- /dev/null +++ b/mozilla/xpcom/threads/nsIThreadPool.idl @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIEventTarget.idl" + +/** + * An interface to a thread pool. A thread pool creates a limited number of + * anonymous (unnamed) worker threads. An event dispatched to the thread pool + * will be run on the next available worker thread. + */ +[scriptable, uuid(394c29f0-225f-487f-86d3-4c259da76cab)] +interface nsIThreadPool : nsIEventTarget +{ + /** + * Shutdown the thread pool. This method may not be executed from any thread + * in the thread pool. Instead, it is meant to be executed from another + * thread (usually the thread that created this thread pool). When this + * function returns, the thread pool and all of its threads will be shutdown, + * and it will no longer be possible to dispatch tasks to the thread pool. + */ + void shutdown(); + + /** + * Get/set the maximum number of threads allowed at one time in this pool. + */ + attribute unsigned long threadLimit; + + /** + * Get/set the maximum number of idle threads kept alive. + */ + attribute unsigned long idleThreadLimit; + + /** + * Get/set the amount of time in milliseconds before an idle thread is + * destroyed. + */ + attribute unsigned long idleThreadTimeout; +}; diff --git a/mozilla/xpcom/threads/nsPIEventQueueChain.h b/mozilla/xpcom/threads/nsPIEventQueueChain.h index 7f84e3cc1ee..e69de29bb2d 100644 --- a/mozilla/xpcom/threads/nsPIEventQueueChain.h +++ b/mozilla/xpcom/threads/nsPIEventQueueChain.h @@ -1,104 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsPIEventQueueChain_h__ -#define nsPIEventQueueChain_h__ - -#include "nsISupports.h" - -// {6a418ae8-db08-495d-843a-0822ebdc9d10} -#define NS_IEVENTQUEUECHAIN_IID \ -{ 0x6a418ae8, 0xdb08, 0x495d, { 0x84, 0x3a, 0x08, 0x22, 0xeb, 0xdc, 0x9d, 0x10 } } - -class nsIEventQueue; - -class nsPIEventQueueChain : public nsIEventQueue -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_IEVENTQUEUECHAIN_IID) - - /** - * Add the given queue as the new youngest member of our chain. - * It will not be addrefed. - * @param aQueue the queue. must not be null. - * @return error indication - */ - NS_IMETHOD AppendQueue(nsIEventQueue *aQueue) = 0; - - /** - * Remove this element from the chain. - * @return NS_OK - */ - NS_IMETHOD Unlink() = 0; - - /** - * Fetch (and addref) the youngest member of the chain. - * @param *aQueue the youngest queue. aQueue must not be null. - * @return error indication - */ - NS_IMETHOD GetYoungest(nsIEventQueue **aQueue) = 0; - - /** - * Fetch (and addref) the youngest member of the chain which is - * still accepting events. Note that there may be still younger - * queues which still contain events in need of processing but - * have already stopped accepting new events. - * - * @param *aQueue the youngest such queue. aQueue must not be null. - * *aQueue will be returned null, if no such queue is found. - * @return error indication -- can be NS_OK even if *aQueue is 0 - */ - NS_IMETHOD GetYoungestActive(nsIEventQueue **aQueue) = 0; - - NS_IMETHOD SetYounger(nsPIEventQueueChain *aQueue) = 0; - NS_IMETHOD GetYounger(nsIEventQueue **aQueue) = 0; - - NS_IMETHOD SetElder(nsPIEventQueueChain *aQueue) = 0; - NS_IMETHOD GetElder(nsIEventQueue **aQueue) = 0; - - /** - * Revoke events for aOwner in this queue and all elder queues. This - * differs in behavior from nsIEventQueue::RevokeEvents in that that - * method revokes events in younger queues too. - */ - NS_IMETHOD RevokeEventsInternal(void* aOwner) = 0; -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsPIEventQueueChain, NS_IEVENTQUEUECHAIN_IID) - -#endif /* nsPIEventQueueChain_h___ */ - diff --git a/mozilla/xpcom/threads/nsThread.cpp b/mozilla/xpcom/threads/nsThread.cpp index 46c923d9298..7f4948f8923 100644 --- a/mozilla/xpcom/threads/nsThread.cpp +++ b/mozilla/xpcom/threads/nsThread.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -12,18 +13,18 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is mozilla.org code. + * The Original Code is Mozilla code. * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to @@ -36,450 +37,575 @@ * ***** END LICENSE BLOCK ***** */ #include "nsThread.h" -#include "prmem.h" -#include "prlog.h" +#include "nsThreadManager.h" +#include "nsIClassInfoImpl.h" +#include "nsIProgrammingLanguage.h" #include "nsAutoLock.h" +#include "nsAutoPtr.h" +#include "nsCOMPtr.h" +#include "prlog.h" -PRUintn nsThread::kIThreadSelfIndex = 0; -static nsIThread *gMainThread = 0; +#ifdef PR_LOGGING +static PRLogModuleInfo *sLog = PR_NewLogModule("nsThread"); +#endif +#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args) -#if defined(PR_LOGGING) -// -// Log module for nsIThread logging... -// -// To enable logging (see prlog.h for full details): -// -// set NSPR_LOG_MODULES=nsIThread:5 -// set NSPR_LOG_FILE=nspr.log -// -// this enables PR_LOG_DEBUG level information and places all output in -// the file nspr.log -// -// gSocketLog is defined in nsSocketTransport.cpp -// -PRLogModuleInfo* nsIThreadLog = nsnull; +NS_DECL_CI_INTERFACE_GETTER(nsThread) -#endif /* PR_LOGGING */ +//----------------------------------------------------------------------------- +// Because we do not have our own nsIFactory, we have to implement nsIClassInfo +// somewhat manually. -//////////////////////////////////////////////////////////////////////////////// +class nsThreadClassInfo : public nsIClassInfo { +public: + NS_DECL_ISUPPORTS_INHERITED // no mRefCnt + NS_DECL_NSICLASSINFO + + nsThreadClassInfo() {} +}; + +static nsThreadClassInfo sThreadClassInfo; + +NS_IMETHODIMP_(nsrefcnt) nsThreadClassInfo::AddRef() { return 2; } +NS_IMETHODIMP_(nsrefcnt) nsThreadClassInfo::Release() { return 1; } +NS_IMPL_QUERY_INTERFACE1(nsThreadClassInfo, nsIClassInfo) + +NS_IMETHODIMP +nsThreadClassInfo::GetInterfaces(PRUint32 *count, nsIID ***array) +{ + return NS_CI_INTERFACE_GETTER_NAME(nsThread)(count, array); +} + +NS_IMETHODIMP +nsThreadClassInfo::GetHelperForLanguage(PRUint32 lang, nsISupports **result) +{ + *result = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsThreadClassInfo::GetContractID(char **result) +{ + *result = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsThreadClassInfo::GetClassDescription(char **result) +{ + *result = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsThreadClassInfo::GetClassID(nsCID **result) +{ + *result = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsThreadClassInfo::GetImplementationLanguage(PRUint32 *result) +{ + *result = nsIProgrammingLanguage::CPLUSPLUS; + return NS_OK; +} + +NS_IMETHODIMP +nsThreadClassInfo::GetFlags(PRUint32 *result) +{ + *result = THREADSAFE; + return NS_OK; +} + +NS_IMETHODIMP +nsThreadClassInfo::GetClassIDNoAlloc(nsCID *result) +{ + return NS_ERROR_NOT_AVAILABLE; +} + +//----------------------------------------------------------------------------- + +NS_IMPL_THREADSAFE_ADDREF(nsThread) +NS_IMPL_THREADSAFE_RELEASE(nsThread) +NS_INTERFACE_MAP_BEGIN(nsThread) + NS_INTERFACE_MAP_ENTRY(nsIThread) + NS_INTERFACE_MAP_ENTRY(nsIThreadInternal) + NS_INTERFACE_MAP_ENTRY(nsIEventTarget) + NS_INTERFACE_MAP_ENTRY(nsISupportsPriority) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIThread) + if (aIID.Equals(NS_GET_IID(nsIClassInfo))) { + foundInterface = NS_STATIC_CAST(nsIClassInfo*, &sThreadClassInfo); + } else +NS_INTERFACE_MAP_END +NS_IMPL_CI_INTERFACE_GETTER4(nsThread, nsIThread, nsIThreadInternal, + nsIEventTarget, nsISupportsPriority) + +//----------------------------------------------------------------------------- + +class nsThreadStartupEvent : public nsRunnable { +public: + // Create a new thread startup object. + static nsThreadStartupEvent *Create() { + nsThreadStartupEvent *startup = new nsThreadStartupEvent(); + if (startup && startup->mMon) + return startup; + // Allocation failure + delete startup; + return nsnull; + } + + // This method does not return until the thread startup object is in the + // completion state. + void Wait() { + if (mInitialized) // Maybe avoid locking... + return; + nsAutoMonitor mon(mMon); + while (!mInitialized) + mon.Wait(); + } + +private: + NS_IMETHOD Run() { + nsAutoMonitor mon(mMon); + mInitialized = PR_TRUE; + mon.Notify(); + return NS_OK; + } + + nsThreadStartupEvent() + : mMon(nsAutoMonitor::NewMonitor("xpcom.threadstartup")) + , mInitialized(PR_FALSE) { + } + + virtual ~nsThreadStartupEvent() { + if (mMon) + nsAutoMonitor::DestroyMonitor(mMon); + } + + PRMonitor *mMon; + PRBool mInitialized; +}; + +//----------------------------------------------------------------------------- + +struct nsThreadShutdownContext { + nsThread *joiningThread; + PRBool shutdownAck; +}; + +// This event is responsible for notifying nsThread::Shutdown that it is time +// to call PR_JoinThread. +class nsThreadShutdownAckEvent : public nsRunnable { +public: + nsThreadShutdownAckEvent(nsThreadShutdownContext *ctx) + : mShutdownContext(ctx) { + } + NS_IMETHOD Run() { + mShutdownContext->shutdownAck = PR_TRUE; + return NS_OK; + } +private: + nsThreadShutdownContext *mShutdownContext; +}; + +// This event is responsible for setting mShutdownContext +class nsThreadShutdownEvent : public nsRunnable { +public: + nsThreadShutdownEvent(nsThread *thr, nsThreadShutdownContext *ctx) + : mThread(thr), mShutdownContext(ctx) { + } + NS_IMETHOD Run() { + mThread->mShutdownContext = mShutdownContext; + return NS_OK; + } +private: + nsRefPtr mThread; + nsThreadShutdownContext *mShutdownContext; +}; + +//----------------------------------------------------------------------------- + +/*static*/ void +nsThread::ThreadFunc(void *arg) +{ + nsThread *self = NS_STATIC_CAST(nsThread *, arg); // strong reference + self->mThread = PR_GetCurrentThread(); + + // Inform the ThreadManager + nsThreadManager::get()->RegisterCurrentThread(self); + + // Wait for and process startup event + nsCOMPtr event; + if (!self->GetEvent(PR_TRUE, getter_AddRefs(event))) { + NS_WARNING("failed waiting for thread startup event"); + return; + } + event->Run(); // unblocks nsThread::Init + event = nsnull; + + // Now, process incoming events... + while (!self->ShuttingDown()) + NS_ProcessNextEvent(self); + + NS_ProcessPendingEvents(self); + + // Inform the threadmanager that this thread is going away + nsThreadManager::get()->UnregisterCurrentThread(self); + + // Dispatch shutdown ACK + event = new nsThreadShutdownAckEvent(self->mShutdownContext); + self->mShutdownContext->joiningThread->Dispatch(event, NS_DISPATCH_NORMAL); + + NS_RELEASE(self); +} + +//----------------------------------------------------------------------------- nsThread::nsThread() - : mThread(nsnull), mDead(PR_FALSE), mStartLock(nsnull) + : mLock(PR_NewLock()) + , mEvents(&mEventsRoot) + , mPriority(PRIORITY_NORMAL) + , mThread(nsnull) + , mRunningEvent(0) + , mShutdownContext(nsnull) + , mShutdownRequired(PR_FALSE) { -#if defined(PR_LOGGING) - // - // Initialize the global PRLogModule for nsIThread logging - // if necessary... - // - if (nsIThreadLog == nsnull) { - nsIThreadLog = PR_NewLogModule("nsIThread"); - } -#endif /* PR_LOGGING */ - - // enforce matching of constants to enums in prthread.h - NS_ASSERTION(int(nsIThread::PRIORITY_LOW) == int(PR_PRIORITY_LOW) && - int(nsIThread::PRIORITY_NORMAL) == int(PRIORITY_NORMAL) && - int(nsIThread::PRIORITY_HIGH) == int(PRIORITY_HIGH) && - int(nsIThread::PRIORITY_URGENT) == int(PRIORITY_URGENT) && - int(nsIThread::SCOPE_LOCAL) == int(PR_LOCAL_THREAD) && - int(nsIThread::SCOPE_GLOBAL) == int(PR_GLOBAL_THREAD) && - int(nsIThread::STATE_JOINABLE) == int(PR_JOINABLE_THREAD) && - int(nsIThread::STATE_UNJOINABLE) == int(PR_UNJOINABLE_THREAD), - "Bad constant in nsIThread!"); } nsThread::~nsThread() { - if (mStartLock) - PR_DestroyLock(mStartLock); - - PR_LOG(nsIThreadLog, PR_LOG_DEBUG, - ("nsIThread %p destroyed\n", this)); - - // This code used to free the nsIThreadLog loginfo stuff - // Don't do that; loginfo structures are owned by nspr - // and would be freed if we ever called PR_Cleanup() - // see bug 142072 + if (mLock) + PR_DestroyLock(mLock); } -void -nsThread::Main(void* arg) -{ - nsThread* self = (nsThread*)arg; - - self->WaitUntilReadyToStartMain(); - - nsresult rv = NS_OK; - rv = self->RegisterThreadSelf(); - NS_ASSERTION(rv == NS_OK, "failed to set thread self"); - - PR_LOG(nsIThreadLog, PR_LOG_DEBUG, - ("nsIThread %p start run %p\n", self, self->mRunnable.get())); - rv = self->mRunnable->Run(); - NS_ASSERTION(NS_SUCCEEDED(rv), "runnable failed"); - -#ifdef DEBUG - // Because a thread can die after gMainThread dies and takes nsIThreadLog with it, - // we need to check for it being null so that we don't crash on shutdown. - if (nsIThreadLog) { - PRThreadState state; - rv = self->GetState(&state); - PR_LOG(nsIThreadLog, PR_LOG_DEBUG, - ("nsIThread %p end run %p\n", self, self->mRunnable.get())); - } -#endif - - // explicitly drop the runnable now in case there are circular references - // between it and the thread object - self->mRunnable = nsnull; -} - -void -nsThread::Exit(void* arg) -{ - nsThread* self = (nsThread*)arg; - - if (self->mDead) { - NS_ERROR("attempt to Exit() thread twice"); - return; - } - - self->mDead = PR_TRUE; - -#if defined(PR_LOGGING) - if (nsIThreadLog) { - PR_LOG(nsIThreadLog, PR_LOG_DEBUG, - ("nsIThread %p exited\n", self)); - } -#endif - NS_RELEASE(self); -} - -NS_METHOD -nsThread::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) -{ - nsThread* thread = new nsThread(); - if (!thread) return NS_ERROR_OUT_OF_MEMORY; - nsresult rv = thread->QueryInterface(aIID, aResult); - if (NS_FAILED(rv)) delete thread; - return rv; -} - -NS_IMPL_THREADSAFE_ISUPPORTS1(nsThread, nsIThread) - -NS_IMETHODIMP -nsThread::Join() -{ - // don't check for mDead here because nspr calls Exit (cleaning up - // thread-local storage) before they let us join with the thread - - PR_LOG(nsIThreadLog, PR_LOG_DEBUG, - ("nsIThread %p start join\n", this)); - if (!mThread) - return NS_ERROR_NOT_INITIALIZED; - PRStatus status = PR_JoinThread(mThread); - // XXX can't use NS_RELEASE here because the macro wants to set - // this to null (bad c++) - PR_LOG(nsIThreadLog, PR_LOG_DEBUG, - ("nsIThread %p end join\n", this)); - if (status != PR_SUCCESS) - return NS_ERROR_FAILURE; - - NS_RELEASE_THIS(); // most likely the final release of this thread - return NS_OK; -} - -NS_IMETHODIMP -nsThread::GetPriority(PRThreadPriority *result) -{ - if (mDead) - return NS_ERROR_FAILURE; - if (!mThread) - return NS_ERROR_NOT_INITIALIZED; - *result = PR_GetThreadPriority(mThread); - return NS_OK; -} - -NS_IMETHODIMP -nsThread::SetPriority(PRThreadPriority value) -{ - if (mDead) - return NS_ERROR_FAILURE; - if (!mThread) - return NS_ERROR_NOT_INITIALIZED; - PR_SetThreadPriority(mThread, value); - return NS_OK; -} - -NS_IMETHODIMP -nsThread::Interrupt() -{ - if (mDead) - return NS_ERROR_FAILURE; - if (!mThread) - return NS_ERROR_NOT_INITIALIZED; - PRStatus status = PR_Interrupt(mThread); - return status == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -nsThread::GetScope(PRThreadScope *result) -{ - if (mDead) - return NS_ERROR_FAILURE; - if (!mThread) - return NS_ERROR_NOT_INITIALIZED; - *result = PR_GetThreadScope(mThread); - return NS_OK; -} - -NS_IMETHODIMP -nsThread::GetState(PRThreadState *result) -{ - if (mDead) - return NS_ERROR_FAILURE; - if (!mThread) - return NS_ERROR_NOT_INITIALIZED; - *result = PR_GetThreadState(mThread); - return NS_OK; -} - -NS_IMETHODIMP -nsThread::GetPRThread(PRThread* *result) -{ - if (mDead) { - *result = nsnull; - return NS_ERROR_FAILURE; - } - *result = mThread; - return NS_OK; -} - -NS_IMETHODIMP -nsThread::Init(nsIRunnable* runnable, - PRUint32 stackSize, - PRThreadPriority priority, - PRThreadScope scope, - PRThreadState state) -{ - NS_ENSURE_ARG_POINTER(runnable); - if (mRunnable) - return NS_ERROR_ALREADY_INITIALIZED; - - mRunnable = runnable; - - if (mStartLock) - return NS_ERROR_ALREADY_INITIALIZED; - - mStartLock = PR_NewLock(); - if (mStartLock == nsnull) { - mRunnable = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } - - NS_ADDREF_THIS(); // released in nsThread::Exit - if (state == PR_JOINABLE_THREAD) - NS_ADDREF_THIS(); // released in nsThread::Join - - PR_Lock(mStartLock); - mDead = PR_FALSE; - mThread = PR_CreateThread(PR_USER_THREAD, Main, this, - priority, scope, state, stackSize); - /* As soon as we PR_Unlock(mStartLock), if mThread was successfully - * created, it could run and exit very quickly. In which case, it - * would null mThread and therefore if we check if (mThread) we could - * confuse a successfully created, yet already exited thread with - * OOM - failure to create the thread. So instead we store a local thr - * which we check to see if we really failed to create the thread. - */ - PRThread *thr = mThread; - PR_Unlock(mStartLock); - - if (thr == nsnull) { - mDead = PR_TRUE; // otherwise cleared in nsThread::Exit - mRunnable = nsnull; // otherwise cleared in nsThread::Main(when done) - PR_DestroyLock(mStartLock); - mStartLock = nsnull; - NS_RELEASE_THIS(); // otherwise released in nsThread::Exit - if (state == PR_JOINABLE_THREAD) - NS_RELEASE_THIS(); // otherwise released in nsThread::Join - return NS_ERROR_OUT_OF_MEMORY; - } - - PR_LOG(nsIThreadLog, PR_LOG_DEBUG, - ("nsIThread %p created\n", this)); - - return NS_OK; -} - -/* readonly attribute nsIThread currentThread; */ -NS_IMETHODIMP -nsThread::GetCurrentThread(nsIThread * *aCurrentThread) -{ - return GetIThread(PR_GetCurrentThread(), aCurrentThread); -} - -/* void sleep (in PRUint32 msec); */ -NS_IMETHODIMP -nsThread::Sleep(PRUint32 msec) -{ - if (PR_GetCurrentThread() != mThread) - return NS_ERROR_FAILURE; - - if (PR_Sleep(PR_MillisecondsToInterval(msec)) != PR_SUCCESS) - return NS_ERROR_FAILURE; - - return NS_OK; -} - -NS_COM nsresult -NS_NewThread(nsIThread* *result, - nsIRunnable* runnable, - PRUint32 stackSize, - PRThreadState state, - PRThreadPriority priority, - PRThreadScope scope) -{ - nsresult rv; - nsThread* thread = new nsThread(); - if (thread == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(thread); - - rv = thread->Init(runnable, stackSize, priority, scope, state); - if (NS_FAILED(rv)) { - NS_RELEASE(thread); - return rv; - } - - *result = thread; - return NS_OK; -} - -NS_COM nsresult -NS_NewThread(nsIThread* *result, - PRUint32 stackSize, - PRThreadState state, - PRThreadPriority priority, - PRThreadScope scope) -{ - nsThread* thread = new nsThread(); - if (thread == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(thread); - *result = thread; - return NS_OK; -} - -//////////////////////////////////////////////////////////////////////////////// - nsresult -nsThread::RegisterThreadSelf() +nsThread::Init() { - PRStatus status; + NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY); - if (kIThreadSelfIndex == 0) { - status = PR_NewThreadPrivateIndex(&kIThreadSelfIndex, Exit); - if (status != PR_SUCCESS) return NS_ERROR_FAILURE; - } + // spawn thread and wait until it is fully setup + nsRefPtr startup = nsThreadStartupEvent::Create(); + NS_ENSURE_TRUE(startup, NS_ERROR_OUT_OF_MEMORY); + + NS_ADDREF_THIS(); + + mShutdownRequired = PR_TRUE; - status = PR_SetThreadPrivate(kIThreadSelfIndex, this); - if (status != PR_SUCCESS) return NS_ERROR_FAILURE; + // ThreadFunc is responsible for setting mThread + PRThread *thr = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this, + PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, + PR_JOINABLE_THREAD, 0); + if (!thr) { + NS_RELEASE_THIS(); + return NS_ERROR_OUT_OF_MEMORY; + } - return NS_OK; + // ThreadFunc will wait for this event to be run before it tries to access + // mThread. By delaying insertion of this event into the queue, we ensure + // that mThread is set properly. + { + nsAutoLock lock(mLock); + mEvents->PutEvent(startup); + } + + // Wait for thread to call ThreadManager::SetupCurrentThread, which completes + // initialization of ThreadFunc. + startup->Wait(); + return NS_OK; } -void -nsThread::WaitUntilReadyToStartMain() +nsresult +nsThread::InitCurrentThread() { - PR_Lock(mStartLock); - PR_Unlock(mStartLock); - PR_DestroyLock(mStartLock); - mStartLock = nsnull; + NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY); + + mThread = PR_GetCurrentThread(); + + nsThreadManager::get()->RegisterCurrentThread(this); + return NS_OK; } -NS_COM nsresult -nsIThread::GetCurrent(nsIThread* *result) +PRBool +nsThread::PutEvent(nsIRunnable *event) { - return GetIThread(PR_GetCurrentThread(), result); + PRBool rv; + { + nsAutoLock lock(mLock); + rv = mEvents->PutEvent(event); + } + if (!rv) + return PR_FALSE; + + nsCOMPtr obs = GetObserver(); + if (obs) + obs->OnDispatchedEvent(this); + + return PR_TRUE; } -NS_COM nsresult -nsIThread::GetIThread(PRThread* prthread, nsIThread* *result) +//----------------------------------------------------------------------------- +// nsIEventTarget + +NS_IMETHODIMP +nsThread::Dispatch(nsIRunnable *event, PRUint32 flags) { - PRStatus status; - nsThread* thread; + LOG(("THRD(%p) Dispatch [%p %x]\n", this, event, flags)); - if (nsThread::kIThreadSelfIndex == 0) { - status = PR_NewThreadPrivateIndex(&nsThread::kIThreadSelfIndex, nsThread::Exit); - if (status != PR_SUCCESS) return NS_ERROR_FAILURE; - } + NS_ENSURE_ARG_POINTER(event); - thread = (nsThread*)PR_GetThreadPrivate(nsThread::kIThreadSelfIndex); - if (thread == nsnull) { - // if the current thread doesn't have an nsIThread associated - // with it, make one - thread = new nsThread(); - if (thread == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(thread); // released by Exit - thread->SetPRThread(prthread); - nsresult rv = thread->RegisterThreadSelf(); - if (NS_FAILED(rv)) return rv; - } - NS_ADDREF(thread); - *result = thread; - return NS_OK; + PRBool dispatched; + if (flags & DISPATCH_SYNC) { + nsThread *thread = nsThreadManager::get()->GetCurrentThread(); + NS_ENSURE_STATE(thread); + + // XXX we should be able to do something better here... we should + // be able to monitor the slot occupied by this event and use + // that to tell us when the event has been processed. + + nsRefPtr wrapper = + new nsThreadSyncDispatch(thread, event); + if (!wrapper) + return NS_ERROR_OUT_OF_MEMORY; + dispatched = PutEvent(wrapper); + + while (wrapper->IsPending()) + NS_ProcessNextEvent(thread); + } else { + NS_ASSERTION(flags == NS_DISPATCH_NORMAL, "unexpected dispatch flags"); + dispatched = PutEvent(event); + } + + if (NS_UNLIKELY(!dispatched)) + return NS_ERROR_OUT_OF_MEMORY; + + return NS_OK; } -NS_COM nsresult -nsIThread::SetMainThread() +NS_IMETHODIMP +nsThread::IsOnCurrentThread(PRBool *result) { - // strictly speaking, it could be set twice. but practically speaking, - // it's almost certainly an error if it is - if (gMainThread != 0) { - NS_ERROR("Setting main thread twice?"); - return NS_ERROR_FAILURE; - } - return GetCurrent(&gMainThread); + *result = (PR_GetCurrentThread() == mThread); + return NS_OK; } -NS_COM nsresult -nsIThread::GetMainThread(nsIThread **result) +//----------------------------------------------------------------------------- +// nsIThread + +NS_IMETHODIMP +nsThread::GetPRThread(PRThread **result) { - NS_ASSERTION(result, "bad result pointer"); - if (gMainThread == 0) - return NS_ERROR_FAILURE; - *result = gMainThread; - NS_ADDREF(gMainThread); - return NS_OK; + *result = mThread; + return NS_OK; } -NS_COM PRBool -nsIThread::IsMainThread() -{ - if (gMainThread == 0) - return PR_TRUE; - - PRThread *theMainThread; - gMainThread->GetPRThread(&theMainThread); - return theMainThread == PR_GetCurrentThread(); -} - -void +NS_IMETHODIMP nsThread::Shutdown() { - if (gMainThread) { - // XXX nspr doesn't seem to be calling the main thread's destructor - // callback, so let's help it out: - nsThread::Exit(NS_STATIC_CAST(nsThread*, gMainThread)); - nsrefcnt cnt; - NS_RELEASE2(gMainThread, cnt); - NS_WARN_IF_FALSE(cnt == 0, "Main thread being held past XPCOM shutdown."); - gMainThread = nsnull; - - kIThreadSelfIndex = 0; - } + LOG(("THRD(%p) shutdown\n", this)); + + // XXX If we make this warn, then we hit that warning at xpcom shutdown while + // shutting down a thread in a thread pool. That happens b/c the thread + // in the thread pool is already shutdown by the thread manager. + if (!mThread) + return NS_OK; + + NS_ENSURE_STATE(mThread != PR_GetCurrentThread()); + + // Prevent multiple calls to this method + { + nsAutoLock lock(mLock); + if (!mShutdownRequired) + return NS_ERROR_UNEXPECTED; + mShutdownRequired = PR_FALSE; + } + + nsThreadShutdownContext context; + context.joiningThread = nsThreadManager::get()->GetCurrentThread(); + context.shutdownAck = PR_FALSE; + + // Set mShutdownContext and wake up the thread in case it is waiting for + // events to process. + nsCOMPtr event = new nsThreadShutdownEvent(this, &context); + if (!event) + return NS_ERROR_OUT_OF_MEMORY; + PutEvent(event); + + // We could still end up with other events being added after the shutdown + // task, but that's okay because we process pending events in ThreadFunc + // after setting mShutdownContext just before exiting. + + // Process events on the current thread until we receive a shutdown ACK. + while (!context.shutdownAck) + NS_ProcessNextEvent(context.joiningThread); + + // Now, it should be safe to join without fear of dead-locking. + + PR_JoinThread(mThread); + mThread = nsnull; + return NS_OK; } -//////////////////////////////////////////////////////////////////////////////// +NS_IMETHODIMP +nsThread::HasPendingEvents(PRBool *result) +{ + NS_ENSURE_STATE(PR_GetCurrentThread() == mThread); + + *result = mEvents->GetEvent(PR_FALSE, nsnull); + return NS_OK; +} + +NS_IMETHODIMP +nsThread::ProcessNextEvent(PRBool mayWait, PRBool *result) +{ + LOG(("THRD(%p) ProcessNextEvent [%u %u]\n", this, mayWait, mRunningEvent)); + + NS_ENSURE_STATE(PR_GetCurrentThread() == mThread); + + nsCOMPtr obs = mObserver; + if (obs) + obs->OnProcessNextEvent(this, mayWait && !ShuttingDown(), mRunningEvent); + + // If we are shutting down, then do not wait for new events. + nsCOMPtr event; + mEvents->GetEvent(mayWait && !ShuttingDown(), getter_AddRefs(event)); + + *result = (event.get() != nsnull); + + nsresult rv = NS_OK; + + if (event) { + LOG(("THRD(%p) running [%p]\n", this, event.get())); + ++mRunningEvent; + event->Run(); + --mRunningEvent; + } else if (mayWait) { + NS_ASSERTION(ShuttingDown(), "This should only happen when shutting down"); + rv = NS_ERROR_UNEXPECTED; + } + + return rv; +} + +//----------------------------------------------------------------------------- +// nsISupportsPriority + +NS_IMETHODIMP +nsThread::GetPriority(PRInt32 *priority) +{ + *priority = mPriority; + return NS_OK; +} + +NS_IMETHODIMP +nsThread::SetPriority(PRInt32 priority) +{ + NS_ENSURE_STATE(mThread); + + // NSPR defines the following four thread priorities: + // PR_PRIORITY_LOW + // PR_PRIORITY_NORMAL + // PR_PRIORITY_HIGH + // PR_PRIORITY_URGENT + // We map the priority values defined on nsISupportsPriority to these values. + + mPriority = priority; + + PRThreadPriority pri; + if (mPriority <= PRIORITY_HIGHEST) { + pri = PR_PRIORITY_URGENT; + } else if (mPriority < PRIORITY_NORMAL) { + pri = PR_PRIORITY_HIGH; + } else if (mPriority > PRIORITY_NORMAL) { + pri = PR_PRIORITY_LOW; + } else { + pri = PR_PRIORITY_NORMAL; + } + PR_SetThreadPriority(mThread, pri); + + return NS_OK; +} + +NS_IMETHODIMP +nsThread::AdjustPriority(PRInt32 delta) +{ + return SetPriority(mPriority + delta); +} + +//----------------------------------------------------------------------------- +// nsIThreadInternal + +NS_IMETHODIMP +nsThread::GetObserver(nsIThreadObserver **obs) +{ + nsAutoLock lock(mLock); + NS_IF_ADDREF(*obs = mObserver); + return NS_OK; +} + +NS_IMETHODIMP +nsThread::SetObserver(nsIThreadObserver *obs) +{ + NS_ENSURE_STATE(PR_GetCurrentThread() == mThread); + + nsAutoLock lock(mLock); + mObserver = obs; + return NS_OK; +} + +NS_IMETHODIMP +nsThread::PushEventQueue(nsIThreadEventFilter *filter) +{ + nsChainedEventQueue *queue = new nsChainedEventQueue(filter); + if (!queue || !queue->IsInitialized()) + return NS_ERROR_OUT_OF_MEMORY; + + nsAutoLock lock(mLock); + queue->mNext = mEvents; + mEvents = queue; + return NS_OK; +} + +NS_IMETHODIMP +nsThread::PopEventQueue() +{ + nsAutoLock lock(mLock); + + // Make sure we do not pop too many! + NS_ENSURE_STATE(mEvents != &mEventsRoot); + + nsChainedEventQueue *queue = mEvents; + mEvents = mEvents->mNext; + + nsCOMPtr event; + while (queue->GetEvent(PR_FALSE, getter_AddRefs(event))) + mEvents->PutEvent(event); + + return NS_OK; +} + +PRBool +nsThread::nsChainedEventQueue::PutEvent(nsIRunnable *event) +{ + PRBool val; + if (!mFilter || mFilter->AcceptEvent(event)) { + val = mQueue.PutEvent(event); + } else { + val = mNext->PutEvent(event); + } + return val; +} + +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +nsThreadSyncDispatch::Run() +{ + if (mSyncTask) { + mSyncTask->Run(); + mSyncTask = nsnull; + // unblock the origin thread + mOrigin->Dispatch(this, NS_DISPATCH_NORMAL); + } + return NS_OK; +} diff --git a/mozilla/xpcom/threads/nsThread.h b/mozilla/xpcom/threads/nsThread.h index e75086a71d8..b71ef2fc6f4 100644 --- a/mozilla/xpcom/threads/nsThread.h +++ b/mozilla/xpcom/threads/nsThread.h @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -12,18 +13,18 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is mozilla.org code. + * The Original Code is Mozilla code. * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to @@ -33,60 +34,128 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * - * ***** END LICENSE BLOCK ***** - * This Original Code has been modified by IBM Corporation. - * Modifications made by IBM described herein are - * Copyright (c) International Business Machines - * Corporation, 2000 - * - * Modifications to Mozilla code or documentation - * identified per MPL Section 3.3 - * - * Date Modified by Description of modification - * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2 - */ + * ***** END LICENSE BLOCK ***** */ #ifndef nsThread_h__ #define nsThread_h__ -#include "nsIRunnable.h" -#include "nsIThread.h" -#include "nsCOMPtr.h" +#include "nsIThreadInternal.h" +#include "nsISupportsPriority.h" +#include "nsEventQueue.h" +#include "nsThreadUtils.h" +#include "nsString.h" +#include "nsAutoLock.h" +#include "nsAutoPtr.h" -class nsThread : public nsIThread +// A native thread +class nsThread : public nsIThreadInternal, public nsISupportsPriority { public: - NS_DECL_ISUPPORTS + NS_DECL_ISUPPORTS + NS_DECL_NSIEVENTTARGET + NS_DECL_NSITHREAD + NS_DECL_NSITHREADINTERNAL + NS_DECL_NSISUPPORTSPRIORITY - // nsIThread methods: - NS_DECL_NSITHREAD - - // nsThread methods: - nsThread(); + nsThread(); - nsresult RegisterThreadSelf(); - void SetPRThread(PRThread* thread) { mThread = thread; } - void WaitUntilReadyToStartMain(); + // Initialize this as a wrapper for a new PRThread. + nsresult Init(); - static void PR_CALLBACK Main(void* arg); - static void PR_CALLBACK Exit(void* arg); - static void PR_CALLBACK Shutdown(); + // Initialize this as a wrapper for the current PRThread. + nsresult InitCurrentThread(); - static PRUintn kIThreadSelfIndex; + // The PRThread corresponding to this thread. + PRThread *GetPRThread() { return mThread; } - static NS_METHOD - Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + // If this flag is true, then the nsThread was created using + // nsIThreadManager::NewThread. + PRBool ShutdownRequired() { return mShutdownRequired; } private: - ~nsThread(); + friend class nsThreadShutdownEvent; -protected: - PRThread* mThread; - nsCOMPtr mRunnable; - PRBool mDead; - PRLock* mStartLock; + ~nsThread(); + + PRBool ShuttingDown() { return mShutdownContext != nsnull; } + + PR_STATIC_CALLBACK(void) ThreadFunc(void *arg); + + // Helper + already_AddRefed GetObserver() { + nsIThreadObserver *obs; + nsThread::GetObserver(&obs); + return already_AddRefed(obs); + } + + // Wrappers for event queue methods: + PRBool GetEvent(PRBool mayWait, nsIRunnable **event) { + return mEvents->GetEvent(mayWait, event); + } + PRBool PutEvent(nsIRunnable *event); + + // Wrapper for nsEventQueue that supports chaining. + class nsChainedEventQueue { + public: + nsChainedEventQueue(nsIThreadEventFilter *filter = nsnull) + : mNext(nsnull), mFilter(filter) { + } + + PRBool IsInitialized() { + return mQueue.IsInitialized(); + } + + PRBool GetEvent(PRBool mayWait, nsIRunnable **event) { + return mQueue.GetEvent(mayWait, event); + } + + PRBool PutEvent(nsIRunnable *event); + + class nsChainedEventQueue *mNext; + private: + nsCOMPtr mFilter; + nsEventQueue mQueue; + }; + + // This lock protects access to mObserver and mEvents. Both of those fields + // are only modified on the thread itself (never from another thread). This + // means that we can avoid holding the lock while using mObserver and mEvents + // on the thread itself. When calling PutEvent on mEvents, we have to hold + // the lock to synchronize with PopEventQueue. + PRLock *mLock; + + nsCOMPtr mObserver; + + nsChainedEventQueue *mEvents; // never null + nsChainedEventQueue mEventsRoot; + + PRInt32 mPriority; + PRThread *mThread; + PRUint32 mRunningEvent; // counter + + struct nsThreadShutdownContext *mShutdownContext; + + PRPackedBool mShutdownRequired; + PRPackedBool mShutdownPending; }; -//////////////////////////////////////////////////////////////////////////////// +//----------------------------------------------------------------------------- -#endif // nsThread_h__ +class nsThreadSyncDispatch : public nsRunnable { +public: + nsThreadSyncDispatch(nsIThread *origin, nsIRunnable *task) + : mOrigin(origin), mSyncTask(task) { + } + + PRBool IsPending() { + return mSyncTask != nsnull; + } + +private: + NS_DECL_NSIRUNNABLE + + nsCOMPtr mOrigin; + nsCOMPtr mSyncTask; +}; + +#endif // nsThread_h__ diff --git a/mozilla/xpcom/threads/nsThreadManager.cpp b/mozilla/xpcom/threads/nsThreadManager.cpp new file mode 100644 index 00000000000..02f45f29625 --- /dev/null +++ b/mozilla/xpcom/threads/nsThreadManager.cpp @@ -0,0 +1,270 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsThreadManager.h" +#include "nsThread.h" +#include "nsIClassInfoImpl.h" +#include "nsTArray.h" +#include "nsAutoPtr.h" +#include "nsAutoLock.h" + +typedef nsTArray< nsRefPtr > nsThreadArray; + +//----------------------------------------------------------------------------- + +PR_STATIC_CALLBACK(void) +ReleaseObject(void *data) +{ + NS_STATIC_CAST(nsISupports *, data)->Release(); +} + +PR_STATIC_CALLBACK(PLDHashOperator) +AppendAndRemoveThread(const void *key, nsRefPtr &thread, void *arg) +{ + nsThreadArray *threads = NS_STATIC_CAST(nsThreadArray *, arg); + threads->AppendElement(thread); + return PL_DHASH_REMOVE; +} + +//----------------------------------------------------------------------------- + +nsThreadManager nsThreadManager::sInstance; + +// statically allocated instance +NS_IMETHODIMP_(nsrefcnt) nsThreadManager::AddRef() { return 2; } +NS_IMETHODIMP_(nsrefcnt) nsThreadManager::Release() { return 1; } +NS_IMPL_QUERY_INTERFACE1_CI(nsThreadManager, nsIThreadManager) +NS_IMPL_CI_INTERFACE_GETTER1(nsThreadManager, nsIThreadManager) + +//----------------------------------------------------------------------------- + +nsresult +nsThreadManager::Init() +{ + mLock = PR_NewLock(); + if (!mLock) + return NS_ERROR_OUT_OF_MEMORY; + + if (!mThreadsByPRThread.Init()) + return NS_ERROR_OUT_OF_MEMORY; + + if (PR_NewThreadPrivateIndex(&mCurThreadIndex, ReleaseObject) == PR_FAILURE) + return NS_ERROR_FAILURE; + + // Setup "main" thread + mMainThread = new nsThread(); + if (!mMainThread) + return NS_ERROR_OUT_OF_MEMORY; + + nsresult rv = mMainThread->InitCurrentThread(); + if (NS_FAILED(rv)) { + mMainThread = nsnull; + return rv; + } + + // We need to keep a pointer to the current thread, so we can satisfy + // GetIsMainThread calls that occur post-Shutdown. + mMainThread->GetPRThread(&mMainPRThread); + + mInitialized = PR_TRUE; + return NS_OK; +} + +void +nsThreadManager::Shutdown() +{ + NS_ASSERTION(NS_IsMainThread(), "shutdown not called from main thread"); + + // Prevent further access to the thread manager (no more new threads!) + // + // XXX What happens if shutdown happens before NewThread completes? + // Fortunately, NewThread is only called on the main thread for now. + // + mInitialized = PR_FALSE; + + // XXX FIXME Stop accepting events to the main thread and process any events that got + // through. This hopefully ensures that any background threads that are + // needing to do something on the main thread have either been told that they + // cannot or will have had their work completed. This is done to hopefully + // ensure that calling Shutdown on those background threads will complete. + + NS_ProcessPendingEvents(mMainThread); + + // We move the threads from the hashtable to a list, so that we avoid holding + // the hashtable lock while calling nsIThread::Shutdown. + nsThreadArray threads; + { + nsAutoLock lock(mLock); + mThreadsByPRThread.Enumerate(AppendAndRemoveThread, &threads); + mThreadsByPRThread.Clear(); + } + + // It's tempting to walk the list of threads here and tell them each to stop + // accepting new events, but that could lead to badness if one of those + // threads is stuck waiting for a response from another thread. To do it + // right, we'd need some way to interrupt the threads. + + // Shutdown all threads that require it (join with threads that we created). + for (PRUint32 i = 0; i < threads.Length(); ++i) { + nsThread *thread = threads[i]; + if (thread->ShutdownRequired()) + thread->Shutdown(); + } + + // There are no more background threads at this point. + + // Release main thread object. + mMainThread = nsnull; + + // Remove the TLS entry for the main thread. + PR_SetThreadPrivate(mCurThreadIndex, nsnull); + + // We don't need this lock anymore. + PR_DestroyLock(mLock); + mLock = nsnull; +} + +void +nsThreadManager::RegisterCurrentThread(nsThread *thread) +{ + NS_ASSERTION(thread->GetPRThread() == PR_GetCurrentThread(), "bad thread"); + + nsAutoLock lock(mLock); + + mThreadsByPRThread.Put(thread->GetPRThread(), thread); // XXX check OOM? + + NS_ADDREF(thread); // for TLS entry + PR_SetThreadPrivate(mCurThreadIndex, thread); +} + +void +nsThreadManager::UnregisterCurrentThread(nsThread *thread) +{ + NS_ASSERTION(thread->GetPRThread() == PR_GetCurrentThread(), "bad thread"); + + nsAutoLock lock(mLock); + + mThreadsByPRThread.Remove(thread->GetPRThread()); + + PR_SetThreadPrivate(mCurThreadIndex, nsnull); + // Ref-count balanced via ReleaseObject +} + +nsThread * +nsThreadManager::GetCurrentThread() +{ + // read thread local storage + void *data = PR_GetThreadPrivate(mCurThreadIndex); + if (data) + return NS_STATIC_CAST(nsThread *, data); + + // OK, that's fine. We'll dynamically create one :-) + nsRefPtr thread = new nsThread(); + if (!thread || NS_FAILED(thread->InitCurrentThread())) + return nsnull; + + return thread.get(); // reference held in TLS +} + +NS_IMETHODIMP +nsThreadManager::NewThread(PRUint32 creationFlags, nsIThread **result) +{ + NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); + + nsThread *thr = new nsThread(); + if (!thr) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(thr); + + nsresult rv = thr->Init(); + if (NS_FAILED(rv)) { + NS_RELEASE(thr); + return rv; + } + + // At this point, we expect that the thread has been registered in mThread; + // however, it is possible that it could have also been replaced by now, so + // we cannot really assert that it was added. + + *result = thr; + return NS_OK; +} + +NS_IMETHODIMP +nsThreadManager::GetThreadFromPRThread(PRThread *thread, nsIThread **result) +{ + NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); + NS_ENSURE_ARG_POINTER(thread); + + nsRefPtr temp; + { + nsAutoLock lock(mLock); + mThreadsByPRThread.Get(thread, getter_AddRefs(temp)); + } + + NS_IF_ADDREF(*result = temp); + return NS_OK; +} + +NS_IMETHODIMP +nsThreadManager::GetMainThread(nsIThread **result) +{ + NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); + NS_ADDREF(*result = mMainThread); + return NS_OK; +} + +NS_IMETHODIMP +nsThreadManager::GetCurrentThread(nsIThread **result) +{ + NS_ENSURE_TRUE(mMainThread, NS_ERROR_NOT_INITIALIZED); + *result = GetCurrentThread(); + if (!*result) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(*result); + return NS_OK; +} + +NS_IMETHODIMP +nsThreadManager::GetIsMainThread(PRBool *result) +{ + // This method may be called post-Shutdown + + *result = (PR_GetCurrentThread() == mMainPRThread); + return NS_OK; +} diff --git a/mozilla/xpcom/threads/nsThreadManager.h b/mozilla/xpcom/threads/nsThreadManager.h new file mode 100644 index 00000000000..9bd8c80ed4b --- /dev/null +++ b/mozilla/xpcom/threads/nsThreadManager.h @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsThreadManager_h__ +#define nsThreadManager_h__ + +#include "nsIThreadManager.h" +#include "nsRefPtrHashtable.h" +#include "nsThread.h" + +class nsIRunnable; + +class nsThreadManager : public nsIThreadManager +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSITHREADMANAGER + + static nsThreadManager *get() { + return &sInstance; + } + + nsresult Init(); + + // Shutdown all threads. This function should only be called on the main + // thread of the application process. + void Shutdown(); + + // Called by nsThread to inform the ThreadManager it exists. This method + // must be called when the given thread is the current thread. + void RegisterCurrentThread(nsThread *thread); + + // Called by nsThread to inform the ThreadManager it is going away. This + // method must be called when the given thread is the current thread. + void UnregisterCurrentThread(nsThread *thread); + + // Returns the current thread. Returns null if OOM. + nsThread *GetCurrentThread(); + +private: + nsThreadManager() + : mCurThreadIndex(0) + , mMainPRThread(nsnull) + , mLock(nsnull) + , mInitialized(PR_FALSE) { + } + ~nsThreadManager() {} + + static nsThreadManager sInstance; + + nsRefPtrHashtable mThreadsByPRThread; + PRUintn mCurThreadIndex; // thread-local-storage index + nsRefPtr mMainThread; + PRThread *mMainPRThread; + PRLock *mLock; // protects tables + PRBool mInitialized; +}; + +#define NS_THREADMANAGER_CLASSNAME "nsThreadManager" +#define NS_THREADMANAGER_CID \ +{ /* 7a4204c6-e45a-4c37-8ebb-6709a22c917c */ \ + 0x7a4204c6, \ + 0xe45a, \ + 0x4c37, \ + {0x8e, 0xbb, 0x67, 0x09, 0xa2, 0x2c, 0x91, 0x7c} \ +} + +#endif // nsThreadManager_h__ diff --git a/mozilla/xpcom/threads/nsThreadPool.cpp b/mozilla/xpcom/threads/nsThreadPool.cpp new file mode 100644 index 00000000000..866931b9723 --- /dev/null +++ b/mozilla/xpcom/threads/nsThreadPool.cpp @@ -0,0 +1,328 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIProxyObjectManager.h" +#include "nsIClassInfoImpl.h" +#include "nsThreadPool.h" +#include "nsThreadManager.h" +#include "nsThread.h" +#include "nsMemory.h" +#include "nsAutoPtr.h" +#include "nsAutoLock.h" +#include "prinrval.h" +#include "prlog.h" + +#ifdef PR_LOGGING +static PRLogModuleInfo *sLog = PR_NewLogModule("nsThreadPool"); +#endif +#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args) + +// DESIGN: +// o Allocate anonymous threads. +// o Use nsThreadPool::Run as the main routine for each thread. +// o Each thread waits on the event queue's monitor, checking for +// pending events and rescheduling itself as an idle thread. + +#define DEFAULT_THREAD_LIMIT 4 +#define DEFAULT_IDLE_THREAD_LIMIT 1 +#define DEFAULT_IDLE_THREAD_TIMEOUT PR_SecondsToInterval(60) + +NS_IMPL_THREADSAFE_ADDREF(nsThreadPool) +NS_IMPL_THREADSAFE_RELEASE(nsThreadPool) +NS_IMPL_QUERY_INTERFACE3_CI(nsThreadPool, nsIThreadPool, nsIEventTarget, + nsIRunnable) +NS_IMPL_CI_INTERFACE_GETTER2(nsThreadPool, nsIThreadPool, nsIEventTarget) + +nsThreadPool::nsThreadPool() + : mThreadLimit(DEFAULT_THREAD_LIMIT) + , mIdleThreadLimit(DEFAULT_IDLE_THREAD_LIMIT) + , mIdleThreadTimeout(DEFAULT_IDLE_THREAD_TIMEOUT) + , mIdleCount(0) + , mShutdown(PR_FALSE) +{ +} + +nsThreadPool::~nsThreadPool() +{ + Shutdown(); +} + +nsresult +nsThreadPool::PutEvent(nsIRunnable *event) +{ + // Avoid spawning a new thread while holding the event queue lock... + + PRBool spawnThread = PR_FALSE; + { + nsAutoMonitor mon(mEvents.Monitor()); + + LOG(("THRD-P(%p) put [%d %d %d]\n", this, mIdleCount, mThreads.Count(), + mThreadLimit)); + NS_ASSERTION(mIdleCount <= (PRUint32) mThreads.Count(), "oops"); + + // Make sure we have a thread to service this event. + if (mIdleCount == 0 && mThreads.Count() < (PRInt32) mThreadLimit) + spawnThread = PR_TRUE; + + mEvents.PutEvent(event); + } + + LOG(("THRD-P(%p) put [spawn=%d]\n", this, spawnThread)); + if (!spawnThread) + return NS_OK; + + nsCOMPtr thread; + nsThreadManager::get()->NewThread(0, getter_AddRefs(thread)); + NS_ENSURE_STATE(thread); + + PRBool killThread = PR_FALSE; + { + nsAutoMonitor mon(mEvents.Monitor()); + if (mThreads.Count() < (PRInt32) mThreadLimit) { + mThreads.AppendObject(thread); + } else { + killThread = PR_TRUE; // okay, we don't need this thread anymore + } + } + LOG(("THRD-P(%p) put [%p kill=%d]\n", this, thread.get(), killThread)); + if (killThread) { + thread->Shutdown(); + } else { + thread->Dispatch(this, NS_DISPATCH_NORMAL); + } + + return NS_OK; +} + +void +nsThreadPool::ShutdownThread(nsIThread *thread) +{ + LOG(("THRD-P(%p) shutdown async [%p]\n", this, thread)); + + // This method is responsible for calling Shutdown on |thread|. This must be + // done from some other thread, so we use the main thread of the application. + + NS_ASSERTION(!NS_IsMainThread(), "wrong thread"); + + nsCOMPtr doomed; + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIThread), thread, + NS_PROXY_ASYNC, getter_AddRefs(doomed)); + if (doomed) { + doomed->Shutdown(); + } else { + NS_WARNING("failed to construct proxy to main thread"); + } +} + +NS_IMETHODIMP +nsThreadPool::Run() +{ + LOG(("THRD-P(%p) enter\n", this)); + + nsCOMPtr current; + nsThreadManager::get()->GetCurrentThread(getter_AddRefs(current)); + + PRBool shutdownThreadOnExit = PR_FALSE; + PRBool exitThread = PR_FALSE; + PRBool wasIdle = PR_FALSE; + PRIntervalTime idleSince; + + do { + nsCOMPtr event; + { + nsAutoMonitor mon(mEvents.Monitor()); + if (!mEvents.GetPendingEvent(getter_AddRefs(event))) { + PRIntervalTime now = PR_IntervalNow(); + PRIntervalTime timeout = PR_MillisecondsToInterval(mIdleThreadTimeout); + + // If we are shutting down, then don't keep any idle threads + if (mShutdown) { + exitThread = PR_TRUE; + } else { + if (wasIdle) { + // if too many idle threads or idle for too long, then bail. + if (mIdleCount > mIdleThreadLimit || (now - idleSince) >= timeout) + exitThread = PR_TRUE; + } else { + // if would be too many idle threads... + if (mIdleCount == mIdleThreadLimit) { + exitThread = PR_TRUE; + } else { + ++mIdleCount; + idleSince = now; + wasIdle = PR_TRUE; + } + } + } + + if (exitThread) { + if (wasIdle) + --mIdleCount; + shutdownThreadOnExit = mThreads.RemoveObject(current); + } else { + PRIntervalTime delta = timeout - (now - idleSince); + LOG(("THRD-P(%p) waiting [%d]\n", this, delta)); + mon.Wait(delta); + } + } else if (wasIdle) { + wasIdle = PR_FALSE; + --mIdleCount; + } + } + if (event) { + LOG(("THRD-P(%p) running [%p]\n", this, event.get())); + event->Run(); + } + } while (!exitThread); + + if (shutdownThreadOnExit) + ShutdownThread(current); + + LOG(("THRD-P(%p) leave\n", this)); + return NS_OK; +} + +NS_IMETHODIMP +nsThreadPool::Dispatch(nsIRunnable *event, PRUint32 flags) +{ + LOG(("THRD-P(%p) dispatch [%p %x]\n", this, event, flags)); + + NS_ENSURE_STATE(!mShutdown); + + if (flags & DISPATCH_SYNC) { + nsCOMPtr thread; + nsThreadManager::get()->GetCurrentThread(getter_AddRefs(thread)); + NS_ENSURE_STATE(thread); + + nsRefPtr wrapper = + new nsThreadSyncDispatch(thread, event); + PutEvent(wrapper); + + while (wrapper->IsPending()) + NS_ProcessNextEvent(thread); + } else { + NS_ASSERTION(flags == NS_DISPATCH_NORMAL, "unexpected dispatch flags"); + PutEvent(event); + } + return NS_OK; +} + +NS_IMETHODIMP +nsThreadPool::IsOnCurrentThread(PRBool *result) +{ + // No one should be calling this method. If this assertion gets hit, then we + // need to think carefully about what this method should be returning. + NS_NOTREACHED("implement me"); + + *result = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +nsThreadPool::Shutdown() +{ + nsCOMArray threads; + { + nsAutoMonitor mon(mEvents.Monitor()); + mShutdown = PR_TRUE; + mon.NotifyAll(); + + threads.AppendObjects(mThreads); + } + + // It's important that we shutdown the threads while outside the event queue + // monitor. Otherwise, we could end up dead-locking. The threads will take + // care of removing themselves from mThreads as they exit. + + for (PRInt32 i = 0; i < threads.Count(); ++i) + threads[i]->Shutdown(); + + return NS_OK; +} + +NS_IMETHODIMP +nsThreadPool::GetThreadLimit(PRUint32 *value) +{ + *value = mThreadLimit; + return NS_OK; +} + +NS_IMETHODIMP +nsThreadPool::SetThreadLimit(PRUint32 value) +{ + nsAutoMonitor mon(mEvents.Monitor()); + mThreadLimit = value; + if (mIdleThreadLimit > mThreadLimit) + mIdleThreadLimit = mThreadLimit; + mon.NotifyAll(); // wake up threads so they observe this change + return NS_OK; +} + +NS_IMETHODIMP +nsThreadPool::GetIdleThreadLimit(PRUint32 *value) +{ + *value = mIdleThreadLimit; + return NS_OK; +} + +NS_IMETHODIMP +nsThreadPool::SetIdleThreadLimit(PRUint32 value) +{ + nsAutoMonitor mon(mEvents.Monitor()); + mIdleThreadLimit = value; + if (mIdleThreadLimit > mThreadLimit) + mIdleThreadLimit = mThreadLimit; + mon.NotifyAll(); // wake up threads so they observe this change + return NS_OK; +} + +NS_IMETHODIMP +nsThreadPool::GetIdleThreadTimeout(PRUint32 *value) +{ + *value = mIdleThreadTimeout; + return NS_OK; +} + +NS_IMETHODIMP +nsThreadPool::SetIdleThreadTimeout(PRUint32 value) +{ + nsAutoMonitor mon(mEvents.Monitor()); + mIdleThreadTimeout = value; + mon.NotifyAll(); // wake up threads so they observe this change + return NS_OK; +} diff --git a/mozilla/xpcom/threads/nsThreadPool.h b/mozilla/xpcom/threads/nsThreadPool.h new file mode 100644 index 00000000000..9366b56cd40 --- /dev/null +++ b/mozilla/xpcom/threads/nsThreadPool.h @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsThreadPool_h__ +#define nsThreadPool_h__ + +#include "nsIThreadPool.h" +#include "nsIThread.h" +#include "nsIRunnable.h" +#include "nsEventQueue.h" +#include "nsCOMArray.h" + +class nsThreadPool : public nsIThreadPool, public nsIRunnable +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIEVENTTARGET + NS_DECL_NSITHREADPOOL + NS_DECL_NSIRUNNABLE + + nsThreadPool(); + +private: + ~nsThreadPool(); + + void ShutdownThread(nsIThread *thread); + nsresult PutEvent(nsIRunnable *event); + + nsCOMArray mThreads; + nsEventQueue mEvents; + PRUint32 mThreadLimit; + PRUint32 mIdleThreadLimit; + PRUint32 mIdleThreadTimeout; + PRUint32 mIdleCount; + PRBool mShutdown; +}; + +#define NS_THREADPOOL_CLASSNAME "nsThreadPool" +#define NS_THREADPOOL_CID \ +{ /* 547ec2a8-315e-4ec4-888e-6e4264fe90eb */ \ + 0x547ec2a8, \ + 0x315e, \ + 0x4ec4, \ + {0x88, 0x8e, 0x6e, 0x42, 0x64, 0xfe, 0x90, 0xeb} \ +} + +#endif // nsThreadPool_h__ diff --git a/mozilla/xpcom/threads/nsTimerImpl.cpp b/mozilla/xpcom/threads/nsTimerImpl.cpp index bd7ae7adfb7..4dc48c973ea 100644 --- a/mozilla/xpcom/threads/nsTimerImpl.cpp +++ b/mozilla/xpcom/threads/nsTimerImpl.cpp @@ -41,11 +41,10 @@ #include "nsTimerImpl.h" #include "TimerThread.h" #include "nsAutoLock.h" - +#include "nsAutoPtr.h" #include "nsVoidArray.h" - -#include "nsIEventQueue.h" - +#include "nsThreadManager.h" +#include "nsThreadUtils.h" #include "prmem.h" static PRInt32 gGenerator = 0; @@ -150,7 +149,7 @@ nsTimerImpl::nsTimerImpl() : mTimeout(0) { // XXXbsmedberg: shouldn't this be in Init()? - nsIThread::GetCurrent(getter_AddRefs(mCallingThread)); + mCallingThread = do_GetCurrentThread(); mCallback.c = nsnull; @@ -429,28 +428,45 @@ void nsTimerImpl::Fire() } -struct TimerEventType : public PLEvent { - PRInt32 mGeneration; +class nsTimerEvent : public nsRunnable { +public: + NS_IMETHOD Run(); + + nsTimerEvent(nsTimerImpl *timer, PRInt32 generation) + : mTimer(timer), mGeneration(generation) { + // timer is already addref'd for us + } + #ifdef DEBUG_TIMERS PRIntervalTime mInitTime; #endif + +private: + ~nsTimerEvent() { +#ifdef DEBUG + if (mTimer) + NS_WARNING("leaking reference to nsTimerImpl"); +#endif + } + + nsTimerImpl *mTimer; + PRInt32 mGeneration; }; - -PR_STATIC_CALLBACK(void*) handleTimerEvent(PLEvent* aEvent) +NS_IMETHODIMP nsTimerEvent::Run() { - TimerEventType *event = NS_STATIC_CAST(TimerEventType*, aEvent); + nsRefPtr timer; + timer.swap(mTimer); - nsTimerImpl* timer = NS_STATIC_CAST(nsTimerImpl*, event->owner); - if (event->mGeneration != timer->GetGeneration()) - return nsnull; + if (mGeneration != timer->GetGeneration()) + return NS_OK; #ifdef DEBUG_TIMERS if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) { PRIntervalTime now = PR_IntervalNow(); PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] time between PostTimerEvent() and Fire(): %dms\n", - event->owner, PR_IntervalToMilliseconds(now - event->mInitTime))); + this, PR_IntervalToMilliseconds(now - mInitTime))); } #endif @@ -461,43 +477,27 @@ PR_STATIC_CALLBACK(void*) handleTimerEvent(PLEvent* aEvent) NS_ASSERTION(gManager, "Global Thread Manager is null!"); if (gManager) gManager->AddIdleTimer(timer); - return nsnull; + return NS_OK; } } timer->Fire(); - return nsnull; + return NS_OK; } -PR_STATIC_CALLBACK(void) destroyTimerEvent(PLEvent* aEvent) -{ - TimerEventType *event = NS_STATIC_CAST(TimerEventType*, aEvent); - - nsTimerImpl *timer = NS_STATIC_CAST(nsTimerImpl*, event->owner); - NS_RELEASE(timer); - PR_DELETE(event); -} - - void nsTimerImpl::PostTimerEvent() { - // XXX we may want to reuse the PLEvent in the case of repeating timers. - TimerEventType* event; - - // construct - event = PR_NEW(TimerEventType); - if (!event) - return; - - // initialize - PL_InitEvent((PLEvent*)event, this, handleTimerEvent, destroyTimerEvent); + // XXX we may want to reuse this nsTimerEvent in the case of repeating timers. // Since TimerThread addref'd 'this' for us, we don't need to addref here. - // We will release in destroyMyEvent. We do need to copy the generation - // number from this timer into the event, so we can avoid firing a timer - // that was re-initialized after being canceled. - event->mGeneration = mGeneration; + // We will release in destroyMyEvent. We need to copy the generation number + // from this timer into the event, so we can avoid firing a timer that was + // re-initialized after being canceled. + + nsTimerEvent* event = new nsTimerEvent(this, mGeneration); + if (!event) + return; #ifdef DEBUG_TIMERS if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) { @@ -513,18 +513,7 @@ void nsTimerImpl::PostTimerEvent() gThread->AddTimer(this); } - PRThread *thread; - nsresult rv = mCallingThread->GetPRThread(&thread); - if (NS_FAILED(rv)) { - NS_WARNING("Dropping timer event because thread is dead"); - return; - } - - nsCOMPtr queue; - if (gThread) - gThread->mEventQueueService->GetThreadEventQueue(thread, getter_AddRefs(queue)); - if (queue) - queue->PostEvent(event); + mCallingThread->Dispatch(event, NS_DISPATCH_NORMAL); } void nsTimerImpl::SetDelayInternal(PRUint32 aDelay) @@ -615,7 +604,7 @@ nsresult nsTimerManager::AddIdleTimer(nsITimer* timer) NS_IMETHODIMP nsTimerManager::FireNextIdleTimer() { - if (!gFireOnIdle || !nsIThread::IsMainThread()) { + if (!gFireOnIdle || !NS_IsMainThread()) { return NS_OK; } diff --git a/mozilla/xpcom/threads/nsTimerImpl.h b/mozilla/xpcom/threads/nsTimerImpl.h index 98596f4e918..731de2c4d80 100644 --- a/mozilla/xpcom/threads/nsTimerImpl.h +++ b/mozilla/xpcom/threads/nsTimerImpl.h @@ -108,7 +108,6 @@ public: private: ~nsTimerImpl(); - nsresult InitCommon(PRUint32 aType, PRUint32 aDelay); void ReleaseCallback() diff --git a/mozilla/xpcom/threads/plevent.c b/mozilla/xpcom/threads/plevent.c deleted file mode 100644 index 4fd893730ea..00000000000 --- a/mozilla/xpcom/threads/plevent.c +++ /dev/null @@ -1,1736 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org Code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#if defined(_WIN32) -#include -#endif - -#if defined(XP_OS2) -#define INCL_DOS -#define INCL_DOSERRORS -#define INCL_WIN -#include -#define DefWindowProc WinDefWindowProc -#endif /* XP_OS2 */ - -#include "nspr.h" -#include "plevent.h" - -#if !defined(WIN32) -#include -#include -#if !defined(XP_OS2) -#include -#endif /* !XP_OS2 */ -#endif /* !Win32 */ - -#if defined(XP_UNIX) -/* for fcntl */ -#include -#include -#endif - -#if defined(XP_BEOS) -#include -#endif - -#if defined(XP_MACOSX) -#if defined(MOZ_WIDGET_COCOA) -#include -#define MAC_USE_CFRUNLOOPSOURCE -#elif defined(TARGET_CARBON) -/* #include */ -/* #define MAC_USE_CARBON_EVENT */ -#include -#define MAC_USE_CFRUNLOOPSOURCE -#endif -#endif - -#include "private/pprthred.h" - -#if defined(VMS) -/* -** On OpenVMS, XtAppAddInput doesn't want a regular fd, instead it -** wants an event flag. So, we don't create and use a pipe for -** notification of when an event queue has something ready, instead -** we use an event flag. Shouldn't be a problem if we only have -** a few event queues. -*/ -#include -#include -#include -#endif /* VMS */ - -#if defined(_WIN32) -/* Comment out the following USE_TIMER define to prevent - * WIN32 from using a WIN32 native timer for PLEvent notification. - * With USE_TIMER defined we will use a timer when pending input - * or paint events are starved, otherwise it will use a posted - * WM_APP msg for PLEvent notification. - */ - -#ifndef WINCE -#define USE_TIMER -#endif - -/* Threshold defined in milliseconds for determining when the input - * and paint events have been held in the WIN32 msg queue too long - */ -#define INPUT_STARVATION_LIMIT 50 -/* The paint starvation limit is set to the smallest value which - * does not cause performance degradation while running page load tests - */ -#define PAINT_STARVATION_LIMIT 750 -/* The WIN9X paint starvation limit is larger because it was - * determined that the following value was required to prevent performance - * degradation on page load tests for WIN98/95 only. - */ -#define WIN9X_PAINT_STARVATION_LIMIT 3000 - -#define TIMER_ID 0 -/* If _md_PerformanceSetting <=0 then no event starvation otherwise events will be starved */ -static PRInt32 _md_PerformanceSetting = 0; -static PRUint32 _md_StarvationDelay = 0; -static PRUint32 _md_SwitchTime = 0; -#endif - -static PRLogModuleInfo *event_lm = NULL; - -/******************************************************************************* - * Private Stuff - ******************************************************************************/ - -/* -** EventQueueType -- Defines notification type for an event queue -** -*/ -typedef enum { - EventQueueIsNative = 1, - EventQueueIsMonitored = 2 -} EventQueueType; - - -struct PLEventQueue { - const char* name; - PRCList queue; - PRMonitor* monitor; - PRThread* handlerThread; - EventQueueType type; - PRPackedBool processingEvents; - PRPackedBool notified; -#if defined(_WIN32) - PRPackedBool timerSet; -#endif - -#if defined(XP_UNIX) && !defined(XP_MACOSX) -#if defined(VMS) - int efn; -#else - PRInt32 eventPipe[2]; -#endif - PLGetEventIDFunc idFunc; - void* idFuncClosure; -#elif defined(_WIN32) || defined(XP_OS2) - HWND eventReceiverWindow; - PRBool removeMsg; -#elif defined(XP_BEOS) - port_id eventport; -#elif defined(XP_MACOSX) -#if defined(MAC_USE_CFRUNLOOPSOURCE) - CFRunLoopSourceRef mRunLoopSource; - CFRunLoopRef mMainRunLoop; -#elif defined(MAC_USE_CARBON_EVENT) - EventHandlerUPP eventHandlerUPP; - EventHandlerRef eventHandlerRef; -#endif -#endif -}; - -#define PR_EVENT_PTR(_qp) \ - ((PLEvent*) ((char*) (_qp) - offsetof(PLEvent, link))) - -static PRStatus _pl_SetupNativeNotifier(PLEventQueue* self); -static void _pl_CleanupNativeNotifier(PLEventQueue* self); -static PRStatus _pl_NativeNotify(PLEventQueue* self); -static PRStatus _pl_AcknowledgeNativeNotify(PLEventQueue* self); -static void _md_CreateEventQueue( PLEventQueue *eventQueue ); -static PRInt32 _pl_GetEventCount(PLEventQueue* self); - - -#if defined(_WIN32) || defined(XP_OS2) -#if defined(XP_OS2) -ULONG _pr_PostEventMsgId; -#else -UINT _pr_PostEventMsgId; -#endif /* OS2 */ -static char *_pr_eventWindowClass = "XPCOM:EventWindow"; -#endif /* Win32, OS2 */ - -#if defined(_WIN32) - -static LPCTSTR _md_GetEventQueuePropName() { - static ATOM atom = 0; - if (!atom) { - atom = GlobalAddAtom("XPCOM_EventQueue"); - } - return MAKEINTATOM(atom); -} -#endif - -#if defined(MAC_USE_CARBON_EVENT) -enum { - kEventClassPL = FOUR_CHAR_CODE('PLEC'), - - kEventProcessPLEvents = 1, - - kEventParamPLEventQueue = FOUR_CHAR_CODE('OWNQ') -}; - -static pascal Boolean _md_CarbonEventComparator(EventRef inEvent, void *inCompareData); -#endif - -/******************************************************************************* - * Event Queue Operations - ******************************************************************************/ - -/* -** _pl_CreateEventQueue() -- Create the event queue -** -** -*/ -static PLEventQueue * _pl_CreateEventQueue(const char *name, - PRThread *handlerThread, - EventQueueType qtype) -{ - PRStatus err; - PLEventQueue* self = NULL; - PRMonitor* mon = NULL; - - if (event_lm == NULL) - event_lm = PR_NewLogModule("event"); - - self = PR_NEWZAP(PLEventQueue); - if (self == NULL) return NULL; - - mon = PR_NewNamedMonitor(name); - if (mon == NULL) goto error; - - self->name = name; - self->monitor = mon; - self->handlerThread = handlerThread; - self->processingEvents = PR_FALSE; - self->type = qtype; -#if defined(_WIN32) - self->timerSet = PR_FALSE; -#endif -#if defined(_WIN32) || defined(XP_OS2) - self->removeMsg = PR_TRUE; -#endif - - self->notified = PR_FALSE; - - PR_INIT_CLIST(&self->queue); - if ( qtype == EventQueueIsNative ) { - err = _pl_SetupNativeNotifier(self); - if (err) goto error; - _md_CreateEventQueue( self ); - } - return self; - - error: - if (mon != NULL) - PR_DestroyMonitor(mon); - PR_DELETE(self); - return NULL; -} - -PLEventQueue* -PL_CreateEventQueue(const char* name, PRThread* handlerThread) -{ - return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsNative )); -} - -PLEventQueue * -PL_CreateNativeEventQueue(const char *name, PRThread *handlerThread) -{ - return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsNative )); -} - -PLEventQueue * -PL_CreateMonitoredEventQueue(const char *name, PRThread *handlerThread) -{ - return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsMonitored )); -} - -PRMonitor* -PL_GetEventQueueMonitor(PLEventQueue* self) -{ - return self->monitor; -} - -static void PR_CALLBACK -_pl_destroyEvent(PLEvent* event, void* data, PLEventQueue* queue) -{ - PL_DequeueEvent(event, queue); - PL_DestroyEvent(event); -} - -void -PL_DestroyEventQueue(PLEventQueue* self) -{ - PR_EnterMonitor(self->monitor); - - /* destroy undelivered events */ - PL_MapEvents(self, _pl_destroyEvent, NULL); - - if ( self->type == EventQueueIsNative ) - _pl_CleanupNativeNotifier(self); - - /* destroying the monitor also destroys the name */ - PR_ExitMonitor(self->monitor); - PR_DestroyMonitor(self->monitor); - PR_DELETE(self); - -} - -PRStatus -PL_PostEvent(PLEventQueue* self, PLEvent* event) -{ - PRStatus err = PR_SUCCESS; - PRMonitor* mon; - - if (self == NULL) - return PR_FAILURE; - - mon = self->monitor; - PR_EnterMonitor(mon); - -#if defined(XP_UNIX) && !defined(XP_MACOSX) - if (self->idFunc && event) - event->id = self->idFunc(self->idFuncClosure); -#endif - - /* insert event into thread's event queue: */ - if (event != NULL) { - PR_APPEND_LINK(&event->link, &self->queue); - } - - if (self->type == EventQueueIsNative && !self->notified) { - err = _pl_NativeNotify(self); - - if (err != PR_SUCCESS) - goto error; - - self->notified = PR_TRUE; - } - - /* - * This may fall on deaf ears if we're really notifying the native - * thread, and no one has called PL_WaitForEvent (or PL_EventLoop): - */ - err = PR_Notify(mon); - -error: - PR_ExitMonitor(mon); - return err; -} - -void* -PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event) -{ - void* result; - - if (self == NULL) - return NULL; - - PR_ASSERT(event != NULL); - - if (PR_GetCurrentThread() == self->handlerThread) { - /* Handle the case where the thread requesting the event handling - * is also the thread that's supposed to do the handling. */ - result = event->handler(event); - } - else { - int i, entryCount; - - event->lock = PR_NewLock(); - if (!event->lock) { - return NULL; - } - event->condVar = PR_NewCondVar(event->lock); - if(!event->condVar) { - PR_DestroyLock(event->lock); - event->lock = NULL; - return NULL; - } - - PR_Lock(event->lock); - - entryCount = PR_GetMonitorEntryCount(self->monitor); - - event->synchronousResult = (void*)PR_TRUE; - - PL_PostEvent(self, event); - - /* We need temporarily to give up our event queue monitor if - we're holding it, otherwise, the thread we're going to wait - for notification from won't be able to enter it to process - the event. */ - if (entryCount) { - for (i = 0; i < entryCount; i++) - PR_ExitMonitor(self->monitor); - } - - event->handled = PR_FALSE; - - while (!event->handled) { - /* wait for event to be handled or destroyed */ - PR_WaitCondVar(event->condVar, PR_INTERVAL_NO_TIMEOUT); - } - - if (entryCount) { - for (i = 0; i < entryCount; i++) - PR_EnterMonitor(self->monitor); - } - - result = event->synchronousResult; - event->synchronousResult = NULL; - PR_Unlock(event->lock); - } - - /* For synchronous events, they're destroyed here on the caller's - thread before the result is returned. See PL_HandleEvent. */ - PL_DestroyEvent(event); - - return result; -} - -PLEvent* -PL_GetEvent(PLEventQueue* self) -{ - PLEvent* event = NULL; - PRStatus err = PR_SUCCESS; - - if (self == NULL) - return NULL; - - PR_EnterMonitor(self->monitor); - - if (!PR_CLIST_IS_EMPTY(&self->queue)) { - if ( self->type == EventQueueIsNative && - self->notified && - !self->processingEvents && - 0 == _pl_GetEventCount(self) ) - { - err = _pl_AcknowledgeNativeNotify(self); - self->notified = PR_FALSE; - } - if (err) - goto done; - - /* then grab the event and return it: */ - event = PR_EVENT_PTR(self->queue.next); - PR_REMOVE_AND_INIT_LINK(&event->link); - } - - done: - PR_ExitMonitor(self->monitor); - return event; -} - -PRBool -PL_EventAvailable(PLEventQueue* self) -{ - PRBool result = PR_FALSE; - - if (self == NULL) - return PR_FALSE; - - PR_EnterMonitor(self->monitor); - - if (!PR_CLIST_IS_EMPTY(&self->queue)) - result = PR_TRUE; - - PR_ExitMonitor(self->monitor); - return result; -} - -void -PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data) -{ - PRCList* qp; - - if (self == NULL) - return; - - PR_EnterMonitor(self->monitor); - qp = self->queue.next; - while (qp != &self->queue) { - PLEvent* event = PR_EVENT_PTR(qp); - qp = qp->next; - (*fun)(event, data, self); - } - PR_ExitMonitor(self->monitor); -} - -static void PR_CALLBACK -_pl_DestroyEventForOwner(PLEvent* event, void* owner, PLEventQueue* queue) -{ - PR_ASSERT(PR_GetMonitorEntryCount(queue->monitor) > 0); - if (event->owner == owner) { - PR_LOG(event_lm, PR_LOG_DEBUG, - ("$$$ \tdestroying event %0x for owner %0x", event, owner)); - PL_DequeueEvent(event, queue); - - if (event->synchronousResult == (void*)PR_TRUE) { - PR_Lock(event->lock); - event->synchronousResult = NULL; - event->handled = PR_TRUE; - PR_NotifyCondVar(event->condVar); - PR_Unlock(event->lock); - } - else { - PL_DestroyEvent(event); - } - } - else { - PR_LOG(event_lm, PR_LOG_DEBUG, - ("$$$ \tskipping event %0x for owner %0x", event, owner)); - } -} - -void -PL_RevokeEvents(PLEventQueue* self, void* owner) -{ - if (self == NULL) - return; - - PR_LOG(event_lm, PR_LOG_DEBUG, - ("$$$ revoking events for owner %0x", owner)); - - /* - ** First we enter the monitor so that no one else can post any events - ** to the queue: - */ - PR_EnterMonitor(self->monitor); - PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ owner %0x, entered monitor", owner)); - - /* - ** Discard any pending events for this owner: - */ - PL_MapEvents(self, _pl_DestroyEventForOwner, owner); - -#ifdef DEBUG - { - PRCList* qp = self->queue.next; - while (qp != &self->queue) { - PLEvent* event = PR_EVENT_PTR(qp); - qp = qp->next; - PR_ASSERT(event->owner != owner); - } - } -#endif /* DEBUG */ - - PR_ExitMonitor(self->monitor); - - PR_LOG(event_lm, PR_LOG_DEBUG, - ("$$$ revoking events for owner %0x", owner)); -} - -static PRInt32 -_pl_GetEventCount(PLEventQueue* self) -{ - PRCList* node; - PRInt32 count = 0; - - PR_EnterMonitor(self->monitor); - node = PR_LIST_HEAD(&self->queue); - while (node != &self->queue) { - count++; - node = PR_NEXT_LINK(node); - } - PR_ExitMonitor(self->monitor); - - return count; -} - -void -PL_ProcessPendingEvents(PLEventQueue* self) -{ - PRInt32 count; - - if (self == NULL) - return; - - - PR_EnterMonitor(self->monitor); - - if (self->processingEvents) { - _pl_AcknowledgeNativeNotify(self); - self->notified = PR_FALSE; - PR_ExitMonitor(self->monitor); - return; - } - self->processingEvents = PR_TRUE; - - /* Only process the events that are already in the queue, and - * not any new events that get added. Do this by counting the - * number of events currently in the queue - */ - count = _pl_GetEventCount(self); - PR_ExitMonitor(self->monitor); - - while (count-- > 0) { - PLEvent* event = PL_GetEvent(self); - if (event == NULL) - break; - - PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event")); - PL_HandleEvent(event); - PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event")); - } - - PR_EnterMonitor(self->monitor); - - if (self->type == EventQueueIsNative) { - count = _pl_GetEventCount(self); - - if (count <= 0) { - _pl_AcknowledgeNativeNotify(self); - self->notified = PR_FALSE; - } - else { - _pl_NativeNotify(self); - self->notified = PR_TRUE; - } - - } - self->processingEvents = PR_FALSE; - - PR_ExitMonitor(self->monitor); -} - -/******************************************************************************* - * Event Operations - ******************************************************************************/ - -void -PL_InitEvent(PLEvent* self, void* owner, - PLHandleEventProc handler, - PLDestroyEventProc destructor) -{ -#ifdef PL_POST_TIMINGS - self->postTime = PR_IntervalNow(); -#endif - PR_INIT_CLIST(&self->link); - self->handler = handler; - self->destructor = destructor; - self->owner = owner; - self->synchronousResult = NULL; - self->handled = PR_FALSE; - self->lock = NULL; - self->condVar = NULL; -#if defined(XP_UNIX) && !defined(XP_MACOSX) - self->id = 0; -#endif -} - -void* -PL_GetEventOwner(PLEvent* self) -{ - return self->owner; -} - -void -PL_HandleEvent(PLEvent* self) -{ - void* result; - if (self == NULL) - return; - - /* This event better not be on an event queue anymore. */ - PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link)); - - result = self->handler(self); - if (NULL != self->synchronousResult) { - PR_Lock(self->lock); - self->synchronousResult = result; - self->handled = PR_TRUE; - PR_NotifyCondVar(self->condVar); - PR_Unlock(self->lock); - } - else { - /* For asynchronous events, they're destroyed by the event-handler - thread. See PR_PostSynchronousEvent. */ - PL_DestroyEvent(self); - } -} -#ifdef PL_POST_TIMINGS -static long s_eventCount = 0; -static long s_totalTime = 0; -#endif - -void -PL_DestroyEvent(PLEvent* self) -{ - if (self == NULL) - return; - - /* This event better not be on an event queue anymore. */ - PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link)); - - if(self->condVar) - PR_DestroyCondVar(self->condVar); - if(self->lock) - PR_DestroyLock(self->lock); - -#ifdef PL_POST_TIMINGS - s_totalTime += PR_IntervalNow() - self->postTime; - s_eventCount++; - printf("$$$ running avg (%d) \n", PR_IntervalToMilliseconds(s_totalTime/s_eventCount)); -#endif - - self->destructor(self); -} - -void -PL_DequeueEvent(PLEvent* self, PLEventQueue* queue) -{ - if (self == NULL) - return; - - /* Only the owner is allowed to dequeue events because once the - client has put it in the queue, they have no idea whether it's - been processed and destroyed or not. */ - - PR_ASSERT(queue->handlerThread == PR_GetCurrentThread()); - - PR_EnterMonitor(queue->monitor); - - PR_ASSERT(!PR_CLIST_IS_EMPTY(&self->link)); - -#if 0 - /* I do not think that we need to do this anymore. - if we do not acknowledge and this is the only - only event in the queue, any calls to process - the eventQ will be effective noop. - */ - if (queue->type == EventQueueIsNative) - _pl_AcknowledgeNativeNotify(queue); -#endif - - PR_REMOVE_AND_INIT_LINK(&self->link); - - PR_ExitMonitor(queue->monitor); -} - -void -PL_FavorPerformanceHint(PRBool favorPerformanceOverEventStarvation, - PRUint32 starvationDelay) -{ -#if defined(_WIN32) - - _md_StarvationDelay = starvationDelay; - - if (favorPerformanceOverEventStarvation) { - _md_PerformanceSetting++; - return; - } - - _md_PerformanceSetting--; - - if (_md_PerformanceSetting == 0) { - /* Switched from allowing event starvation to no event starvation so grab - the current time to determine when to actually switch to using timers - instead of posted WM_APP messages. */ - _md_SwitchTime = PR_IntervalToMilliseconds(PR_IntervalNow()); - } - -#endif -} - -/******************************************************************************* - * Pure Event Queues - * - * For when you're only processing PLEvents and there is no native - * select, thread messages, or AppleEvents. - ******************************************************************************/ - -PLEvent* -PL_WaitForEvent(PLEventQueue* self) -{ - PLEvent* event; - PRMonitor* mon; - - if (self == NULL) - return NULL; - - mon = self->monitor; - PR_EnterMonitor(mon); - - while ((event = PL_GetEvent(self)) == NULL) { - PRStatus err; - PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ waiting for event")); - err = PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); - if ((err == PR_FAILURE) - && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break; - } - - PR_ExitMonitor(mon); - return event; -} - -void -PL_EventLoop(PLEventQueue* self) -{ - if (self == NULL) - return; - - while (PR_TRUE) { - PLEvent* event = PL_WaitForEvent(self); - if (event == NULL) { - /* This can only happen if the current thread is interrupted */ - return; - } - - PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event")); - PL_HandleEvent(event); - PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event")); - } -} - -/******************************************************************************* - * Native Event Queues - * - * For when you need to call select, or WaitNextEvent, and yet also want - * to handle PLEvents. - ******************************************************************************/ - -static PRStatus -_pl_SetupNativeNotifier(PLEventQueue* self) -{ -#if defined(VMS) - unsigned int status; - self->idFunc = 0; - self->idFuncClosure = 0; - status = LIB$GET_EF(&self->efn); - if (!$VMS_STATUS_SUCCESS(status)) - return PR_FAILURE; - PR_LOG(event_lm, PR_LOG_DEBUG, - ("$$$ Allocated event flag %d", self->efn)); - return PR_SUCCESS; -#elif defined(XP_UNIX) && !defined(XP_MACOSX) - int err; - int flags; - - self->idFunc = 0; - self->idFuncClosure = 0; - - err = pipe(self->eventPipe); - if (err != 0) { - return PR_FAILURE; - } - - /* make the pipe nonblocking */ - flags = fcntl(self->eventPipe[0], F_GETFL, 0); - if (flags == -1) { - goto failed; - } - err = fcntl(self->eventPipe[0], F_SETFL, flags | O_NONBLOCK); - if (err == -1) { - goto failed; - } - flags = fcntl(self->eventPipe[1], F_GETFL, 0); - if (flags == -1) { - goto failed; - } - err = fcntl(self->eventPipe[1], F_SETFL, flags | O_NONBLOCK); - if (err == -1) { - goto failed; - } - return PR_SUCCESS; - -failed: - close(self->eventPipe[0]); - close(self->eventPipe[1]); - return PR_FAILURE; -#elif defined(XP_BEOS) - /* hook up to the nsToolkit queue, however the appshell - * isn't necessairly started, so we might have to create - * the queue ourselves - * - * Set up the port for communicating. As restarts thru execv may occur - * and ports survive those (with faulty events as result). Combined with the fact - * that nsAppShell.cpp may or may not have created the port we need to take extra - * care that the port is created for this launch, otherwise we need to reopen it - * so that faulty messages gets lost. - * - * We do this by checking if the sem has been created. If it is we can reuse the port (if it exists). - * Otherwise we need to create the sem and the port, deleting any open ports before. - */ - - sem_info info; - int32 cookie = 0; - - char portname[64]; - char semname[64]; - PR_snprintf(portname, sizeof(portname), "event%lx", - (long unsigned) self->handlerThread); - PR_snprintf(semname, sizeof(semname), "sync%lx", - (long unsigned) self->handlerThread); - - self->eventport = find_port(portname); - while(get_next_sem_info(0, &cookie, &info) == B_OK) - { - if(strcmp(semname, info.name) != 0) { - continue; - } - - /* found semaphore */ - if(self->eventport < 0) { - self->eventport = create_port(200, portname); - } - return PR_SUCCESS; - } - /* setup the port and semaphore */ - if(self->eventport >= 0) - { - delete_port( self->eventport ); - } - self->eventport = create_port(200, portname); - /* We don't use the sem, but it has to be there - */ - create_sem(0, semname); - return PR_SUCCESS; -#else - return PR_SUCCESS; -#endif -} - -static void -_pl_CleanupNativeNotifier(PLEventQueue* self) -{ -#if defined(VMS) - { - unsigned int status; - PR_LOG(event_lm, PR_LOG_DEBUG, - ("$$$ Freeing event flag %d", self->efn)); - status = LIB$FREE_EF(&self->efn); - } -#elif defined(XP_UNIX) && !defined(XP_MACOSX) - close(self->eventPipe[0]); - close(self->eventPipe[1]); -#elif defined(_WIN32) - if (self->timerSet) { - KillTimer(self->eventReceiverWindow, TIMER_ID); - self->timerSet = PR_FALSE; - } - RemoveProp(self->eventReceiverWindow, _md_GetEventQueuePropName()); - - /* DestroyWindow doesn't do anything when called from a non ui thread. Since - * self->eventReceiverWindow was created on the ui thread, it must be destroyed - * on the ui thread. - */ - SendMessage(self->eventReceiverWindow, WM_CLOSE, 0, 0); - -#elif defined(XP_OS2) - WinDestroyWindow(self->eventReceiverWindow); -#elif defined(MAC_USE_CFRUNLOOPSOURCE) - - CFRunLoopRemoveSource(self->mMainRunLoop, self->mRunLoopSource, kCFRunLoopCommonModes); - CFRelease(self->mRunLoopSource); - CFRelease(self->mMainRunLoop); - -#elif defined(MAC_USE_CARBON_EVENT) - EventComparatorUPP comparator = NewEventComparatorUPP(_md_CarbonEventComparator); - PR_ASSERT(comparator != NULL); - if (comparator) { - FlushSpecificEventsFromQueue(GetMainEventQueue(), comparator, self); - DisposeEventComparatorUPP(comparator); - } - DisposeEventHandlerUPP(self->eventHandlerUPP); - RemoveEventHandler(self->eventHandlerRef); -#endif -} - -#if defined(_WIN32) - -static PRBool _md_WasInputPending = PR_FALSE; -static PRUint32 _md_InputTime = 0; -static PRBool _md_WasPaintPending = PR_FALSE; -static PRUint32 _md_PaintTime = 0; -/* last mouse location */ -static POINT _md_LastMousePos; - -/******************************************************************************* - * Timer callback function. Timers are used on WIN32 instead of APP events - * when there are pending UI events because APP events can cause the GUI to lockup - * because posted messages are processed before other messages. - ******************************************************************************/ - -static void CALLBACK _md_TimerProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime ) -{ - PREventQueue* queue = (PREventQueue *) GetProp(hwnd, _md_GetEventQueuePropName()); - PR_ASSERT(queue != NULL); - - KillTimer(hwnd, TIMER_ID); - queue->timerSet = PR_FALSE; - queue->removeMsg = PR_FALSE; - PL_ProcessPendingEvents( queue ); - queue->removeMsg = PR_TRUE; -} - -static PRBool _md_IsWIN9X = PR_FALSE; -static PRBool _md_IsOSSet = PR_FALSE; - -static void _md_DetermineOSType() -{ - OSVERSIONINFO os; - os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&os); - if (VER_PLATFORM_WIN32_WINDOWS == os.dwPlatformId) { - _md_IsWIN9X = PR_TRUE; - } -} - -static PRUint32 _md_GetPaintStarvationLimit() -{ - if (! _md_IsOSSet) { - _md_DetermineOSType(); - _md_IsOSSet = PR_TRUE; - } - - if (_md_IsWIN9X) { - return WIN9X_PAINT_STARVATION_LIMIT; - } - - return PAINT_STARVATION_LIMIT; -} - - -/* - * Determine if an event is being starved (i.e the starvation limit has - * been exceeded. - * Note: this function uses the current setting and updates the contents - * of the wasPending and lastTime arguments - * - * ispending: PR_TRUE if the event is currently pending - * starvationLimit: Threshold defined in milliseconds for determining when - * the event has been held in the queue too long - * wasPending: PR_TRUE if the last time _md_EventIsStarved was called - * the event was pending. This value is updated within - * this function. - * lastTime: Holds the last time the event was in the queue. - * This value is updated within this function - * returns: PR_TRUE if the event is starved, PR_FALSE otherwise - */ - -static PRBool _md_EventIsStarved(PRBool isPending, PRUint32 starvationLimit, - PRBool *wasPending, PRUint32 *lastTime, - PRUint32 currentTime) -{ - if (*wasPending && isPending) { - /* - * It was pending previously and the event is still - * pending so check to see if the elapsed time is - * over the limit which indicates the event was starved - */ - if ((currentTime - *lastTime) > starvationLimit) { - return PR_TRUE; /* pending and over the limit */ - } - - return PR_FALSE; /* pending but within the limit */ - } - - if (isPending) { - /* - * was_pending must be false so record the current time - * so the elapsed time can be computed the next time this - * function is called - */ - *lastTime = currentTime; - *wasPending = PR_TRUE; - return PR_FALSE; - } - - /* Event is no longer pending */ - *wasPending = PR_FALSE; - return PR_FALSE; -} - -/* Determines if the there is a pending Mouse or input event */ - -static PRBool _md_IsInputPending(WORD qstatus) -{ - /* Return immediately there aren't any pending input or paints. */ - if (qstatus == 0) { - return PR_FALSE; - } - - /* Is there anything other than a QS_MOUSEMOVE pending? */ - if ((qstatus & QS_MOUSEBUTTON) || - (qstatus & QS_KEY) -#ifndef WINCE - || (qstatus & QS_HOTKEY) -#endif - ) { - return PR_TRUE; - } - - /* - * Mouse moves need extra processing to determine if the mouse - * pointer actually changed location because Windows automatically - * generates WM_MOVEMOVE events when a new window is created which - * we need to filter out. - */ - if (qstatus & QS_MOUSEMOVE) { - POINT cursorPos; - GetCursorPos(&cursorPos); - if ((_md_LastMousePos.x == cursorPos.x) && - (_md_LastMousePos.y == cursorPos.y)) { - return PR_FALSE; /* This is a fake mouse move */ - } - - /* Real mouse move */ - _md_LastMousePos.x = cursorPos.x; - _md_LastMousePos.y = cursorPos.y; - return PR_TRUE; - } - - return PR_FALSE; -} - -static PRStatus -_pl_NativeNotify(PLEventQueue* self) -{ -#ifdef USE_TIMER - WORD qstatus; - - PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow()); - - /* Since calls to set the _md_PerformanceSetting can be nested - * only performance setting values <= 0 will potentially trigger - * the use of a timer. - */ - if ((_md_PerformanceSetting <= 0) && - ((now - _md_SwitchTime) > _md_StarvationDelay)) { - SetTimer(self->eventReceiverWindow, TIMER_ID, 0 ,_md_TimerProc); - self->timerSet = PR_TRUE; - _md_WasInputPending = PR_FALSE; - _md_WasPaintPending = PR_FALSE; - return PR_SUCCESS; - } - - qstatus = HIWORD(GetQueueStatus(QS_INPUT | QS_PAINT)); - - /* Check for starved input */ - if (_md_EventIsStarved( _md_IsInputPending(qstatus), - INPUT_STARVATION_LIMIT, - &_md_WasInputPending, - &_md_InputTime, - now )) { - /* - * Use a timer for notification. Timers have the lowest priority. - * They are not processed until all other events have been processed. - * This allows any starved paints and input to be processed. - */ - SetTimer(self->eventReceiverWindow, TIMER_ID, 0 ,_md_TimerProc); - self->timerSet = PR_TRUE; - - /* - * Clear any pending paint. _md_WasInputPending was cleared in - * _md_EventIsStarved. - */ - _md_WasPaintPending = PR_FALSE; - return PR_SUCCESS; - } - - if (_md_EventIsStarved( (qstatus & QS_PAINT), - _md_GetPaintStarvationLimit(), - &_md_WasPaintPending, - &_md_PaintTime, - now) ) { - /* - * Use a timer for notification. Timers have the lowest priority. - * They are not processed until all other events have been processed. - * This allows any starved paints and input to be processed - */ - SetTimer(self->eventReceiverWindow, TIMER_ID, 0 ,_md_TimerProc); - self->timerSet = PR_TRUE; - - /* - * Clear any pending input. _md_WasPaintPending was cleared in - * _md_EventIsStarved. - */ - _md_WasInputPending = PR_FALSE; - return PR_SUCCESS; - } - - /* - * Nothing is being starved so post a message instead of using a timer. - * Posted messages are processed before other messages so they have the - * highest priority. - */ -#endif - PostMessage( self->eventReceiverWindow, _pr_PostEventMsgId, - (WPARAM)0, (LPARAM)self ); - - return PR_SUCCESS; -}/* --- end _pl_NativeNotify() --- */ -#endif - - -#if defined(XP_OS2) -static PRStatus -_pl_NativeNotify(PLEventQueue* self) -{ - BOOL rc = WinPostMsg( self->eventReceiverWindow, _pr_PostEventMsgId, - 0, MPFROMP(self)); - return (rc == TRUE) ? PR_SUCCESS : PR_FAILURE; -}/* --- end _pl_NativeNotify() --- */ -#endif /* XP_OS2 */ - -#if defined(VMS) -/* Just set the event flag */ -static PRStatus -_pl_NativeNotify(PLEventQueue* self) -{ - unsigned int status; - PR_LOG(event_lm, PR_LOG_DEBUG, - ("_pl_NativeNotify: self=%p efn=%d", - self, self->efn)); - status = SYS$SETEF(self->efn); - return ($VMS_STATUS_SUCCESS(status)) ? PR_SUCCESS : PR_FAILURE; -}/* --- end _pl_NativeNotify() --- */ -#elif defined(XP_UNIX) && !defined(XP_MACOSX) - -static PRStatus -_pl_NativeNotify(PLEventQueue* self) -{ -#define NOTIFY_TOKEN 0xFA - PRInt32 count; - unsigned char buf[] = { NOTIFY_TOKEN }; - - PR_LOG(event_lm, PR_LOG_DEBUG, - ("_pl_NativeNotify: self=%p", - self)); - count = write(self->eventPipe[1], buf, 1); - if (count == 1) - return PR_SUCCESS; - if (count == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) - return PR_SUCCESS; - return PR_FAILURE; -}/* --- end _pl_NativeNotify() --- */ -#endif /* defined(XP_UNIX) && !defined(XP_MACOSX) */ - -#if defined(XP_BEOS) -struct ThreadInterfaceData -{ - void *data; - thread_id waitingThread; -}; - -static PRStatus -_pl_NativeNotify(PLEventQueue* self) -{ - struct ThreadInterfaceData id; - id.data = self; - id.waitingThread = 0; - write_port(self->eventport, 'natv', &id, sizeof(id)); - - return PR_SUCCESS; /* Is this correct? */ -} -#endif /* XP_BEOS */ - -#if defined(XP_MACOSX) -static PRStatus -_pl_NativeNotify(PLEventQueue* self) -{ -#if defined(MAC_USE_CFRUNLOOPSOURCE) - CFRunLoopSourceSignal(self->mRunLoopSource); - CFRunLoopWakeUp(self->mMainRunLoop); -#elif defined(MAC_USE_CARBON_EVENT) - OSErr err; - EventRef newEvent; - if (CreateEvent(NULL, kEventClassPL, kEventProcessPLEvents, - 0, kEventAttributeNone, &newEvent) != noErr) - return PR_FAILURE; - err = SetEventParameter(newEvent, kEventParamPLEventQueue, - typeUInt32, sizeof(PREventQueue*), &self); - if (err == noErr) { - err = PostEventToQueue(GetMainEventQueue(), newEvent, kEventPriorityLow); - ReleaseEvent(newEvent); - } - if (err != noErr) - return PR_FAILURE; -#endif - return PR_SUCCESS; -} -#endif /* defined(XP_MACOSX) */ - -static PRStatus -_pl_AcknowledgeNativeNotify(PLEventQueue* self) -{ -#if defined(_WIN32) || defined(XP_OS2) -#ifdef XP_OS2 - QMSG aMsg; -#else - MSG aMsg; -#endif - /* - * only remove msg when we've been called directly by - * PL_ProcessPendingEvents, not when we've been called by - * the window proc because the window proc will remove the - * msg for us. - */ - if (self->removeMsg) { - PR_LOG(event_lm, PR_LOG_DEBUG, - ("_pl_AcknowledgeNativeNotify: self=%p", self)); -#ifdef XP_OS2 - WinPeekMsg((HAB)0, &aMsg, self->eventReceiverWindow, - _pr_PostEventMsgId, _pr_PostEventMsgId, PM_REMOVE); -#else - PeekMessage(&aMsg, self->eventReceiverWindow, - _pr_PostEventMsgId, _pr_PostEventMsgId, PM_REMOVE); - if (self->timerSet) { - KillTimer(self->eventReceiverWindow, TIMER_ID); - self->timerSet = PR_FALSE; - } -#endif - } - return PR_SUCCESS; -#elif defined(VMS) - PR_LOG(event_lm, PR_LOG_DEBUG, - ("_pl_AcknowledgeNativeNotify: self=%p efn=%d", - self, self->efn)); - /* - ** If this is the last entry, then clear the event flag. Also make sure - ** the flag is cleared on any spurious wakeups. - */ - sys$clref(self->efn); - return PR_SUCCESS; -#elif defined(XP_UNIX) && !defined(XP_MACOSX) - - PRInt32 count; - unsigned char c; - PR_LOG(event_lm, PR_LOG_DEBUG, - ("_pl_AcknowledgeNativeNotify: self=%p", - self)); - /* consume the byte NativeNotify put in our pipe: */ - count = read(self->eventPipe[0], &c, 1); - if ((count == 1) && (c == NOTIFY_TOKEN)) - return PR_SUCCESS; - if ((count == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) - return PR_SUCCESS; - return PR_FAILURE; -#else - - /* nothing to do on the other platforms */ - return PR_SUCCESS; -#endif -} - -PRInt32 -PL_GetEventQueueSelectFD(PLEventQueue* self) -{ - if (self == NULL) - return -1; - -#if defined(VMS) - return -(self->efn); -#elif defined(XP_UNIX) && !defined(XP_MACOSX) - return self->eventPipe[0]; -#else - return -1; /* other platforms don't handle this (yet) */ -#endif -} - -PRBool -PL_IsQueueOnCurrentThread( PLEventQueue *queue ) -{ - PRThread *me = PR_GetCurrentThread(); - return me == queue->handlerThread; -} - -PRBool -PL_IsQueueNative(PLEventQueue *queue) -{ - return queue->type == EventQueueIsNative ? PR_TRUE : PR_FALSE; -} - -#if defined(_WIN32) || defined(XP_OS2) -#ifdef XP_OS2 -MRESULT EXPENTRY -_md_EventReceiverProc(HWND hwnd, ULONG uMsg, MPARAM wParam, MPARAM lParam) -#else -LRESULT CALLBACK -_md_EventReceiverProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -#endif -{ - if (_pr_PostEventMsgId == uMsg ) - { - PREventQueue *queue = (PREventQueue *)lParam; - queue->removeMsg = PR_FALSE; - PL_ProcessPendingEvents(queue); - queue->removeMsg = PR_TRUE; -#ifdef XP_OS2 - return MRFROMLONG(TRUE); -#else - return TRUE; -#endif - } - return DefWindowProc(hwnd, uMsg, wParam, lParam); -} - -static PRBool isInitialized; -static PRCallOnceType once; -static PRLock *initLock; - -/* -** InitWinEventLib() -- Create the Windows initialization lock -** -*/ -static PRStatus InitEventLib( void ) -{ - PR_ASSERT( initLock == NULL ); - - initLock = PR_NewLock(); - return initLock ? PR_SUCCESS : PR_FAILURE; -} - -#endif /* Win32, OS2 */ - -#if defined(_WIN32) - -/* -** _md_CreateEventQueue() -- ModelDependent initializer -*/ -static void _md_CreateEventQueue( PLEventQueue *eventQueue ) -{ - WNDCLASS wc; - HANDLE h = GetModuleHandle(NULL); - - /* - ** If this is the first call to PL_InitializeEventsLib(), - ** make the call to InitWinEventLib() to create the initLock. - ** - ** Then lock the initializer lock to insure that - ** we have exclusive control over the initialization sequence. - ** - */ - - - /* Register the windows message for XPCOM Event notification */ - _pr_PostEventMsgId = RegisterWindowMessage("XPCOM_PostEvent"); - - /* Register the class for the event receiver window */ - if (!GetClassInfo(h, _pr_eventWindowClass, &wc)) { - wc.style = 0; - wc.lpfnWndProc = _md_EventReceiverProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = h; - wc.hIcon = NULL; - wc.hCursor = NULL; - wc.hbrBackground = (HBRUSH) NULL; - wc.lpszMenuName = (LPCSTR) NULL; - wc.lpszClassName = _pr_eventWindowClass; - RegisterClass(&wc); - } - - /* Create the event receiver window */ - eventQueue->eventReceiverWindow = CreateWindow(_pr_eventWindowClass, - "XPCOM:EventReceiver", - 0, 0, 0, 10, 10, - NULL, NULL, h, - NULL); - PR_ASSERT(eventQueue->eventReceiverWindow); - /* Set a property which can be used to retrieve the event queue - * within the _md_TimerProc callback - */ - SetProp(eventQueue->eventReceiverWindow, - _md_GetEventQueuePropName(), (HANDLE)eventQueue); - - return; -} /* end _md_CreateEventQueue() */ -#endif /* Winxx */ - -#if defined(XP_OS2) -/* -** _md_CreateEventQueue() -- ModelDependent initializer -*/ -static void _md_CreateEventQueue( PLEventQueue *eventQueue ) -{ - /* Must have HMQ for this & can't assume we already have appshell */ - if( FALSE == WinQueryQueueInfo( HMQ_CURRENT, NULL, 0)) - { - PPIB ppib; - PTIB ptib; - HAB hab; - HMQ hmq; - - /* Set our app to be a PM app before attempting Win calls */ - DosGetInfoBlocks(&ptib, &ppib); - ppib->pib_ultype = 3; - - hab = WinInitialize(0); - hmq = WinCreateMsgQueue(hab, 0); - PR_ASSERT(hmq); - } - - if( !_pr_PostEventMsgId) - { - WinRegisterClass( 0 /* hab_current */, - _pr_eventWindowClass, - _md_EventReceiverProc, - 0, 0); - - _pr_PostEventMsgId = WinAddAtom( WinQuerySystemAtomTable(), - "XPCOM_PostEvent"); - } - - eventQueue->eventReceiverWindow = WinCreateWindow( HWND_DESKTOP, - _pr_eventWindowClass, - "", 0, - 0, 0, 0, 0, - HWND_DESKTOP, - HWND_TOP, - 0, - NULL, - NULL); - PR_ASSERT(eventQueue->eventReceiverWindow); - - return; -} /* end _md_CreateEventQueue() */ -#endif /* XP_OS2 */ - -#if (defined(XP_UNIX) && !defined(XP_MACOSX)) || defined(XP_BEOS) -/* -** _md_CreateEventQueue() -- ModelDependent initializer -*/ -static void _md_CreateEventQueue( PLEventQueue *eventQueue ) -{ - /* there's really nothing special to do here, - ** the guts of the unix stuff is in the setupnativenotify - ** and related functions. - */ - return; -} /* end _md_CreateEventQueue() */ -#endif /* (defined(XP_UNIX) && !defined(XP_MACOSX)) || defined(XP_BEOS) */ - -#if defined(MAC_USE_CFRUNLOOPSOURCE) -static void _md_EventReceiverProc(void *info) -{ - PLEventQueue *queue = (PLEventQueue*)info; - PL_ProcessPendingEvents(queue); -} - -#elif defined(MAC_USE_CARBON_EVENT) -/* -** _md_CreateEventQueue() -- ModelDependent initializer -*/ - -static pascal OSStatus _md_EventReceiverProc(EventHandlerCallRef nextHandler, - EventRef inEvent, - void* userData) -{ - if (GetEventClass(inEvent) == kEventClassPL && - GetEventKind(inEvent) == kEventProcessPLEvents) - { - PREventQueue *queue; - if (GetEventParameter(inEvent, kEventParamPLEventQueue, - typeUInt32, NULL, sizeof(PREventQueue*), NULL, - &queue) == noErr) - { - PL_ProcessPendingEvents(queue); - return noErr; - } - } - return eventNotHandledErr; -} - -static pascal Boolean _md_CarbonEventComparator(EventRef inEvent, - void *inCompareData) -{ - Boolean match = false; - - if (GetEventClass(inEvent) == kEventClassPL && - GetEventKind(inEvent) == kEventProcessPLEvents) - { - PREventQueue *queue; - match = ((GetEventParameter(inEvent, kEventParamPLEventQueue, - typeUInt32, NULL, sizeof(PREventQueue*), NULL, - &queue) == noErr) && (queue == inCompareData)); - } - return match; -} - -#endif /* defined(MAC_USE_CARBON_EVENT) */ - -#if defined(XP_MACOSX) -static void _md_CreateEventQueue( PLEventQueue *eventQueue ) -{ -#if defined(MAC_USE_CFRUNLOOPSOURCE) - CFRunLoopSourceContext sourceContext = { 0 }; - sourceContext.version = 0; - sourceContext.info = (void*)eventQueue; - sourceContext.perform = _md_EventReceiverProc; - - /* make a run loop source */ - eventQueue->mRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0 /* order */, &sourceContext); - PR_ASSERT(eventQueue->mRunLoopSource); - - eventQueue->mMainRunLoop = CFRunLoopGetCurrent(); - CFRetain(eventQueue->mMainRunLoop); - - /* and add it to the run loop */ - CFRunLoopAddSource(eventQueue->mMainRunLoop, eventQueue->mRunLoopSource, kCFRunLoopCommonModes); - -#elif defined(MAC_USE_CARBON_EVENT) - eventQueue->eventHandlerUPP = NewEventHandlerUPP(_md_EventReceiverProc); - PR_ASSERT(eventQueue->eventHandlerUPP); - if (eventQueue->eventHandlerUPP) - { - EventTypeSpec eventType; - - eventType.eventClass = kEventClassPL; - eventType.eventKind = kEventProcessPLEvents; - - InstallApplicationEventHandler(eventQueue->eventHandlerUPP, 1, &eventType, - eventQueue, &eventQueue->eventHandlerRef); - PR_ASSERT(eventQueue->eventHandlerRef); - } -#endif -} /* end _md_CreateEventQueue() */ -#endif /* defined(XP_MACOSX) */ - -/* extra functions for unix */ - -#if defined(XP_UNIX) && !defined(XP_MACOSX) - -PRInt32 -PL_ProcessEventsBeforeID(PLEventQueue *aSelf, unsigned long aID) -{ - PRInt32 count = 0; - PRInt32 fullCount; - - if (aSelf == NULL) - return -1; - - PR_EnterMonitor(aSelf->monitor); - - if (aSelf->processingEvents) { - PR_ExitMonitor(aSelf->monitor); - return 0; - } - - aSelf->processingEvents = PR_TRUE; - - /* Only process the events that are already in the queue, and - * not any new events that get added. Do this by counting the - * number of events currently in the queue - */ - fullCount = _pl_GetEventCount(aSelf); - PR_LOG(event_lm, PR_LOG_DEBUG, - ("$$$ fullCount is %d id is %ld\n", fullCount, aID)); - - if (fullCount == 0) { - aSelf->processingEvents = PR_FALSE; - PR_ExitMonitor(aSelf->monitor); - return 0; - } - - PR_ExitMonitor(aSelf->monitor); - - while (fullCount-- > 0) { - /* peek at the next event */ - PLEvent *event; - event = PR_EVENT_PTR(aSelf->queue.next); - if (event == NULL) - break; - PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event %ld\n", - event->id)); - if (event->id >= aID) { - PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ skipping event and breaking")); - break; - } - - event = PL_GetEvent(aSelf); - PL_HandleEvent(event); - PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event")); - count++; - } - - PR_EnterMonitor(aSelf->monitor); - - /* if full count still had items left then there's still items left - in the queue. Let the native notify token stay. */ - - if (aSelf->type == EventQueueIsNative) { - fullCount = _pl_GetEventCount(aSelf); - - if (fullCount <= 0) { - _pl_AcknowledgeNativeNotify(aSelf); - aSelf->notified = PR_FALSE; - } - } - - aSelf->processingEvents = PR_FALSE; - - PR_ExitMonitor(aSelf->monitor); - - return count; -} - -void -PL_RegisterEventIDFunc(PLEventQueue *aSelf, PLGetEventIDFunc aFunc, - void *aClosure) -{ - aSelf->idFunc = aFunc; - aSelf->idFuncClosure = aClosure; -} - -void -PL_UnregisterEventIDFunc(PLEventQueue *aSelf) -{ - aSelf->idFunc = 0; - aSelf->idFuncClosure = 0; -} - -#endif /* defined(XP_UNIX) && !defined(XP_MACOSX) */ - -/* --- end plevent.c --- */ diff --git a/mozilla/xpcom/threads/plevent.h b/mozilla/xpcom/threads/plevent.h deleted file mode 100644 index 173fea16288..00000000000 --- a/mozilla/xpcom/threads/plevent.h +++ /dev/null @@ -1,664 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org Code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/********************************************************************** -NSPL Events - -Defining Events ---------------- - -Events are essentially structures that represent argument lists for a -function that will run on another thread. All event structures you -define must include a PLEvent struct as their first field: - - typedef struct MyEventType { - PLEvent e; - // arguments follow... - int x; - char* y; - } MyEventType; - -It is also essential that you establish a model of ownership for each -argument passed in an event record, i.e. whether particular arguments -will be deleted by the event destruction callback, or whether they -only loaned to the event handler callback, and guaranteed to persist -until the time at which the handler is called. - -Sending Events --------------- - -Events are initialized by PL_InitEvent and can be sent via -PL_PostEvent or PL_PostSynchronousEvent. Events can also have an -owner. The owner of an event can revoke all the events in a given -event-queue by calling PL_RevokeEvents. An owner might want -to do this if, for instance, it is being destroyed, and handling the -events after the owner's destruction would cause an error (e.g. an -MWContext). - -Since the act of initializing and posting an event must be coordinated -with it's possible revocation, it is essential that the event-queue's -monitor be entered surrounding the code that constructs, initializes -and posts the event: - - void postMyEvent(MyOwner* owner, int x, char* y) - { - MyEventType* event; - - PL_ENTER_EVENT_QUEUE_MONITOR(myQueue); - - // construct - event = PR_NEW(MyEventType); - if (event == NULL) goto done; - - // initialize - PL_InitEvent(event, owner, handleMyEvent, destroyMyEvent); - event->x = x; - event->y = strdup(y); - - // post - PL_PostEvent(myQueue, &event->e); - - done: - PL_EXIT_EVENT_QUEUE_MONITOR(myQueue); - } - -If you don't call PL_InitEvent and PL_PostEvent within the -event-queue's monitor, you'll get a big red assert. - -Handling Events ---------------- - -To handle an event you must write a callback that is passed the event -record you defined containing the event's arguments: - - PR_STATIC_CALLBACK(void*) handleMyEvent(PLEvent* aEvent) - { - MyEventType *event = NS_STATIC_CAST(MyEventType*, aEvent); - doit(event->x, event->y); - return NULL; // you could return a value for a sync event - } - -Similarly for the destruction callback: - - PR_STATIC_CALLBACK(void) destroyMyEvent(PLEvent* aEvent) - { - MyEventType *event = NS_STATIC_CAST(MyEventType*, aEvent); - free(event->y); // created by strdup - free(event); - } - -Processing Events in Your Event Loop ------------------------------------- - -If your main loop only processes events delivered to the event queue, -things are rather simple. You just get the next event (which may -block), and then handle it: - - while (1) { - event = PL_GetEvent(myQueue); - PL_HandleEvent(event); - } - -However, if other things must be waited on, you'll need to obtain a -file-descriptor that represents your event queue, and hand it to select: - - fd = PL_GetEventQueueSelectFD(myQueue); - ...add fd to select set... - while (select(...)) { - if (...fd...) { - PL_ProcessPendingEvents(myQueue); - } - ... - } - -Of course, with Motif and Windows it's more complicated than that, and -on Mac it's completely different, but you get the picture. - -Revoking Events ---------------- -If at any time an owner of events is about to be destroyed, you must -take steps to ensure that no one tries to use the event queue after -the owner is gone (or a crash may result). You can do this by either -processing all the events in the queue before destroying the owner: - - { - ... - PL_ENTER_EVENT_QUEUE_MONITOR(myQueue); - PL_ProcessPendingEvents(myQueue); - DestroyMyOwner(owner); - PL_EXIT_EVENT_QUEUE_MONITOR(myQueue); - ... - } - -or by revoking the events that are in the queue for that owner. This -removes them from the queue and calls their destruction callback: - - { - ... - PL_ENTER_EVENT_QUEUE_MONITOR(myQueue); - PL_RevokeEvents(myQueue, owner); - DestroyMyOwner(owner); - PL_EXIT_EVENT_QUEUE_MONITOR(myQueue); - ... - } - -In either case it is essential that you be in the event-queue's monitor -to ensure that all events are removed from the queue for that owner, -and to ensure that no more events will be delivered for that owner. -**********************************************************************/ - -#ifndef plevent_h___ -#define plevent_h___ - -#include "prtypes.h" -#include "prclist.h" -#include "prthread.h" -#include "prlock.h" -#include "prcvar.h" -#include "prmon.h" - -#include "nscore.h" - -/* For HWND */ -#if defined(XP_WIN32) -#include -#elif defined(XP_OS2) -#define INCL_DOSMISC -#define INCL_DOSPROCESS -#define INCL_DOSERRORS -#define INCL_WINSHELLDATA -#include -#endif - -PR_BEGIN_EXTERN_C - -/* Typedefs */ - -typedef struct PLEvent PLEvent; -typedef struct PLEventQueue PLEventQueue; - -/******************************************************************************* - * Event Queue Operations - ******************************************************************************/ - -/* -** Creates a new event queue. Returns NULL on failure. -*/ -NS_COM PLEventQueue* -PL_CreateEventQueue(const char* name, PRThread* handlerThread); - - -/* ----------------------------------------------------------------------- -** FUNCTION: PL_CreateNativeEventQueue() -** -** DESCRIPTION: -** PL_CreateNativeEventQueue() creates an event queue that -** uses platform specific notify mechanisms. -** -** For Unix, the platform specific notify mechanism provides -** an FD that may be extracted using the function -** PL_GetEventQueueSelectFD(). The FD returned may be used in -** a select() function call. -** -** For Windows, the platform specific notify mechanism -** provides an event receiver window that is called by -** Windows to process the event using the windows message -** pump engine. -** -** INPUTS: -** name: A name, as a diagnostic aid. -** -** handlerThread: A pointer to the PRThread structure for -** the thread that will "handle" events posted to this event -** queue. -** -** RETURNS: -** A pointer to a PLEventQueue structure or NULL. -** -*/ -NS_COM PLEventQueue * - PL_CreateNativeEventQueue( - const char *name, - PRThread *handlerThread - ); - -/* ----------------------------------------------------------------------- -** FUNCTION: PL_CreateMonitoredEventQueue() -** -** DESCRIPTION: -** PL_CreateMonitoredEventQueue() creates an event queue. No -** platform specific notify mechanism is created with the -** event queue. -** -** Users of this type of event queue must explicitly poll the -** event queue to retreive and process events. -** -** -** INPUTS: -** name: A name, as a diagnostic aid. -** -** handlerThread: A pointer to the PRThread structure for -** the thread that will "handle" events posted to this event -** queue. -** -** RETURNS: -** A pointer to a PLEventQueue structure or NULL. -** -*/ -NS_COM PLEventQueue * - PL_CreateMonitoredEventQueue( - const char *name, - PRThread *handlerThread - ); - -/* -** Destroys an event queue. -*/ -NS_COM void -PL_DestroyEventQueue(PLEventQueue* self); - -/* -** Returns the monitor associated with an event queue. This monitor is -** selectable. The monitor should be entered to protect against anyone -** calling PL_RevokeEvents while the event is trying to be constructed -** and delivered. -*/ -NS_COM PRMonitor* -PL_GetEventQueueMonitor(PLEventQueue* self); - -#define PL_ENTER_EVENT_QUEUE_MONITOR(queue) \ - PR_EnterMonitor(PL_GetEventQueueMonitor(queue)) - -#define PL_EXIT_EVENT_QUEUE_MONITOR(queue) \ - PR_ExitMonitor(PL_GetEventQueueMonitor(queue)) - -/* -** Posts an event to an event queue, waking up any threads waiting for an -** event. If event is NULL, notification still occurs, but no event will -** be available. -** -** Any events delivered by this routine will be destroyed by PL_HandleEvent -** when it is called (by the event-handling thread). -*/ -NS_COM PRStatus -PL_PostEvent(PLEventQueue* self, PLEvent* event); - -/* -** Like PL_PostEvent, this routine posts an event to the event handling -** thread, but does so synchronously, waiting for the result. The result -** which is the value of the handler routine is returned. -** -** Any events delivered by this routine will be not be destroyed by -** PL_HandleEvent, but instead will be destroyed just before the result is -** returned (by the current thread). -*/ -NS_COM void* -PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event); - -/* -** Gets an event from an event queue. Returns NULL if no event is -** available. -*/ -NS_COM PLEvent* -PL_GetEvent(PLEventQueue* self); - -/* -** Returns true if there is an event available for PL_GetEvent. -*/ -NS_COM PRBool -PL_EventAvailable(PLEventQueue* self); - -/* -** This is the type of the function that must be passed to PL_MapEvents -** (see description below). -*/ -typedef void -(PR_CALLBACK *PLEventFunProc)(PLEvent* event, void* data, PLEventQueue* queue); - -/* -** Applies a function to every event in the event queue. This can be used -** to selectively handle, filter, or remove events. The data pointer is -** passed to each invocation of the function fun. -*/ -NS_COM void -PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data); - -/* -** This routine walks an event queue and destroys any event whose owner is -** the owner specified. The == operation is used to compare owners. -*/ -NS_COM void -PL_RevokeEvents(PLEventQueue* self, void* owner); - -/* -** This routine processes all pending events in the event queue. It can be -** called from the thread's main event-processing loop whenever the event -** queue's selectFD is ready (returned by PL_GetEventQueueSelectFD). -*/ -NS_COM void -PL_ProcessPendingEvents(PLEventQueue* self); - -/******************************************************************************* - * Pure Event Queues - * - * For when you're only processing PLEvents and there is no native - * select, thread messages, or AppleEvents. - ******************************************************************************/ - -/* -** Blocks until an event can be returned from the event queue. This routine -** may return NULL if the current thread is interrupted. -*/ -NS_COM PLEvent* -PL_WaitForEvent(PLEventQueue* self); - -/* -** One stop shopping if all you're going to do is process PLEvents. Just -** call this and it loops forever processing events as they arrive. It will -** terminate when your thread is interrupted or dies. -*/ -NS_COM void -PL_EventLoop(PLEventQueue* self); - -/******************************************************************************* - * Native Event Queues - * - * For when you need to call select, or WaitNextEvent, and yet also want - * to handle PLEvents. - ******************************************************************************/ - -/* -** This routine allows you to grab the file descriptor associated with an -** event queue and use it in the readFD set of select. Useful for platforms -** that support select, and must wait on other things besides just PLEvents. -*/ -NS_COM PRInt32 -PL_GetEventQueueSelectFD(PLEventQueue* self); - -/* -** This routine will allow you to check to see if the given eventQueue in -** on the current thread. It will return PR_TRUE if so, else it will return -** PR_FALSE -*/ -NS_COM PRBool - PL_IsQueueOnCurrentThread( PLEventQueue *queue ); - -/* -** Returns whether the queue is native (true) or monitored (false) -*/ -NS_COM PRBool -PL_IsQueueNative(PLEventQueue *queue); - -/******************************************************************************* - * Event Operations - ******************************************************************************/ - -/* -** The type of an event handler function. This function is passed as an -** initialization argument to PL_InitEvent, and called by -** PL_HandleEvent. If the event is called synchronously, a void* result -** may be returned (otherwise any result will be ignored). -*/ -typedef void* -(PR_CALLBACK *PLHandleEventProc)(PLEvent* self); - -/* -** The type of an event destructor function. This function is passed as -** an initialization argument to PL_InitEvent, and called by -** PL_DestroyEvent. -*/ -typedef void -(PR_CALLBACK *PLDestroyEventProc)(PLEvent* self); - -/* -** Initializes an event. Usually events are embedded in a larger event -** structure which holds event-specific data, so this is an initializer -** for that embedded part of the structure. -*/ -NS_COM void -PL_InitEvent(PLEvent* self, void* owner, - PLHandleEventProc handler, - PLDestroyEventProc destructor); - -/* -** Returns the owner of an event. -*/ -NS_COM void* -PL_GetEventOwner(PLEvent* self); - -/* -** Handles an event, calling the event's handler routine. -*/ -NS_COM void -PL_HandleEvent(PLEvent* self); - -/* -** Destroys an event, calling the event's destructor. -*/ -NS_COM void -PL_DestroyEvent(PLEvent* self); - -/* -** Removes an event from an event queue. -*/ -NS_COM void -PL_DequeueEvent(PLEvent* self, PLEventQueue* queue); - - -/* - * Give hint to native PL_Event notification mechanism. If the native - * platform needs to tradeoff performance vs. native event starvation - * this hint tells the native dispatch code which to favor. - * The default is to prevent event starvation. - * - * Calls to this function may be nested. When the number of calls that - * pass PR_TRUE is subtracted from the number of calls that pass PR_FALSE - * is greater than 0, performance is given precedence over preventing - * event starvation. - * - * The starvationDelay arg is only used when - * favorPerformanceOverEventStarvation is PR_FALSE. It is the - * amount of time in milliseconds to wait before the PR_FALSE actually - * takes effect. - */ -NS_COM void -PL_FavorPerformanceHint(PRBool favorPerformanceOverEventStarvation, PRUint32 starvationDelay); - - -/******************************************************************************* - * Private Stuff - ******************************************************************************/ - -struct PLEvent { - PRCList link; - PLHandleEventProc handler; - PLDestroyEventProc destructor; - void* owner; - void* synchronousResult; - PRLock* lock; - PRCondVar* condVar; - PRBool handled; -#ifdef PL_POST_TIMINGS - PRIntervalTime postTime; -#endif -#ifdef XP_UNIX - unsigned long id; -#endif /* XP_UNIX */ - /* other fields follow... */ -}; - -/******************************************************************************/ - -/* -** Returns the event queue associated with the main thread. -** -*/ -#if defined(XP_WIN) || defined(XP_OS2) -/* ----------------------------------------------------------------------- -** FUNCTION: PL_GetNativeEventReceiverWindow() -** -** DESCRIPTION: -** PL_GetNativeEventReceiverWindow() returns the windows -** handle of the event receiver window associated with the -** referenced PLEventQueue argument. -** -** INPUTS: -** PLEventQueue pointer -** -** RETURNS: -** event receiver window handle. -** -** RESTRICTIONS: MS-Windows ONLY. -** -*/ -NS_COM HWND - PL_GetNativeEventReceiverWindow( - PLEventQueue *eqp - ); -#endif /* XP_WIN || XP_OS2 */ - -#ifdef XP_UNIX -/* ----------------------------------------------------------------------- -** FUNCTION: PL_ProcessEventsBeforeID() -** -** DESCRIPTION: -** -** PL_ProcessEventsBeforeID() will process events in a native event -** queue that have an id that is older than the ID passed in. -** -** INPUTS: -** PLEventQueue *aSelf -** unsigned long aID -** -** RETURNS: -** PRInt32 number of requests processed, -1 on error. -** -** RESTRICTIONS: Unix only (well, X based unix only) -*/ -NS_COM PRInt32 -PL_ProcessEventsBeforeID(PLEventQueue *aSelf, unsigned long aID); - -/* This prototype is a function that can be called when an event is - posted to stick an ID on it. */ - -typedef unsigned long -(PR_CALLBACK *PLGetEventIDFunc)(void *aClosure); - - -/* ----------------------------------------------------------------------- -** FUNCTION: PL_RegisterEventIDFunc() -** -** DESCRIPTION: -** -** This function registers a function for getting the ID on unix for -** this event queue. -** -** INPUTS: -** PLEventQueue *aSelf -** PLGetEventIDFunc func -** void *aClosure -** -** RETURNS: -** void -** -** RESTRICTIONS: Unix only (well, X based unix only) */ -NS_COM void -PL_RegisterEventIDFunc(PLEventQueue *aSelf, PLGetEventIDFunc aFunc, - void *aClosure); - -/* ----------------------------------------------------------------------- -** FUNCTION: PL_RegisterEventIDFunc() -** -** DESCRIPTION: -** -** This function unregisters a function for getting the ID on unix for -** this event queue. -** -** INPUTS: -** PLEventQueue *aSelf -** -** RETURNS: -** void -** -** RESTRICTIONS: Unix only (well, X based unix only) */ -NS_COM void -PL_UnregisterEventIDFunc(PLEventQueue *aSelf); - -#endif /* XP_UNIX */ - - -/* ----------------------------------------------------------------------- */ - -#if defined(NO_NSPR_10_SUPPORT) -#else -/********* ???????????????? FIX ME ??????????????????????????? *****/ -/********************** Some old definitions *****************************/ - -/* Re: prevent.h->plevent.h */ -#define PREvent PLEvent -#define PREventQueue PLEventQueue -#define PR_CreateEventQueue PL_CreateEventQueue -#define PR_DestroyEventQueue PL_DestroyEventQueue -#define PR_GetEventQueueMonitor PL_GetEventQueueMonitor -#define PR_ENTER_EVENT_QUEUE_MONITOR PL_ENTER_EVENT_QUEUE_MONITOR -#define PR_EXIT_EVENT_QUEUE_MONITOR PL_EXIT_EVENT_QUEUE_MONITOR -#define PR_PostEvent PL_PostEvent -#define PR_PostSynchronousEvent PL_PostSynchronousEvent -#define PR_GetEvent PL_GetEvent -#define PR_EventAvailable PL_EventAvailable -#define PREventFunProc PLEventFunProc -#define PR_MapEvents PL_MapEvents -#define PR_RevokeEvents PL_RevokeEvents -#define PR_ProcessPendingEvents PL_ProcessPendingEvents -#define PR_WaitForEvent PL_WaitForEvent -#define PR_EventLoop PL_EventLoop -#define PR_GetEventQueueSelectFD PL_GetEventQueueSelectFD -#define PRHandleEventProc PLHandleEventProc -#define PRDestroyEventProc PLDestroyEventProc -#define PR_InitEvent PL_InitEvent -#define PR_GetEventOwner PL_GetEventOwner -#define PR_HandleEvent PL_HandleEvent -#define PR_DestroyEvent PL_DestroyEvent -#define PR_DequeueEvent PL_DequeueEvent -#define PR_GetMainEventQueue PL_GetMainEventQueue - -/********* ????????????? End Fix me ?????????????????????????????? *****/ -#endif /* NO_NSPR_10_SUPPORT */ - -PR_END_EXTERN_C - -#endif /* plevent_h___ */ diff --git a/mozilla/xpfe/appshell/src/nsAbout.cpp b/mozilla/xpfe/appshell/src/nsAbout.cpp index 3cb6b51ade9..22f1768fa9b 100644 --- a/mozilla/xpfe/appshell/src/nsAbout.cpp +++ b/mozilla/xpfe/appshell/src/nsAbout.cpp @@ -38,6 +38,7 @@ #include "nsAbout.h" #include "nsIIOService.h" #include "nsIServiceManager.h" +#include "nsIChannel.h" #include "nsCOMPtr.h" #include "nsIURI.h" #include "nsNetCID.h" diff --git a/mozilla/xpfe/appshell/src/nsAppShellService.cpp b/mozilla/xpfe/appshell/src/nsAppShellService.cpp index 66993023b64..6f4137d8cce 100644 --- a/mozilla/xpfe/appshell/src/nsAppShellService.cpp +++ b/mozilla/xpfe/appshell/src/nsAppShellService.cpp @@ -44,7 +44,6 @@ #include "nsIURL.h" #include "nsNetUtil.h" #include "nsIServiceManager.h" -#include "nsIEventQueueService.h" #include "nsIObserverService.h" #include "nsIObserver.h" #include "nsIXPConnect.h" @@ -63,7 +62,6 @@ #include "nsCRT.h" #include "nsITimelineService.h" #include "prprf.h" -#include "plevent.h" #include "nsWidgetsCID.h" #include "nsIRequestObserver.h" diff --git a/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp b/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp index a16b00001a5..f67ef5c71a0 100644 --- a/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp +++ b/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp @@ -81,8 +81,6 @@ #include "nsIMenuListener.h" #include "nsITimer.h" -#include "nsIEventQueueService.h" -#include "plevent.h" #include "prmem.h" #include "prlock.h" diff --git a/mozilla/xpfe/appshell/src/nsXULWindow.cpp b/mozilla/xpfe/appshell/src/nsXULWindow.cpp index af68a40e6c6..e441ed919e5 100644 --- a/mozilla/xpfe/appshell/src/nsXULWindow.cpp +++ b/mozilla/xpfe/appshell/src/nsXULWindow.cpp @@ -1,5 +1,6 @@ -/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 ci et: */ +/* * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -47,6 +48,8 @@ #include "nsWidgetsCID.h" #include "prprf.h" #include "nsCRT.h" +#include "nsThreadUtils.h" +#include "nsNetCID.h" //Interfaces needed to be included #include "nsIAppShell.h" @@ -77,7 +80,8 @@ #include "nsIScreenManager.h" #include "nsIScreen.h" #include "nsIScrollable.h" -#include "nsIPref.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" #include "nsIScriptSecurityManager.h" #include "nsIWindowWatcher.h" #include "nsIURI.h" @@ -106,25 +110,30 @@ #define ZLEVEL_ATTRIBUTE NS_LITERAL_STRING("zlevel") // CIDs static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); -static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); -static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID); //***************************************************************************** //*** nsXULWindow: Object Management //***************************************************************************** -nsXULWindow::nsXULWindow() : mChromeTreeOwner(nsnull), - mContentTreeOwner(nsnull), mPrimaryContentTreeOwner(nsnull), - mModalStatus(NS_OK), mContinueModalLoop(PR_FALSE), - mDebuting(PR_FALSE), mChromeLoaded(PR_FALSE), - mShowAfterLoad(PR_FALSE), mIntrinsicallySized(PR_FALSE), - mCenterAfterLoad(PR_FALSE), mIsHiddenWindow(PR_FALSE), - mLockedUntilChromeLoad(PR_FALSE), - mContextFlags(0), mBlurSuppressionLevel(0), - mPersistentAttributesDirty(0), mPersistentAttributesMask(0), - mChromeFlags(nsIWebBrowserChrome::CHROME_ALL) +nsXULWindow::nsXULWindow() + : mChromeTreeOwner(nsnull), + mContentTreeOwner(nsnull), + mPrimaryContentTreeOwner(nsnull), + mModalStatus(NS_OK), + mContinueModalLoop(PR_FALSE), + mDebuting(PR_FALSE), + mChromeLoaded(PR_FALSE), + mShowAfterLoad(PR_FALSE), + mIntrinsicallySized(PR_FALSE), + mCenterAfterLoad(PR_FALSE), + mIsHiddenWindow(PR_FALSE), + mLockedUntilChromeLoad(PR_FALSE), + mContextFlags(0), + mBlurSuppressionLevel(0), + mPersistentAttributesDirty(0), + mPersistentAttributesMask(0), + mChromeFlags(nsIWebBrowserChrome::CHROME_ALL) { } @@ -141,14 +150,14 @@ NS_IMPL_THREADSAFE_ADDREF(nsXULWindow) NS_IMPL_THREADSAFE_RELEASE(nsXULWindow) NS_INTERFACE_MAP_BEGIN(nsXULWindow) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULWindow) - NS_INTERFACE_MAP_ENTRY(nsIXULWindow) - NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) - NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) - NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) - if (aIID.Equals(NS_GET_IID(nsXULWindow))) - foundInterface = NS_REINTERPRET_CAST(nsISupports*, this); - else + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULWindow) + NS_INTERFACE_MAP_ENTRY(nsIXULWindow) + NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + if (aIID.Equals(NS_GET_IID(nsXULWindow))) + foundInterface = NS_REINTERPRET_CAST(nsISupports*, this); + else NS_INTERFACE_MAP_END //***************************************************************************** @@ -320,16 +329,16 @@ NS_IMETHODIMP nsXULWindow::SetChromeFlags(PRUint32 aChromeFlags) NS_IMETHODIMP nsXULWindow::SetIntrinsicallySized(PRBool aIntrinsicallySized) { - mIntrinsicallySized = aIntrinsicallySized; - return NS_OK; + mIntrinsicallySized = aIntrinsicallySized; + return NS_OK; } NS_IMETHODIMP nsXULWindow::GetIntrinsicallySized(PRBool* aIntrinsicallySized) { - NS_ENSURE_ARG_POINTER(aIntrinsicallySized); + NS_ENSURE_ARG_POINTER(aIntrinsicallySized); - *aIntrinsicallySized = mIntrinsicallySized; - return NS_OK; + *aIntrinsicallySized = mIntrinsicallySized; + return NS_OK; } NS_IMETHODIMP nsXULWindow::GetPrimaryContentShell(nsIDocShellTreeItem** @@ -361,8 +370,8 @@ NS_IMETHODIMP nsXULWindow::GetContentShellById(const PRUnichar* aID, NS_IMETHODIMP nsXULWindow::AddChildWindow(nsIXULWindow *aChild) { - // we're not really keeping track of this right now - return NS_OK; + // we're not really keeping track of this right now + return NS_OK; } NS_IMETHODIMP nsXULWindow::RemoveChildWindow(nsIXULWindow *aChild) @@ -373,11 +382,6 @@ NS_IMETHODIMP nsXULWindow::RemoveChildWindow(nsIXULWindow *aChild) NS_IMETHODIMP nsXULWindow::ShowModal() { - nsCOMPtr appShell(do_CreateInstance(kAppShellCID)); - NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE); - - appShell->Create(0, nsnull); - appShell->Spinup(); // Store locally so it doesn't die on us nsCOMPtr window = mWindow; nsCOMPtr tempRef = this; @@ -392,25 +396,16 @@ NS_IMETHODIMP nsXULWindow::ShowModal() NS_STATIC_CAST(nsIXULWindow*, this), PR_TRUE); nsCOMPtr stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1")); - nsresult rv = NS_OK; if (stack && NS_SUCCEEDED(stack->Push(nsnull))) { - while(NS_SUCCEEDED(rv) && mContinueModalLoop) { - void* data; - PRBool isRealEvent; - PRBool processEvent; - - rv = appShell->GetNativeEvent(isRealEvent, data); - if(NS_SUCCEEDED(rv)) { - window->ModalEventFilter(isRealEvent, data, &processEvent); - if(processEvent) - appShell->DispatchNativeEvent(isRealEvent, data); - } + nsIThread *thread = NS_GetCurrentThread(); + while (mContinueModalLoop) { + if (!NS_ProcessNextEvent(thread)) + break; } JSContext* cx; stack->Pop(&cx); NS_ASSERTION(cx == nsnull, "JSContextStack mismatch"); - } else - rv = NS_ERROR_FAILURE; + } mContinueModalLoop = PR_FALSE; window->SetModal(PR_FALSE); @@ -428,7 +423,6 @@ NS_IMETHODIMP nsXULWindow::ShowModal() modal loop is always exited using ExitModalLoop (the other way would be to change the protected member variable directly.) */ - appShell->Spindown(); return mModalStatus; } @@ -440,49 +434,49 @@ NS_IMETHODIMP nsXULWindow::ShowModal() NS_IMETHODIMP nsXULWindow::InitWindow(nativeWindow aParentNativeWindow, nsIWidget* parentWidget, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy) { - //XXX First Check In - NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); - return NS_OK; + //XXX First Check In + NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); + return NS_OK; } NS_IMETHODIMP nsXULWindow::Create() { - //XXX First Check In - NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); - return NS_OK; + //XXX First Check In + NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); + return NS_OK; } NS_IMETHODIMP nsXULWindow::Destroy() { - if(!mWindow) - return NS_OK; + if(!mWindow) + return NS_OK; - nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); - NS_ASSERTION(appShell, "Couldn't get appShell... xpcom shutdown?"); - if(appShell) - appShell->UnregisterTopLevelWindow(NS_STATIC_CAST(nsIXULWindow*, this)); + nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); + NS_ASSERTION(appShell, "Couldn't get appShell... xpcom shutdown?"); + if (appShell) + appShell->UnregisterTopLevelWindow(NS_STATIC_CAST(nsIXULWindow*, this)); - nsCOMPtr parentWindow(do_QueryReferent(mParentWindow)); - if (parentWindow) - parentWindow->RemoveChildWindow(this); + nsCOMPtr parentWindow(do_QueryReferent(mParentWindow)); + if (parentWindow) + parentWindow->RemoveChildWindow(this); - // let's make sure the window doesn't get deleted out from under us - // while we are trying to close....this can happen if the docshell - // we close ends up being the last owning reference to this xulwindow + // let's make sure the window doesn't get deleted out from under us + // while we are trying to close....this can happen if the docshell + // we close ends up being the last owning reference to this xulwindow - // XXXTAB This shouldn't be an issue anymore because the ownership model - // only goes in one direction. When webshell container is fully removed - // try removing this... + // XXXTAB This shouldn't be an issue anymore because the ownership model + // only goes in one direction. When webshell container is fully removed + // try removing this... - nsCOMPtr placeHolder = this; + nsCOMPtr placeHolder = this; - // Remove modality (if any) and hide while destroying. More than - // a convenience, the hide prevents user interaction with the partially - // destroyed window. This is especially necessary when the eldest window - // in a stack of modal windows is destroyed first. It happens. - ExitModalLoop(NS_OK); - if (mWindow) - mWindow->Show(PR_FALSE); + // Remove modality (if any) and hide while destroying. More than + // a convenience, the hide prevents user interaction with the partially + // destroyed window. This is especially necessary when the eldest window + // in a stack of modal windows is destroyed first. It happens. + ExitModalLoop(NS_OK); + if (mWindow) + mWindow->Show(PR_FALSE); #if defined(XP_WIN) || defined(XP_OS2) // We need to explicitly set the focus on Windows @@ -506,55 +500,56 @@ NS_IMETHODIMP nsXULWindow::Destroy() } #endif - mDOMWindow = nsnull; - if(mDocShell) { - nsCOMPtr shellAsWin(do_QueryInterface(mDocShell)); - shellAsWin->Destroy(); - mDocShell = nsnull; // this can cause reentrancy of this function - } + mDOMWindow = nsnull; + if (mDocShell) { + nsCOMPtr shellAsWin(do_QueryInterface(mDocShell)); + shellAsWin->Destroy(); + mDocShell = nsnull; // this can cause reentrancy of this function + } - // Remove our ref on the content shells - PRInt32 count; - count = mContentShells.Count(); - for(PRInt32 i = 0; i < count; i++) { - nsContentShellInfo* shellInfo = (nsContentShellInfo*)(mContentShells.ElementAt(i)); - delete shellInfo; - } - mContentShells.Clear(); - mPrimaryContentShell = nsnull; + // Remove our ref on the content shells + PRInt32 count; + count = mContentShells.Count(); + for (PRInt32 i = 0; i < count; i++) { + nsContentShellInfo* shellInfo = + NS_STATIC_CAST(nsContentShellInfo *, mContentShells.ElementAt(i)); + delete shellInfo; + } + mContentShells.Clear(); + mPrimaryContentShell = nsnull; - if(mContentTreeOwner) { - mContentTreeOwner->XULWindow(nsnull); - NS_RELEASE(mContentTreeOwner); - } - if(mPrimaryContentTreeOwner) { - mPrimaryContentTreeOwner->XULWindow(nsnull); - NS_RELEASE(mPrimaryContentTreeOwner); - } - if(mChromeTreeOwner) { - mChromeTreeOwner->XULWindow(nsnull); - NS_RELEASE(mChromeTreeOwner); - } - if(mWindow) { - mWindow->SetClientData(0); // nsWebShellWindow hackery - mWindow = nsnull; - } + if(mContentTreeOwner) { + mContentTreeOwner->XULWindow(nsnull); + NS_RELEASE(mContentTreeOwner); + } + if(mPrimaryContentTreeOwner) { + mPrimaryContentTreeOwner->XULWindow(nsnull); + NS_RELEASE(mPrimaryContentTreeOwner); + } + if(mChromeTreeOwner) { + mChromeTreeOwner->XULWindow(nsnull); + NS_RELEASE(mChromeTreeOwner); + } + if(mWindow) { + mWindow->SetClientData(0); // nsWebShellWindow hackery + mWindow = nsnull; + } - if (!mIsHiddenWindow) { - /* Inform appstartup we've destroyed this window and it could - quit now if it wanted. This must happen at least after mDocShell - is destroyed, because onunload handlers fire then, and those being - script, anything could happen. A new window could open, even. - See bug 130719. */ - nsCOMPtr obssvc = - do_GetService("@mozilla.org/observer-service;1"); - NS_ASSERTION(obssvc, "Couldn't get observer service?"); + if (!mIsHiddenWindow) { + /* Inform appstartup we've destroyed this window and it could + quit now if it wanted. This must happen at least after mDocShell + is destroyed, because onunload handlers fire then, and those being + script, anything could happen. A new window could open, even. + See bug 130719. */ + nsCOMPtr obssvc = + do_GetService("@mozilla.org/observer-service;1"); + NS_ASSERTION(obssvc, "Couldn't get observer service?"); - if (obssvc) - obssvc->NotifyObservers(nsnull, "xul-window-destroyed", nsnull); - } + if (obssvc) + obssvc->NotifyObservers(nsnull, "xul-window-destroyed", nsnull); + } - return NS_OK; + return NS_OK; } NS_IMETHODIMP nsXULWindow::SetPosition(PRInt32 aX, PRInt32 aY) @@ -572,7 +567,7 @@ NS_IMETHODIMP nsXULWindow::SetPosition(PRInt32 aX, PRInt32 aY) NS_IMETHODIMP nsXULWindow::GetPosition(PRInt32* aX, PRInt32* aY) { - return GetPositionAndSize(aX, aY, nsnull, nsnull); + return GetPositionAndSize(aX, aY, nsnull, nsnull); } NS_IMETHODIMP nsXULWindow::SetSize(PRInt32 aCX, PRInt32 aCY, PRBool aRepaint) @@ -697,44 +692,44 @@ NS_IMETHODIMP nsXULWindow::Center(nsIXULWindow *aRelative, PRBool aScreen, PRBoo NS_IMETHODIMP nsXULWindow::Repaint(PRBool aForce) { - //XXX First Check In - NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); - return NS_OK; + //XXX First Check In + NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); + return NS_OK; } NS_IMETHODIMP nsXULWindow::GetParentWidget(nsIWidget** aParentWidget) { - NS_ENSURE_ARG_POINTER(aParentWidget); - NS_ENSURE_STATE(mWindow); + NS_ENSURE_ARG_POINTER(aParentWidget); + NS_ENSURE_STATE(mWindow); - NS_IF_ADDREF(*aParentWidget = mWindow->GetParent()); - return NS_OK; + NS_IF_ADDREF(*aParentWidget = mWindow->GetParent()); + return NS_OK; } NS_IMETHODIMP nsXULWindow::SetParentWidget(nsIWidget* aParentWidget) { - //XXX First Check In - NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); - return NS_OK; + //XXX First Check In + NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); + return NS_OK; } NS_IMETHODIMP nsXULWindow::GetParentNativeWindow(nativeWindow* aParentNativeWindow) { - NS_ENSURE_ARG_POINTER(aParentNativeWindow); + NS_ENSURE_ARG_POINTER(aParentNativeWindow); - nsCOMPtr parentWidget; - NS_ENSURE_SUCCESS(GetParentWidget(getter_AddRefs(parentWidget)), NS_ERROR_FAILURE); + nsCOMPtr parentWidget; + NS_ENSURE_SUCCESS(GetParentWidget(getter_AddRefs(parentWidget)), NS_ERROR_FAILURE); - *aParentNativeWindow = parentWidget->GetNativeData(NS_NATIVE_WIDGET); + *aParentNativeWindow = parentWidget->GetNativeData(NS_NATIVE_WIDGET); - return NS_OK; + return NS_OK; } NS_IMETHODIMP nsXULWindow::SetParentNativeWindow(nativeWindow aParentNativeWindow) { - //XXX First Check In - NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); - return NS_OK; + //XXX First Check In + NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); + return NS_OK; } NS_IMETHODIMP nsXULWindow::GetVisibility(PRBool* aVisibility) @@ -751,41 +746,40 @@ NS_IMETHODIMP nsXULWindow::GetVisibility(PRBool* aVisibility) NS_IMETHODIMP nsXULWindow::SetVisibility(PRBool aVisibility) { - NS_TIMELINE_ENTER("nsXULWindow::SetVisibility."); - if(!mChromeLoaded) - { - mShowAfterLoad = aVisibility; - NS_TIMELINE_LEAVE("nsXULWindow::SetVisibility"); - return NS_OK; - } + NS_TIMELINE_ENTER("nsXULWindow::SetVisibility."); + if (!mChromeLoaded) { + mShowAfterLoad = aVisibility; + NS_TIMELINE_LEAVE("nsXULWindow::SetVisibility"); + return NS_OK; + } - if(mDebuting) { - NS_TIMELINE_LEAVE("nsXULWindow::SetVisibility"); - return NS_OK; - } - mDebuting = PR_TRUE; // (Show / Focus is recursive) + if (mDebuting) { + NS_TIMELINE_LEAVE("nsXULWindow::SetVisibility"); + return NS_OK; + } + mDebuting = PR_TRUE; // (Show / Focus is recursive) - //XXXTAB Do we really need to show docshell and the window? Isn't - // the window good enough? - nsCOMPtr shellAsWin(do_QueryInterface(mDocShell)); - shellAsWin->SetVisibility(aVisibility); - mWindow->Show(aVisibility); + //XXXTAB Do we really need to show docshell and the window? Isn't + // the window good enough? + nsCOMPtr shellAsWin(do_QueryInterface(mDocShell)); + shellAsWin->SetVisibility(aVisibility); + mWindow->Show(aVisibility); - nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID)); - if(windowMediator) - windowMediator->UpdateWindowTimeStamp(NS_STATIC_CAST(nsIXULWindow*, this)); + nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID)); + if (windowMediator) + windowMediator->UpdateWindowTimeStamp(NS_STATIC_CAST(nsIXULWindow*, this)); - // notify observers so that we can hide the splash screen if possible - nsCOMPtr obssvc - (do_GetService("@mozilla.org/observer-service;1")); - NS_ASSERTION(obssvc, "Couldn't get observer service."); - if (obssvc) { - obssvc->NotifyObservers(nsnull, "xul-window-visible", nsnull); - } + // notify observers so that we can hide the splash screen if possible + nsCOMPtr obssvc + (do_GetService("@mozilla.org/observer-service;1")); + NS_ASSERTION(obssvc, "Couldn't get observer service."); + if (obssvc) { + obssvc->NotifyObservers(nsnull, "xul-window-visible", nsnull); + } - mDebuting = PR_FALSE; - NS_TIMELINE_LEAVE("nsXULWindow::SetVisibility"); - return NS_OK; + mDebuting = PR_FALSE; + NS_TIMELINE_LEAVE("nsXULWindow::SetVisibility"); + return NS_OK; } NS_IMETHODIMP nsXULWindow::GetEnabled(PRBool *aEnabled) @@ -833,45 +827,45 @@ NS_IMETHODIMP nsXULWindow::SetBlurSuppression(PRBool aBlurSuppression) NS_IMETHODIMP nsXULWindow::GetMainWidget(nsIWidget** aMainWidget) { - NS_ENSURE_ARG_POINTER(aMainWidget); + NS_ENSURE_ARG_POINTER(aMainWidget); - *aMainWidget = mWindow; - NS_IF_ADDREF(*aMainWidget); - return NS_OK; + *aMainWidget = mWindow; + NS_IF_ADDREF(*aMainWidget); + return NS_OK; } NS_IMETHODIMP nsXULWindow::SetFocus() { - //XXX First Check In - NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); - return NS_OK; + //XXX First Check In + NS_ASSERTION(PR_FALSE, "Not Yet Implemented"); + return NS_OK; } NS_IMETHODIMP nsXULWindow::GetTitle(PRUnichar** aTitle) { - NS_ENSURE_ARG_POINTER(aTitle); + NS_ENSURE_ARG_POINTER(aTitle); - *aTitle = ToNewUnicode(mTitle); - if (!*aTitle) - return NS_ERROR_OUT_OF_MEMORY; - return NS_OK; + *aTitle = ToNewUnicode(mTitle); + if (!*aTitle) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; } NS_IMETHODIMP nsXULWindow::SetTitle(const PRUnichar* aTitle) { - NS_ENSURE_STATE(mWindow); - mTitle.Assign(aTitle); - mTitle.StripChars("\n\r"); - NS_ENSURE_SUCCESS(mWindow->SetTitle(mTitle), NS_ERROR_FAILURE); + NS_ENSURE_STATE(mWindow); + mTitle.Assign(aTitle); + mTitle.StripChars("\n\r"); + NS_ENSURE_SUCCESS(mWindow->SetTitle(mTitle), NS_ERROR_FAILURE); - // Tell the window mediator that a title has changed - nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID)); - if(!windowMediator) - return NS_OK; + // Tell the window mediator that a title has changed + nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID)); + if(!windowMediator) + return NS_OK; - windowMediator->UpdateWindowTitle(NS_STATIC_CAST(nsIXULWindow*, this), aTitle); + windowMediator->UpdateWindowTitle(NS_STATIC_CAST(nsIXULWindow*, this), aTitle); - return NS_OK; + return NS_OK; } @@ -881,74 +875,75 @@ NS_IMETHODIMP nsXULWindow::SetTitle(const PRUnichar* aTitle) NS_IMETHODIMP nsXULWindow::EnsureChromeTreeOwner() { - if(mChromeTreeOwner) - return NS_OK; + if (mChromeTreeOwner) + return NS_OK; - mChromeTreeOwner = new nsChromeTreeOwner(); - NS_ENSURE_TRUE(mChromeTreeOwner, NS_ERROR_OUT_OF_MEMORY); + mChromeTreeOwner = new nsChromeTreeOwner(); + NS_ENSURE_TRUE(mChromeTreeOwner, NS_ERROR_OUT_OF_MEMORY); - NS_ADDREF(mChromeTreeOwner); - mChromeTreeOwner->XULWindow(this); + NS_ADDREF(mChromeTreeOwner); + mChromeTreeOwner->XULWindow(this); - return NS_OK; + return NS_OK; } NS_IMETHODIMP nsXULWindow::EnsureContentTreeOwner() { - if(mContentTreeOwner) - return NS_OK; + if (mContentTreeOwner) + return NS_OK; - mContentTreeOwner = new nsContentTreeOwner(PR_FALSE); - NS_ENSURE_TRUE(mContentTreeOwner, NS_ERROR_FAILURE); + mContentTreeOwner = new nsContentTreeOwner(PR_FALSE); + NS_ENSURE_TRUE(mContentTreeOwner, NS_ERROR_FAILURE); - NS_ADDREF(mContentTreeOwner); - mContentTreeOwner->XULWindow(this); + NS_ADDREF(mContentTreeOwner); + mContentTreeOwner->XULWindow(this); - return NS_OK; + return NS_OK; } NS_IMETHODIMP nsXULWindow::EnsurePrimaryContentTreeOwner() { - if(mPrimaryContentTreeOwner) - return NS_OK; + if (mPrimaryContentTreeOwner) + return NS_OK; - mPrimaryContentTreeOwner = new nsContentTreeOwner(PR_TRUE); - NS_ENSURE_TRUE(mPrimaryContentTreeOwner, NS_ERROR_FAILURE); + mPrimaryContentTreeOwner = new nsContentTreeOwner(PR_TRUE); + NS_ENSURE_TRUE(mPrimaryContentTreeOwner, NS_ERROR_FAILURE); - NS_ADDREF(mPrimaryContentTreeOwner); - mPrimaryContentTreeOwner->XULWindow(this); + NS_ADDREF(mPrimaryContentTreeOwner); + mPrimaryContentTreeOwner->XULWindow(this); - return NS_OK; + return NS_OK; } NS_IMETHODIMP nsXULWindow::EnsurePrompter() { - if (mPrompter) - return NS_OK; + if (mPrompter) + return NS_OK; - nsCOMPtr ourWindow; - nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow)); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); - if (wwatch) - wwatch->GetNewPrompter(ourWindow, getter_AddRefs(mPrompter)); - } - return mPrompter ? NS_OK : NS_ERROR_FAILURE; + nsCOMPtr ourWindow; + nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow)); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr wwatch = + do_GetService(NS_WINDOWWATCHER_CONTRACTID); + if (wwatch) + wwatch->GetNewPrompter(ourWindow, getter_AddRefs(mPrompter)); + } + return mPrompter ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP nsXULWindow::EnsureAuthPrompter() { - if (mAuthPrompter) - return NS_OK; + if (mAuthPrompter) + return NS_OK; - nsCOMPtr ourWindow; - nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow)); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); - if (wwatch) - wwatch->GetNewAuthPrompter(ourWindow, getter_AddRefs(mAuthPrompter)); - } - return mAuthPrompter ? NS_OK : NS_ERROR_FAILURE; + nsCOMPtr ourWindow; + nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow)); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); + if (wwatch) + wwatch->GetNewAuthPrompter(ourWindow, getter_AddRefs(mAuthPrompter)); + } + return mAuthPrompter ? NS_OK : NS_ERROR_FAILURE; } void nsXULWindow::OnChromeLoaded() @@ -1350,62 +1345,62 @@ NS_IMETHODIMP nsXULWindow::LoadWindowClassFromXUL() NS_IMETHODIMP nsXULWindow::LoadIconFromXUL() { - NS_ENSURE_STATE(mWindow); + NS_ENSURE_STATE(mWindow); - // Get element. - nsCOMPtr windowElement; - GetWindowDOMElement(getter_AddRefs(windowElement)); - NS_ENSURE_TRUE(windowElement, NS_ERROR_FAILURE); + // Get element. + nsCOMPtr windowElement; + GetWindowDOMElement(getter_AddRefs(windowElement)); + NS_ENSURE_TRUE(windowElement, NS_ERROR_FAILURE); - // XXX The following code is being #if 0'd out since it - // basically does nothing until bug 70974 is fixed. - // After bug 70974 is fixed, we will also need to implement - // computed style for that property before this will - // be of any use. And even then, it will *still* - // do nothing on platforms which don't implement - // nsWindow::SetIcon(). See bug 76211 for that. - // Also see bug 57576 and its dependency tree. + // XXX The following code is being #if 0'd out since it + // basically does nothing until bug 70974 is fixed. + // After bug 70974 is fixed, we will also need to implement + // computed style for that property before this will + // be of any use. And even then, it will *still* + // do nothing on platforms which don't implement + // nsWindow::SetIcon(). See bug 76211 for that. + // Also see bug 57576 and its dependency tree. #if 0 - // Get document in which this is contained. - nsCOMPtr document; - windowElement->GetOwnerDocument(getter_AddRefs(document)); - NS_ENSURE_TRUE(document, NS_ERROR_FAILURE); + // Get document in which this is contained. + nsCOMPtr document; + windowElement->GetOwnerDocument(getter_AddRefs(document)); + NS_ENSURE_TRUE(document, NS_ERROR_FAILURE); - // Get document view. - nsCOMPtr docView(do_QueryInterface(document)); - NS_ENSURE_TRUE(docView, NS_ERROR_FAILURE); + // Get document view. + nsCOMPtr docView(do_QueryInterface(document)); + NS_ENSURE_TRUE(docView, NS_ERROR_FAILURE); - // Get default/abstract view. - nsCOMPtr abstractView; - docView->GetDefaultView(getter_AddRefs(abstractView)); - NS_ENSURE_TRUE(abstractView, NS_ERROR_FAILURE); + // Get default/abstract view. + nsCOMPtr abstractView; + docView->GetDefaultView(getter_AddRefs(abstractView)); + NS_ENSURE_TRUE(abstractView, NS_ERROR_FAILURE); - // Get "view CSS." - nsCOMPtr viewCSS(do_QueryInterface(abstractView)); - NS_ENSURE_TRUE(viewCSS, NS_ERROR_FAILURE); + // Get "view CSS." + nsCOMPtr viewCSS(do_QueryInterface(abstractView)); + NS_ENSURE_TRUE(viewCSS, NS_ERROR_FAILURE); - // Next, get CSS style declaration. - nsCOMPtr cssDecl; - viewCSS->GetComputedStyle(windowElement, EmptyString(), - getter_AddRefs(cssDecl)); - NS_ENSURE_TRUE(cssDecl, NS_ERROR_FAILURE); + // Next, get CSS style declaration. + nsCOMPtr cssDecl; + viewCSS->GetComputedStyle(windowElement, EmptyString(), + getter_AddRefs(cssDecl)); + NS_ENSURE_TRUE(cssDecl, NS_ERROR_FAILURE); - // Whew. Now get "list-style-image" property value. - nsAutoString windowIcon; - windowIcon.AssignLiteral("-moz-window-icon"); - nsAutoString icon; - cssDecl->GetPropertyValue(windowIcon, icon); + // Whew. Now get "list-style-image" property value. + nsAutoString windowIcon; + windowIcon.AssignLiteral("-moz-window-icon"); + nsAutoString icon; + cssDecl->GetPropertyValue(windowIcon, icon); #endif - nsAutoString id; - windowElement->GetAttribute(NS_LITERAL_STRING("id"), id); + nsAutoString id; + windowElement->GetAttribute(NS_LITERAL_STRING("id"), id); - if (id.IsEmpty()) { - id.AssignLiteral("default"); - } + if (id.IsEmpty()) { + id.AssignLiteral("default"); + } - mWindow->SetIcon(id); - return NS_OK; + mWindow->SetIcon(id); + return NS_OK; } NS_IMETHODIMP nsXULWindow::SavePersistentAttributes() @@ -1525,69 +1520,69 @@ NS_IMETHODIMP nsXULWindow::SavePersistentAttributes() NS_IMETHODIMP nsXULWindow::GetWindowDOMWindow(nsIDOMWindowInternal** aDOMWindow) { - NS_ENSURE_STATE(mDocShell); + NS_ENSURE_STATE(mDocShell); - if(!mDOMWindow) - mDOMWindow = do_GetInterface(mDocShell); - NS_ENSURE_TRUE(mDOMWindow, NS_ERROR_FAILURE); + if (!mDOMWindow) + mDOMWindow = do_GetInterface(mDocShell); + NS_ENSURE_TRUE(mDOMWindow, NS_ERROR_FAILURE); - *aDOMWindow = mDOMWindow; - NS_ADDREF(*aDOMWindow); - return NS_OK; + *aDOMWindow = mDOMWindow; + NS_ADDREF(*aDOMWindow); + return NS_OK; } NS_IMETHODIMP nsXULWindow::GetWindowDOMElement(nsIDOMElement** aDOMElement) { - NS_ENSURE_STATE(mDocShell); - NS_ENSURE_ARG_POINTER(aDOMElement); + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_ARG_POINTER(aDOMElement); - *aDOMElement = nsnull; + *aDOMElement = nsnull; - nsCOMPtr cv; - - mDocShell->GetContentViewer(getter_AddRefs(cv)); - NS_ENSURE_TRUE(cv, NS_ERROR_FAILURE); + nsCOMPtr cv; - nsCOMPtr docv(do_QueryInterface(cv)); - NS_ENSURE_TRUE(docv, NS_ERROR_FAILURE); + mDocShell->GetContentViewer(getter_AddRefs(cv)); + NS_ENSURE_TRUE(cv, NS_ERROR_FAILURE); - nsCOMPtr doc; - docv->GetDocument(getter_AddRefs(doc)); - nsCOMPtr domdoc(do_QueryInterface(doc)); - NS_ENSURE_TRUE(domdoc, NS_ERROR_FAILURE); + nsCOMPtr docv(do_QueryInterface(cv)); + NS_ENSURE_TRUE(docv, NS_ERROR_FAILURE); - domdoc->GetDocumentElement(aDOMElement); - NS_ENSURE_TRUE(*aDOMElement, NS_ERROR_FAILURE); + nsCOMPtr doc; + docv->GetDocument(getter_AddRefs(doc)); + nsCOMPtr domdoc(do_QueryInterface(doc)); + NS_ENSURE_TRUE(domdoc, NS_ERROR_FAILURE); - return NS_OK; + domdoc->GetDocumentElement(aDOMElement); + NS_ENSURE_TRUE(*aDOMElement, NS_ERROR_FAILURE); + + return NS_OK; } NS_IMETHODIMP nsXULWindow::GetDOMElementById(char* aID, nsIDOMElement** aDOMElement) { - NS_ENSURE_STATE(mDocShell); - NS_ENSURE_ARG_POINTER(aDOMElement); + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_ARG_POINTER(aDOMElement); - *aDOMElement = nsnull; + *aDOMElement = nsnull; - nsCOMPtr cv; - - mDocShell->GetContentViewer(getter_AddRefs(cv)); - if(!cv) - return NS_ERROR_FAILURE; + nsCOMPtr cv; - nsCOMPtr docv(do_QueryInterface(cv)); - if(!docv) - return NS_ERROR_FAILURE; + mDocShell->GetContentViewer(getter_AddRefs(cv)); + if(!cv) + return NS_ERROR_FAILURE; - nsCOMPtr doc; - docv->GetDocument(getter_AddRefs(doc)); - nsCOMPtr domdoc(do_QueryInterface(doc)); - if(!domdoc) - return NS_ERROR_FAILURE; - - NS_ENSURE_SUCCESS(domdoc->GetElementById(NS_ConvertASCIItoUTF16(aID), aDOMElement), NS_ERROR_FAILURE); + nsCOMPtr docv(do_QueryInterface(cv)); + if(!docv) + return NS_ERROR_FAILURE; - return NS_OK; + nsCOMPtr doc; + docv->GetDocument(getter_AddRefs(doc)); + nsCOMPtr domdoc(do_QueryInterface(doc)); + if(!domdoc) + return NS_ERROR_FAILURE; + + NS_ENSURE_SUCCESS(domdoc->GetElementById(NS_ConvertASCIItoUTF16(aID), aDOMElement), NS_ERROR_FAILURE); + + return NS_OK; } nsresult nsXULWindow::ContentShellAdded(nsIDocShellTreeItem* aContentShell, @@ -1678,31 +1673,30 @@ nsresult nsXULWindow::ContentShellRemoved(nsIDocShellTreeItem* aContentShell) NS_IMETHODIMP nsXULWindow::SizeShellTo(nsIDocShellTreeItem* aShellItem, PRInt32 aCX, PRInt32 aCY) { - // XXXTAB This is wrong, we should actually reflow based on the passed in' - // shell. For now we are hacking and doing delta sizing. This is bad - // because it assumes all size we add will go to the shell which probably - // won't happen. + // XXXTAB This is wrong, we should actually reflow based on the passed in + // shell. For now we are hacking and doing delta sizing. This is bad + // because it assumes all size we add will go to the shell which probably + // won't happen. - nsCOMPtr shellAsWin(do_QueryInterface(aShellItem)); - NS_ENSURE_TRUE(shellAsWin, NS_ERROR_FAILURE); + nsCOMPtr shellAsWin(do_QueryInterface(aShellItem)); + NS_ENSURE_TRUE(shellAsWin, NS_ERROR_FAILURE); - PRInt32 width = 0; - PRInt32 height = 0; - shellAsWin->GetSize(&width, &height); + PRInt32 width = 0; + PRInt32 height = 0; + shellAsWin->GetSize(&width, &height); - PRInt32 widthDelta = aCX - width; - PRInt32 heightDelta = aCY - height; + PRInt32 widthDelta = aCX - width; + PRInt32 heightDelta = aCY - height; - if(widthDelta || heightDelta) - { - PRInt32 winCX = 0; - PRInt32 winCY = 0; + if (widthDelta || heightDelta) { + PRInt32 winCX = 0; + PRInt32 winCY = 0; - GetSize(&winCX, &winCY); - SetSize(winCX + widthDelta, winCY + heightDelta, PR_TRUE); - } + GetSize(&winCX, &winCY); + SetSize(winCX + widthDelta, winCY + heightDelta, PR_TRUE); + } - return NS_OK; + return NS_OK; } NS_IMETHODIMP nsXULWindow::ExitModalLoop(nsresult aStatus) @@ -1728,127 +1722,102 @@ NS_IMETHODIMP nsXULWindow::CreateNewWindow(PRInt32 aChromeFlags, NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(PRInt32 aChromeFlags, nsIAppShell* aAppShell, nsIXULWindow **_retval) { - NS_TIMELINE_ENTER("nsXULWindow::CreateNewChromeWindow"); - nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); - NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE); - - // Just do a normal create of a window and return. - //XXXTAB remove this when appshell talks in terms of nsIXULWindow - nsCOMPtr parent; - if(aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT) - parent = this; + NS_TIMELINE_ENTER("nsXULWindow::CreateNewChromeWindow"); + nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); + NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE); - nsCOMPtr newWindow; - appShell->CreateTopLevelWindow(parent, nsnull, aChromeFlags, - nsIAppShellService::SIZE_TO_CONTENT, - nsIAppShellService::SIZE_TO_CONTENT, - aAppShell, getter_AddRefs(newWindow)); + // Just do a normal create of a window and return. + //XXXTAB remove this when appshell talks in terms of nsIXULWindow + nsCOMPtr parent; + if(aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT) + parent = this; - NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE); + nsCOMPtr newWindow; + appShell->CreateTopLevelWindow(parent, nsnull, aChromeFlags, + nsIAppShellService::SIZE_TO_CONTENT, + nsIAppShellService::SIZE_TO_CONTENT, + aAppShell, getter_AddRefs(newWindow)); - newWindow->SetChromeFlags(aChromeFlags); + NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE); - *_retval = newWindow; - NS_ADDREF(*_retval); - - NS_TIMELINE_LEAVE("nsXULWindow::CreateNewChromeWindow done"); - return NS_OK; + newWindow->SetChromeFlags(aChromeFlags); + + *_retval = newWindow; + NS_ADDREF(*_retval); + + NS_TIMELINE_LEAVE("nsXULWindow::CreateNewChromeWindow done"); + return NS_OK; } NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(PRInt32 aChromeFlags, nsIAppShell* aAppShell, nsIXULWindow **_retval) { - NS_TIMELINE_ENTER("nsXULWindow::CreateNewContentWindow"); - nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); - NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE); + NS_TIMELINE_ENTER("nsXULWindow::CreateNewContentWindow"); - nsCOMPtr parent; - if(aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT) - parent = this; + nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); + NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE); - // We need to create a new top level window and then enter a nested - // loop. Eventually the new window will be told that it has loaded, - // at which time we know it is safe to spin out of the nested loop - // and allow the opening code to proceed. + nsCOMPtr parent; + if (aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT) + parent = this; - // First push a nested event queue for event processing from netlib - // onto our UI thread queue stack. - nsEventQueueStack queuePusher; - NS_ENSURE_SUCCESS(queuePusher.Success(), NS_ERROR_FAILURE); + // We need to create a new top level window and then enter a nested + // loop. Eventually the new window will be told that it has loaded, + // at which time we know it is safe to spin out of the nested loop + // and allow the opening code to proceed. - nsCOMPtr uri; + nsCOMPtr uri; - nsCOMPtr prefs(do_GetService(kPrefServiceCID)); - if (prefs) { - char *urlStr; - PRBool strAllocated = PR_TRUE; - nsresult prefres; - prefres = prefs->CopyCharPref("browser.chromeURL", &urlStr); - if (NS_SUCCEEDED(prefres) && urlStr[0] == '\0') { - PL_strfree(urlStr); - prefres = NS_ERROR_FAILURE; - } - if (NS_FAILED(prefres)) { - urlStr = "chrome://navigator/content/navigator.xul"; - strAllocated = PR_FALSE; - } + nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (prefs) { + nsXPIDLCString urlStr; + nsresult prefres; + prefres = prefs->GetCharPref("browser.chromeURL", getter_Copies(urlStr)); + if (NS_SUCCEEDED(prefres) && urlStr.IsEmpty()) + prefres = NS_ERROR_FAILURE; + if (NS_FAILED(prefres)) + urlStr.AssignLiteral("chrome://navigator/content/navigator.xul"); - nsCOMPtr service(do_GetService(kIOServiceCID)); - if (service) - service->NewURI(nsDependentCString(urlStr), nsnull, nsnull, getter_AddRefs(uri)); - if (strAllocated) - PL_strfree(urlStr); - } - NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE); + nsCOMPtr service(do_GetService(NS_IOSERVICE_CONTRACTID)); + if (service) + service->NewURI(urlStr, nsnull, nsnull, getter_AddRefs(uri)); + } + NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE); - nsCOMPtr newWindow; - appShell->CreateTopLevelWindow(parent, uri, - aChromeFlags, 615, 480, aAppShell, - getter_AddRefs(newWindow)); + nsCOMPtr newWindow; + appShell->CreateTopLevelWindow(parent, uri, + aChromeFlags, 615, 480, aAppShell, + getter_AddRefs(newWindow)); - NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE); + NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE); - newWindow->SetChromeFlags(aChromeFlags); + newWindow->SetChromeFlags(aChromeFlags); - nsCOMPtr subShell(do_CreateInstance(kAppShellCID)); - NS_ENSURE_TRUE(subShell, NS_ERROR_FAILURE); + // Specify that we want the window to remain locked until the chrome has loaded. + nsXULWindow *xulWin = NS_STATIC_CAST(nsXULWindow*, + NS_STATIC_CAST(nsIXULWindow*, + newWindow)); - subShell->Create(0, nsnull); - subShell->Spinup(); + xulWin->LockUntilChromeLoad(); - // Specify that we want the window to remain locked until the chrome has loaded. - nsXULWindow *xulWin = NS_STATIC_CAST(nsXULWindow*, - NS_STATIC_CAST(nsIXULWindow*, - newWindow)); + // Push nsnull onto the JSContext stack before we dispatch a native event. + nsCOMPtr stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1")); + if (stack && NS_SUCCEEDED(stack->Push(nsnull))) { + nsIThread *thread = NS_GetCurrentThread(); + while (xulWin->IsLocked()) { + if (!NS_ProcessNextEvent(thread)) + break; + } + JSContext *cx; + stack->Pop(&cx); + NS_ASSERTION(cx == nsnull, "JSContextStack mismatch"); + } - xulWin->LockUntilChromeLoad(); + *_retval = newWindow; + NS_ADDREF(*_retval); - // Push nsnull onto the JSContext stack before we dispatch a native event. - nsCOMPtr stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1")); - if(stack && NS_SUCCEEDED(stack->Push(nsnull))) - { - nsresult looprv = NS_OK; - while(NS_SUCCEEDED(looprv) && xulWin->IsLocked()) - { - void *data; - PRBool isRealEvent; - - looprv = subShell->GetNativeEvent(isRealEvent, data); - subShell->DispatchNativeEvent(isRealEvent, data); - } - - JSContext *cx; - stack->Pop(&cx); - NS_ASSERTION(cx == nsnull, "JSContextStack mismatch"); - } - - subShell->Spindown(); - - *_retval = newWindow; - NS_ADDREF(*_retval); - - NS_TIMELINE_LEAVE("nsXULWindow::CreateNewContentWindow"); - return NS_OK; + NS_TIMELINE_LEAVE("nsXULWindow::CreateNewContentWindow"); + return NS_OK; } void nsXULWindow::EnableParent(PRBool aEnable) @@ -2012,8 +1981,8 @@ void nsXULWindow::PlaceWindowLayersBehind(PRUint32 aLowLevel, } } -void nsXULWindow::SetContentScrollbarVisibility(PRBool aVisible) { - +void nsXULWindow::SetContentScrollbarVisibility(PRBool aVisible) +{ nsCOMPtr contentWin(do_GetInterface(mPrimaryContentShell)); if (contentWin) { nsCOMPtr scrollbars; @@ -2023,8 +1992,8 @@ void nsXULWindow::SetContentScrollbarVisibility(PRBool aVisible) { } } -PRBool nsXULWindow::GetContentScrollbarVisibility() { - +PRBool nsXULWindow::GetContentScrollbarVisibility() +{ PRBool visible = PR_TRUE; nsCOMPtr contentWin(do_GetInterface(mPrimaryContentShell)); @@ -2038,8 +2007,8 @@ PRBool nsXULWindow::GetContentScrollbarVisibility() { } // during spinup, attributes that haven't been loaded yet can't be dirty -void nsXULWindow::PersistentAttributesDirty(PRUint32 aDirtyFlags) { - +void nsXULWindow::PersistentAttributesDirty(PRUint32 aDirtyFlags) +{ mPersistentAttributesDirty |= aDirtyFlags & mPersistentAttributesMask; } @@ -2126,29 +2095,3 @@ nsContentShellInfo::~nsContentShellInfo() MOZ_COUNT_DTOR(nsContentShellInfo); //XXX Set Tree Owner to null if the tree owner is nsXULWindow->mContentTreeOwner } - -//***************************************************************************** -//*** nsEventQueueStack: Object Implementation -//***************************************************************************** - -nsEventQueueStack::nsEventQueueStack() : mQueue(nsnull) -{ - mService = do_GetService(kEventQueueServiceCID); - - if(mService) - mService->PushThreadEventQueue(getter_AddRefs(mQueue)); -} -nsEventQueueStack::~nsEventQueueStack() -{ - if(mQueue) - mService->PopThreadEventQueue(mQueue); - mService = nsnull; -} - -nsresult nsEventQueueStack::Success() -{ - return mQueue ? NS_OK : NS_ERROR_FAILURE; -} - - - diff --git a/mozilla/xpfe/appshell/src/nsXULWindow.h b/mozilla/xpfe/appshell/src/nsXULWindow.h index fc929fcbc51..fc9fa2e259a 100644 --- a/mozilla/xpfe/appshell/src/nsXULWindow.h +++ b/mozilla/xpfe/appshell/src/nsXULWindow.h @@ -56,7 +56,6 @@ #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" #include "nsIDOMWindowInternal.h" -#include "nsIEventQueueService.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIWidget.h" @@ -199,20 +198,4 @@ public: nsWeakPtr child; // content shell (weak reference to nsIDocShellTreeItem) }; -// nsEventQueueStack -// a little utility object to push an event queue and pop it when it -// goes out of scope. should probably be in a file of utility functions. -class nsEventQueueStack -{ -public: - nsEventQueueStack(); - ~nsEventQueueStack(); - - nsresult Success(); - -protected: - nsCOMPtr mService; - nsCOMPtr mQueue; -}; - #endif /* nsXULWindow_h__ */ diff --git a/mozilla/xpfe/bootstrap/nsAppRunner.cpp b/mozilla/xpfe/bootstrap/nsAppRunner.cpp index 60b88ceb725..c7fda56b325 100644 --- a/mozilla/xpfe/bootstrap/nsAppRunner.cpp +++ b/mozilla/xpfe/bootstrap/nsAppRunner.cpp @@ -61,7 +61,6 @@ #include "nsIPrefService.h" #include "nsIPrefBranch.h" #include "nsILocaleService.h" -#include "plevent.h" #include "prmem.h" #include "prenv.h" #include "prnetdb.h" @@ -85,7 +84,6 @@ #include "nsICategoryManager.h" #include "nsIXULWindow.h" #include "nsIChromeRegistrySea.h" -#include "nsIEventQueueService.h" #include "nsDirectoryServiceDefs.h" #include "nsBuildID.h" #include "nsIWindowCreator.h" @@ -1033,14 +1031,6 @@ static nsresult main1(int argc, char* argv[], nsISupports *nativeApp ) fpsetmask(0); #endif - NS_TIMELINE_ENTER("init event service"); - nsCOMPtr eventQService(do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv)); - if (NS_SUCCEEDED(rv)) { - // XXX: What if this fails? - rv = eventQService->CreateThreadEventQueue(); - } - NS_TIMELINE_LEAVE("init event service"); - // Setup an autoreg obserer, so that we can update a progress // string in the splash screen nsCOMPtr obsService(do_GetService("@mozilla.org/observer-service;1")); diff --git a/mozilla/xpfe/browser/src/nsBrowserInstance.cpp b/mozilla/xpfe/browser/src/nsBrowserInstance.cpp index cd99ce7dee2..d30c4292868 100644 --- a/mozilla/xpfe/browser/src/nsBrowserInstance.cpp +++ b/mozilla/xpfe/browser/src/nsBrowserInstance.cpp @@ -69,15 +69,16 @@ #include "nsIWebBrowserChrome.h" #include "nsIWindowWatcher.h" #include "nsCOMPtr.h" +#include "nsAutoPtr.h" #include "nsXPIDLString.h" #include "nsReadableUtils.h" +#include "nsThreadUtils.h" #include "nsIPref.h" #include "nsIServiceManager.h" #include "nsIURL.h" #include "nsIIOService.h" #include "nsIWidget.h" -#include "plevent.h" #include "plstr.h" #include "nsIAppStartup.h" @@ -108,7 +109,6 @@ /* Define Class IDs */ static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); -static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); #ifdef DEBUG static int APP_DEBUG = 0; // Set to 1 in debugger to turn on debugging. @@ -129,7 +129,6 @@ const char *kIgnoreOverrideMilestone = "ignore"; //***************************************************************************** #ifdef ENABLE_PAGE_CYCLER -#include "nsIProxyObjectManager.h" #include "nsITimer.h" static void TimesUp(nsITimer *aTimer, void *aClosure); @@ -139,7 +138,14 @@ class PageCycler : public nsIObserver { public: NS_DECL_ISUPPORTS - PLEvent mEvent; + struct PageCyclerEvent : public nsRunnable { + PageCyclerEvent(PageCycler *pc) : mPageCycler(pc) {} + NS_IMETHOD Run() { + mPageCycler->DoCycle(); + return NS_OK; + } + nsRefPtr mPageCycler; + }; PageCycler(nsBrowserInstance* appCore, const char *aTimeoutValue = nsnull, const char *aWaitValue = nsnull) : mAppCore(appCore), mBuffer(nsnull), mCursor(nsnull), mTimeoutValue(0), mWaitValue(1 /*sec*/) { @@ -223,13 +229,11 @@ public: nsCOMPtr appStartup = do_GetService(NS_APPSTARTUP_CONTRACTID, &rv); if(NS_FAILED(rv)) return rv; - nsCOMPtr pIProxyObjectManager = - do_GetService(kProxyObjectManagerCID, &rv); - if(NS_FAILED(rv)) return rv; nsCOMPtr appStartupProxy; - rv = pIProxyObjectManager->GetProxyForObject(NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIAppStartup), - appStartup, PROXY_ASYNC | PROXY_ALWAYS, - getter_AddRefs(appStartupProxy)); + rv = NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, + NS_GET_IID(nsIAppStartup), appStartup, + NS_PROXY_ASYNC | NS_PROXY_ALWAYS, + getter_AddRefs(appStartupProxy)); (void)appStartupProxy->Quit(nsIAppStartup::eAttemptQuit); return NS_ERROR_FAILURE; @@ -268,23 +272,9 @@ public: // otherwise we'll run the risk of confusing the docshell // (which notifies observers before propagating the // DocumentEndLoad up to parent docshells). - nsCOMPtr eqs - = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID); - - rv = NS_ERROR_FAILURE; - - if (eqs) { - nsCOMPtr eq; - eqs->ResolveEventQueue(NS_UI_THREAD_EVENTQ, getter_AddRefs(eq)); - if (eq) { - rv = eq->InitEvent(&mEvent, this, HandleAsyncLoadEvent, - DestroyAsyncLoadEvent); - - if (NS_SUCCEEDED(rv)) { - rv = eq->PostEvent(&mEvent); - } - } - } + nsCOMPtr ev = new PageCyclerEvent(this); + if (ev) + rv = NS_DispatchToCurrentThread(ev); if (NS_FAILED(rv)) { printf("######### PageCycler couldn't asynchronously load: %s\n", NS_ConvertUTF16toUTF8(mLastRequest).get()); @@ -299,27 +289,19 @@ public: return rv; } - static void* PR_CALLBACK - HandleAsyncLoadEvent(PLEvent* aEvent) + void DoCycle() { - // This is the callback that actually loads the page - PageCycler* self = NS_STATIC_CAST(PageCycler*, PL_GetEventOwner(aEvent)); - // load the URL - const PRUnichar* url = self->mLastRequest.get(); + const PRUnichar* url = mLastRequest.get(); printf("########## PageCycler starting: %s\n", NS_ConvertUTF16toUTF8(url).get()); - self->mIntervalTime = PR_IntervalNow(); - self->mAppCore->LoadUrl(url); + mIntervalTime = PR_IntervalNow(); + mAppCore->LoadUrl(url); // start new timer - self->StartTimer(); - return nsnull; + StartTimer(); } - static void PR_CALLBACK - DestroyAsyncLoadEvent(PLEvent* aEvent) { /*no-op*/ } - const nsAutoString &GetLastRequest( void ) { return mLastRequest; diff --git a/mozilla/xpfe/components/startup/src/nsAppStartup.cpp b/mozilla/xpfe/components/startup/src/nsAppStartup.cpp index 5b5157203fe..83167df3eb2 100644 --- a/mozilla/xpfe/components/startup/src/nsAppStartup.cpp +++ b/mozilla/xpfe/components/startup/src/nsAppStartup.cpp @@ -45,8 +45,6 @@ #include "nsICloseAllWindows.h" #include "nsICmdLineService.h" #include "nsIDOMWindowInternal.h" -#include "nsIEventQueue.h" -#include "nsIEventQueueService.h" #include "nsIInterfaceRequestor.h" #include "nsILocalFile.h" #include "nsIObserverService.h" @@ -63,6 +61,8 @@ #include "nsIWindowWatcher.h" #include "nsIXULWindow.h" #include "nsNativeCharsetUtils.h" +#include "nsThreadUtils.h" +#include "nsAutoPtr.h" #include "prprf.h" #include "nsCRT.h" @@ -72,6 +72,25 @@ #include "nsXPFEComponentsCID.h" #include "nsEmbedCID.h" +class nsAppStartupExitEvent : public nsRunnable +{ +public: + nsAppStartupExitEvent(nsAppStartup *service) + : mService(service) {} + + NS_IMETHOD Run() { + // Tell the appshell to exit + mService->mAppShell->Exit(); + + // We're done "shutting down". + mService->mShuttingDown = PR_FALSE; + return NS_OK; + } + +private: + nsRefPtr mService; +}; + NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); // @@ -114,21 +133,13 @@ nsAppStartup::Initialize(nsISupports *aNativeAppSupportOrSplashScreen) mSplashScreen = do_QueryInterface(aNativeAppSupportOrSplashScreen); // Create widget application shell - mAppShell = do_CreateInstance(kAppShellCID, &rv); + mAppShell = do_GetService(kAppShellCID, &rv); NS_ENSURE_SUCCESS(rv, rv); - rv = mAppShell->Create(nsnull, nsnull); - NS_ENSURE_SUCCESS(rv, rv); - - // listen to EventQueues' comings and goings. do this after the appshell - // has been created, but after the event queue has been created. that - // latter bit is unfortunate, but we deal with it. nsCOMPtr os (do_GetService("@mozilla.org/observer-service;1", &rv)); NS_ENSURE_SUCCESS(rv, rv); - os->AddObserver(this, "nsIEventQueueActivated", PR_TRUE); - os->AddObserver(this, "nsIEventQueueDestroyed", PR_TRUE); os->AddObserver(this, "skin-selected", PR_TRUE); os->AddObserver(this, "locale-selected", PR_TRUE); os->AddObserver(this, "xpinstall-restart", PR_TRUE); @@ -356,34 +367,16 @@ nsAppStartup::Quit(PRUint32 aFerocity) // no matter what, make sure we send the exit event. If // worst comes to worst, we'll do a leaky shutdown but we WILL // shut down. Well, assuming that all *this* stuff works ;-). - nsCOMPtr svc = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv)) { - - nsCOMPtr queue; - rv = svc->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); + nsCOMPtr event = new nsAppStartupExitEvent(this); + if (event) { + rv = NS_DispatchToCurrentThread(event); if (NS_SUCCEEDED(rv)) { - - PLEvent* event = new PLEvent; - if (event) { - NS_ADDREF_THIS(); - PL_InitEvent(event, - this, - HandleExitEvent, - DestroyExitEvent); - - rv = queue->PostEvent(event); - if (NS_SUCCEEDED(rv)) { - postedExitEvent = PR_TRUE; - } - else { - PL_DestroyEvent(event); - } - } - else { - rv = NS_ERROR_OUT_OF_MEMORY; - } + postedExitEvent = PR_TRUE; } } + else { + rv = NS_ERROR_OUT_OF_MEMORY; + } } // turn off the reentrancy check flag, but not if we have @@ -672,32 +665,6 @@ nsAppStartup::Ensure1Window(nsICmdLineService *aCmdLineService) return rv; } - -void* PR_CALLBACK -nsAppStartup::HandleExitEvent(PLEvent* aEvent) -{ - nsAppStartup *service = - NS_REINTERPRET_CAST(nsAppStartup*, aEvent->owner); - - // Tell the appshell to exit - service->mAppShell->Exit(); - - // We're done "shutting down". - service->mShuttingDown = PR_FALSE; - - return nsnull; -} - -void PR_CALLBACK -nsAppStartup::DestroyExitEvent(PLEvent* aEvent) -{ - nsAppStartup *service = - NS_REINTERPRET_CAST(nsAppStartup*, aEvent->owner); - NS_RELEASE(service); - delete aEvent; -} - - nsresult nsAppStartup::LaunchTask(const char *aParam, PRInt32 height, PRInt32 width, PRBool *windowOpened) { @@ -918,27 +885,9 @@ nsAppStartup::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { NS_ASSERTION(mAppShell, "appshell service notified before appshell built"); - if (!strcmp(aTopic, "nsIEventQueueActivated")) { - nsCOMPtr eq(do_QueryInterface(aSubject)); - if (eq) { - PRBool isNative = PR_TRUE; - // we only add native event queues to the appshell - eq->IsQueueNative(&isNative); - if (isNative) - mAppShell->ListenToEventQueue(eq, PR_TRUE); - } - } else if (!strcmp(aTopic, "nsIEventQueueDestroyed")) { - nsCOMPtr eq(do_QueryInterface(aSubject)); - if (eq) { - PRBool isNative = PR_TRUE; - // we only remove native event queues from the appshell - eq->IsQueueNative(&isNative); - if (isNative) - mAppShell->ListenToEventQueue(eq, PR_FALSE); - } - } else if (!strcmp(aTopic, "skin-selected") || - !strcmp(aTopic, "locale-selected") || - !strcmp(aTopic, "xpinstall-restart")) { + if (!strcmp(aTopic, "skin-selected") || + !strcmp(aTopic, "locale-selected") || + !strcmp(aTopic, "xpinstall-restart")) { if (mNativeAppSupport) mNativeAppSupport->SetIsServerMode(PR_FALSE); } else if (!strcmp(aTopic, "profile-change-teardown")) { diff --git a/mozilla/xpfe/components/startup/src/nsAppStartup.h b/mozilla/xpfe/components/startup/src/nsAppStartup.h index e4f963c3880..df4b464775a 100644 --- a/mozilla/xpfe/components/startup/src/nsAppStartup.h +++ b/mozilla/xpfe/components/startup/src/nsAppStartup.h @@ -72,14 +72,12 @@ public: nsAppStartup(); private: + friend class nsAppStartupExitEvent; + ~nsAppStartup() { } void AttemptingQuit(PRBool aAttempt); - // A "last event" that is used to flush the appshell's event queue. - PR_STATIC_CALLBACK(void*) HandleExitEvent(PLEvent* aEvent); - PR_STATIC_CALLBACK(void) DestroyExitEvent(PLEvent* aEvent); - nsresult CheckAndRemigrateDefunctProfile(); nsresult LaunchTask(const char* aParam, PRInt32 height, PRInt32 width, diff --git a/mozilla/xpinstall/src/nsInstall.cpp b/mozilla/xpinstall/src/nsInstall.cpp index a5621aa03a0..678c195dd52 100644 --- a/mozilla/xpinstall/src/nsInstall.cpp +++ b/mozilla/xpinstall/src/nsInstall.cpp @@ -56,6 +56,7 @@ #include "nsDirectoryServiceDefs.h" #include "nsAppDirectoryServiceDefs.h" #include "nsDirectoryServiceUtils.h" +#include "nsThreadUtils.h" #include "nsNetUtil.h" @@ -111,9 +112,6 @@ #include #endif -static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); -static NS_DEFINE_IID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); - static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); #define kInstallLocaleProperties "chrome://global/locale/commonDialogs.properties" @@ -188,9 +186,11 @@ nsInstallInfo::nsInstallInfo(PRUint32 aInstallType, // Failure is an option, and will occur in the stub installer. + nsCOMPtr thread = do_GetMainThread(); + NS_WITH_ALWAYS_PROXIED_SERVICE(CHROMEREG_IFACE, cr, NS_CHROMEREGISTRY_CONTRACTID, - NS_UI_THREAD_EVENTQ, &rv); + thread, &rv); if (NS_SUCCEEDED(rv)) { mChromeRegistry = cr; @@ -210,7 +210,7 @@ nsInstallInfo::nsInstallInfo(PRUint32 aInstallType, #ifdef MOZ_XUL_APP NS_WITH_ALWAYS_PROXIED_SERVICE(nsIExtensionManager, em, "@mozilla.org/extensions/manager;1", - NS_UI_THREAD_EVENTQ, &rv); + thread, &rv); if (NS_SUCCEEDED(rv)) mExtensionManager = em; @@ -261,12 +261,14 @@ nsInstall::nsInstall(nsIZipReader * theJARFile) su->Release(); + nsCOMPtr thread = do_GetMainThread(); + // get the resourced xpinstall string bundle mStringBundle = nsnull; NS_WITH_PROXIED_SERVICE( nsIStringBundleService, service, kStringBundleServiceCID, - NS_UI_THREAD_EVENTQ, + thread, &rv ); if (NS_SUCCEEDED(rv) && service) @@ -1207,7 +1209,6 @@ nsInstall::LoadResources(JSContext* cx, const nsString& aBaseName, jsval* aRetur nsCOMPtr resFile; nsIURI *url = nsnull; nsIStringBundleService* service = nsnull; - nsIEventQueueService* pEventQueueService = nsnull; nsIStringBundle* bundle = nsnull; nsCOMPtr propEnum; jsval v = JSVAL_NULL; @@ -1232,13 +1233,6 @@ nsInstall::LoadResources(JSContext* cx, const nsString& aBaseName, jsval* aRetur // initialize string bundle and related services ret = CallGetService(kStringBundleServiceCID, &service); - if (NS_FAILED(ret)) - goto cleanup; - ret = CallGetService(kEventQueueServiceCID, &pEventQueueService); - if (NS_FAILED(ret)) - goto cleanup; - ret = pEventQueueService->CreateThreadEventQueue(); - NS_RELEASE(pEventQueueService); if (NS_FAILED(ret)) goto cleanup; @@ -1393,14 +1387,11 @@ nsPIXPIProxy* nsInstall::GetUIThreadProxy() if (!mUIThreadProxy) { nsresult rv; - nsCOMPtr pmgr = - do_GetService(kProxyObjectManagerCID, &rv); - if (NS_SUCCEEDED(rv)) - { - nsCOMPtr tmp(do_QueryInterface(new nsXPIProxy())); - rv = pmgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsPIXPIProxy), - tmp, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs(mUIThreadProxy) ); - } + nsCOMPtr tmp(do_QueryInterface(new nsXPIProxy())); + rv = NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsPIXPIProxy), tmp, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs(mUIThreadProxy) ); } return mUIThreadProxy; diff --git a/mozilla/xpinstall/src/nsInstall.h b/mozilla/xpinstall/src/nsInstall.h index 13c166c7013..bef51d8b4eb 100644 --- a/mozilla/xpinstall/src/nsInstall.h +++ b/mozilla/xpinstall/src/nsInstall.h @@ -46,8 +46,6 @@ #include "jsapi.h" -#include "plevent.h" - #include "nsString.h" #include "nsVoidArray.h" #include "nsHashtable.h" @@ -66,7 +64,6 @@ #include "nsIStringBundle.h" #include "nsILocale.h" -#include "nsIEventQueueService.h" #include "nsIServiceManager.h" #include "nsIComponentManager.h" #include "nsIEnumerator.h" diff --git a/mozilla/xpinstall/src/nsInstallFolder.cpp b/mozilla/xpinstall/src/nsInstallFolder.cpp index cec3fb39adb..663406e8f43 100644 --- a/mozilla/xpinstall/src/nsInstallFolder.cpp +++ b/mozilla/xpinstall/src/nsInstallFolder.cpp @@ -58,8 +58,7 @@ #ifdef XP_WIN #include #include -#include -#include +#include #endif struct DirectoryTable diff --git a/mozilla/xpinstall/src/nsSoftwareUpdate.cpp b/mozilla/xpinstall/src/nsSoftwareUpdate.cpp index e8caa8f872b..cb6a9b0c9d6 100644 --- a/mozilla/xpinstall/src/nsSoftwareUpdate.cpp +++ b/mozilla/xpinstall/src/nsSoftwareUpdate.cpp @@ -78,9 +78,6 @@ #include "nsIScriptNameSpaceManager.h" #include "nsIScriptExternalNameSet.h" -#include "nsIEventQueueService.h" -#include "nsIProxyObjectManager.h" -#include "nsProxiedService.h" #include "nsIChromeRegistry.h" #include "nsCURILoader.h" diff --git a/mozilla/xpinstall/src/nsSoftwareUpdateRun.cpp b/mozilla/xpinstall/src/nsSoftwareUpdateRun.cpp index 342ea27a582..47e7fca45db 100644 --- a/mozilla/xpinstall/src/nsSoftwareUpdateRun.cpp +++ b/mozilla/xpinstall/src/nsSoftwareUpdateRun.cpp @@ -57,7 +57,6 @@ #include "plstr.h" #include "jsapi.h" -#include "nsIEventQueueService.h" #include "nsIEnumerator.h" #include "nsIZipReader.h" #include "nsIJSRuntimeService.h" @@ -77,7 +76,6 @@ #include "nsIExtensionManager.h" static NS_DEFINE_CID(kSoftwareUpdateCID, NS_SoftwareUpdate_CID); -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); extern JSObject *InitXPInstallObjects(JSContext *jscontext, JSObject *global, nsIFile* jarfile, const PRUnichar* url, @@ -479,16 +477,6 @@ extern "C" void RunInstallOnThread(void *data) nsCOMPtr listener; - // lets set up an eventQ so that our xpcom/proxies will not have to: - nsCOMPtr eventQ; - nsCOMPtr eventQService = - do_GetService(kEventQueueServiceCID, &rv); - if (NS_SUCCEEDED(rv)) - { - eventQService->CreateMonitoredThreadEventQueue(); - eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eventQ)); - } - nsCOMPtr softwareUpdate = do_GetService(kSoftwareUpdateCID, &rv); diff --git a/mozilla/xpinstall/src/nsWinReg.h b/mozilla/xpinstall/src/nsWinReg.h index 7b33761425c..87bbd591f5d 100644 --- a/mozilla/xpinstall/src/nsWinReg.h +++ b/mozilla/xpinstall/src/nsWinReg.h @@ -46,8 +46,6 @@ #include "jsapi.h" -#include "plevent.h" - #include "nsString.h" #include "nsHashtable.h" diff --git a/mozilla/xpinstall/src/nsXPITriggerInfo.cpp b/mozilla/xpinstall/src/nsXPITriggerInfo.cpp index 3d0799a4733..e71e342f09c 100644 --- a/mozilla/xpinstall/src/nsXPITriggerInfo.cpp +++ b/mozilla/xpinstall/src/nsXPITriggerInfo.cpp @@ -42,14 +42,13 @@ #include "nsXPITriggerInfo.h" #include "nsNetUtil.h" #include "nsDebug.h" +#include "nsAutoPtr.h" +#include "nsThreadUtils.h" #include "nsIServiceManager.h" -#include "nsIEventQueueService.h" #include "nsIJSContextStack.h" #include "nsIScriptSecurityManager.h" #include "nsICryptoHash.h" -static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - // // nsXPITriggerItem // @@ -225,7 +224,7 @@ void nsXPITriggerInfo::SaveCallback( JSContext *aCx, jsval aVal ) } mCbval = aVal; - mThread = PR_GetCurrentThread(); + mThread = do_GetCurrentThread(); if ( !JSVAL_IS_NULL(mCbval) ) { JS_BeginRequest(mCx); @@ -234,26 +233,24 @@ void nsXPITriggerInfo::SaveCallback( JSContext *aCx, jsval aVal ) } } -PR_STATIC_CALLBACK(void) destroyTriggerEvent(PLEvent* aEvent) +XPITriggerEvent::~XPITriggerEvent() { - XPITriggerEvent *event = NS_STATIC_CAST(XPITriggerEvent*, aEvent); - JS_BeginRequest(event->cx); - JS_RemoveRoot( event->cx, &event->cbval ); - JS_EndRequest(event->cx); - delete event; + JS_BeginRequest(cx); + JS_RemoveRoot(cx, &cbval); + JS_EndRequest(cx); } -PR_STATIC_CALLBACK(void*) handleTriggerEvent(PLEvent* aEvent) +NS_IMETHODIMP +XPITriggerEvent::Run() { - XPITriggerEvent *event = NS_STATIC_CAST(XPITriggerEvent*, aEvent); jsval ret; void* mark; jsval* args; - JS_BeginRequest(event->cx); - args = JS_PushArguments( event->cx, &mark, "Wi", - event->URL.get(), - event->status ); + JS_BeginRequest(cx); + args = JS_PushArguments(cx, &mark, "Wi", + URL.get(), + status); if ( args ) { // This code is all in a JS request, and here we're about to @@ -266,7 +263,7 @@ PR_STATIC_CALLBACK(void*) handleTriggerEvent(PLEvent* aEvent) nsCOMPtr stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); if (stack) - stack->Push(event->cx); + stack->Push(cx); nsCOMPtr secman = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); @@ -289,7 +286,7 @@ PR_STATIC_CALLBACK(void*) handleTriggerEvent(PLEvent* aEvent) if (!errorStr) { PRBool equals = PR_FALSE; - principal->Equals(event->princ, &equals); + principal->Equals(princ, &equals); if (!equals) { @@ -299,13 +296,13 @@ PR_STATIC_CALLBACK(void*) handleTriggerEvent(PLEvent* aEvent) if (errorStr) { - JS_ReportError(event->cx, errorStr); + JS_ReportError(cx, errorStr); } else { - JS_CallFunctionValue(event->cx, - JSVAL_TO_OBJECT(event->global), - event->cbval, + JS_CallFunctionValue(cx, + JSVAL_TO_OBJECT(global), + cbval, 2, args, &ret); @@ -314,9 +311,9 @@ PR_STATIC_CALLBACK(void*) handleTriggerEvent(PLEvent* aEvent) if (stack) stack->Pop(nsnull); - JS_PopArguments( event->cx, mark ); + JS_PopArguments(cx, mark); } - JS_EndRequest(event->cx); + JS_EndRequest(cx); return 0; } @@ -324,59 +321,45 @@ PR_STATIC_CALLBACK(void*) handleTriggerEvent(PLEvent* aEvent) void nsXPITriggerInfo::SendStatus(const PRUnichar* URL, PRInt32 status) { - nsCOMPtr eq; nsresult rv; if ( mCx && mGlobalWrapper && mCbval ) { - nsCOMPtr EQService = - do_GetService(kEventQueueServiceCID, &rv); - if ( NS_SUCCEEDED( rv ) ) + // create event and post it + nsRefPtr event = new XPITriggerEvent(); + if (event) { - rv = EQService->GetThreadEventQueue(mThread, getter_AddRefs(eq)); - if ( NS_SUCCEEDED(rv) ) - { - // create event and post it - XPITriggerEvent* event = new XPITriggerEvent(); - if (event) - { - PL_InitEvent(event, 0, - handleTriggerEvent, - destroyTriggerEvent); + event->URL = URL; + event->status = status; + event->cx = mCx; + event->princ = mPrincipal; - event->URL = URL; - event->status = status; - event->cx = mCx; - event->princ = mPrincipal; + JSObject *obj = nsnull; - JSObject *obj = nsnull; + mGlobalWrapper->GetJSObject(&obj); - mGlobalWrapper->GetJSObject(&obj); + event->global = OBJECT_TO_JSVAL(obj); - event->global = OBJECT_TO_JSVAL(obj); + event->cbval = mCbval; + JS_BeginRequest(event->cx); + JS_AddNamedRoot(event->cx, &event->cbval, + "XPITriggerEvent::cbval" ); + JS_EndRequest(event->cx); - event->cbval = mCbval; - JS_BeginRequest(event->cx); - JS_AddNamedRoot( event->cx, &event->cbval, - "XPITriggerEvent::cbval" ); - JS_EndRequest(event->cx); + // Hold a strong reference to keep the underlying + // JSContext from dying before we handle this event. + event->ref = mGlobalWrapper; - // Hold a strong reference to keep the underlying - // JSContext from dying before we handle this event. - event->ref = mGlobalWrapper; - - eq->PostEvent(event); - } - else - rv = NS_ERROR_OUT_OF_MEMORY; - } + rv = mThread->Dispatch(event, NS_DISPATCH_NORMAL); } + else + rv = NS_ERROR_OUT_OF_MEMORY; if ( NS_FAILED( rv ) ) { // couldn't get event queue -- maybe window is gone or // some similarly catastrophic occurrance + NS_WARNING("failed to dispatch XPITriggerEvent"); } } } - diff --git a/mozilla/xpinstall/src/nsXPITriggerInfo.h b/mozilla/xpinstall/src/nsXPITriggerInfo.h index 00dadcd2811..7301797e872 100644 --- a/mozilla/xpinstall/src/nsXPITriggerInfo.h +++ b/mozilla/xpinstall/src/nsXPITriggerInfo.h @@ -48,12 +48,12 @@ #include "nsIOutputStream.h" #include "jsapi.h" #include "prthread.h" -#include "plevent.h" #include "nsIXPConnect.h" #include "nsICryptoHash.h" #include "nsIPrincipal.h" +#include "nsThreadUtils.h" -struct XPITriggerEvent : public PLEvent { +struct XPITriggerEvent : public nsRunnable { nsString URL; PRInt32 status; JSContext* cx; @@ -61,10 +61,11 @@ struct XPITriggerEvent : public PLEvent { jsval cbval; nsCOMPtr ref; nsCOMPtr princ; + + virtual ~XPITriggerEvent(); + NS_IMETHOD Run(); }; - - class nsXPITriggerItem { public: @@ -133,7 +134,7 @@ class nsXPITriggerInfo JSContext *mCx; nsCOMPtr mGlobalWrapper; jsval mCbval; - PRThread* mThread; + nsCOMPtr mThread; nsCOMPtr mPrincipal; diff --git a/mozilla/xpinstall/src/nsXPInstallManager.cpp b/mozilla/xpinstall/src/nsXPInstallManager.cpp index c4181a61d4d..4975edbb699 100644 --- a/mozilla/xpinstall/src/nsXPInstallManager.cpp +++ b/mozilla/xpinstall/src/nsXPInstallManager.cpp @@ -86,11 +86,8 @@ #include "nsEmbedCID.h" -static NS_DEFINE_IID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); static NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); -#include "nsIEventQueueService.h" - #define PREF_XPINSTALL_ENABLED "xpinstall.enabled" #define PREF_XPINSTALL_CONFIRM_DLG "xpinstall.dialog.confirm" #define PREF_XPINSTALL_STATUS_DLG_SKIN "xpinstall.dialog.progress.skin" @@ -547,16 +544,11 @@ NS_IMETHODIMP nsXPInstallManager::Observe( nsISupports *aSubject, if (dlg) { // --- create and save a proxy for the dialog - nsCOMPtr pmgr = - do_GetService(kProxyObjectManagerCID, &rv); - if (pmgr) - { - rv = pmgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, - NS_GET_IID(nsIXPIProgressDialog), - dlg, - PROXY_SYNC | PROXY_ALWAYS, - getter_AddRefs(mDlg) ); - } + rv = NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIXPIProgressDialog), + dlg, + NS_PROXY_SYNC | NS_PROXY_ALWAYS, + getter_AddRefs(mDlg) ); } // -- get the ball rolling