From 588868b60c9a5e6e9d49c50b5db71f43be32598d Mon Sep 17 00:00:00 2001 From: "danm%netscape.com" Date: Mon, 18 Oct 1999 14:59:57 +0000 Subject: [PATCH] event queues own and delete themselves when they're done. bug 15856 r:hyatt@netscape.com --- xpcom/threads/nsEventQueue.cpp | 197 ++++++++++++++++++++++--- xpcom/threads/nsEventQueue.h | 49 +++++-- xpcom/threads/nsEventQueueService.cpp | 202 ++++++++++++++++---------- xpcom/threads/nsEventQueueService.h | 56 +------ xpcom/threads/nsIEventQueue.h | 12 +- xpcom/threads/nsIEventQueueService.h | 12 +- 6 files changed, 359 insertions(+), 169 deletions(-) diff --git a/xpcom/threads/nsEventQueue.cpp b/xpcom/threads/nsEventQueue.cpp index b9e9157003e5..6be32c56491d 100644 --- a/xpcom/threads/nsEventQueue.cpp +++ b/xpcom/threads/nsEventQueue.cpp @@ -17,19 +17,37 @@ * Netscape Communications Corporation. All Rights Reserved. */ +#include "nsCOMPtr.h" #include "nsEventQueue.h" +#include "nsIServiceManager.h" +#include "nsIObserverService.h" +#include "nsString2.h" + +// in a real system, these would be members in a header class... +static char *gActivatedNotification = "nsIEventQueueActivated"; +static char *gDestroyedNotification = "nsIEventQueueDestroyed"; nsEventQueueImpl::nsEventQueueImpl() { NS_INIT_REFCNT(); + AddRef(); + // eventqueue ownership model is a little unusual. it addrefs + // itself, but when linked into a chain after the head, it releases + // itself, so when it goes dark and empty (unused) it will be + // deleted. mEventQueue = NULL; - + mYoungerQueue = NULL; + mElderQueue = NULL; + mAcceptingEvents = PR_TRUE; + mCouldHaveEvents = PR_TRUE; } nsEventQueueImpl::~nsEventQueueImpl() { - if (NULL != mEventQueue) { + Unlink(); + if (mEventQueue != NULL) { + NotifyObservers(gDestroyedNotification); PL_DestroyEventQueue(mEventQueue); } } @@ -38,35 +56,80 @@ NS_IMETHODIMP nsEventQueueImpl::Init() { mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", PR_GetCurrentThread()); - return NS_OK; + NotifyObservers(gActivatedNotification); + return NS_OK; } NS_IMETHODIMP nsEventQueueImpl::InitFromPLQueue(PLEventQueue* aQueue) { - mEventQueue = aQueue; - return NS_OK; + mEventQueue = aQueue; + NotifyObservers(gActivatedNotification); + return NS_OK; } /* nsISupports interface implementation... */ -NS_IMPL_ISUPPORTS1(nsEventQueueImpl,nsIEventQueue) +NS_IMPL_ISUPPORTS2(nsEventQueueImpl,nsIEventQueue,nsPIEventQueueChain) /* nsIEventQueue interface implementation... */ +NS_IMETHODIMP +nsEventQueueImpl::StopAcceptingEvents() +{ + NS_ASSERTION(mElderQueue, "attempted to disable eldest queue in chain"); + mAcceptingEvents = PR_FALSE; + CheckForDeactivation(); + return NS_OK; +} + +// utility funtion to send observers a notification +void +nsEventQueueImpl::NotifyObservers(const char *aTopic) +{ + nsresult rv; + nsAutoString topic(aTopic); + nsISupports *us = NS_STATIC_CAST(nsISupports *,(NS_STATIC_CAST(nsIEventQueue *,this))); + + NS_WITH_SERVICE(nsIObserverService, os, NS_OBSERVERSERVICE_PROGID, &rv); + if (NS_SUCCEEDED(rv)) + os->Notify(us, topic.GetUnicode(), NULL); +} + NS_IMETHODIMP_(PRStatus) nsEventQueueImpl::PostEvent(PLEvent* aEvent) { - return PL_PostEvent(mEventQueue, aEvent); + if (!mAcceptingEvents) { + PRStatus rv = PR_FAILURE; + NS_ASSERTION(mElderQueue, "event dropped because event chain is dead"); + if (mElderQueue) { + nsCOMPtr elder(do_QueryInterface(mElderQueue)); + if (elder) + rv = elder->PostEvent(aEvent); + } + return rv; + } + return PL_PostEvent(mEventQueue, aEvent); } NS_IMETHODIMP nsEventQueueImpl::PostSynchronousEvent(PLEvent* aEvent, void** aResult) { - void* result = PL_PostSynchronousEvent(mEventQueue, aEvent); - if (aResult) - { - *aResult = result; + if (!mAcceptingEvents) { + 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; + } + return NS_ERROR_ABORT; } + + void* result = PL_PostSynchronousEvent(mEventQueue, aEvent); + if (aResult) + *aResult = result; + return NS_OK; } @@ -115,8 +178,8 @@ nsEventQueueImpl::IsQueueOnCurrentThread(PRBool *aResult) NS_IMETHODIMP nsEventQueueImpl::ProcessPendingEvents() { - PL_ProcessPendingEvents(mEventQueue); - return NS_OK; + PL_ProcessPendingEvents(mEventQueue); + return NS_OK; } NS_IMETHODIMP @@ -129,22 +192,23 @@ nsEventQueueImpl::EventLoop() NS_IMETHODIMP nsEventQueueImpl::EventAvailable(PRBool& aResult) { - aResult = PL_EventAvailable(mEventQueue); - return NS_OK; + aResult = PL_EventAvailable(mEventQueue); + return NS_OK; } NS_IMETHODIMP nsEventQueueImpl::GetEvent(PLEvent** aResult) { - *aResult = PL_GetEvent(mEventQueue); - return NS_OK; + *aResult = PL_GetEvent(mEventQueue); + CheckForDeactivation(); + return NS_OK; } NS_IMETHODIMP nsEventQueueImpl::HandleEvent(PLEvent* aEvent) { - PL_HandleEvent(aEvent); - return NS_OK; + PL_HandleEvent(aEvent); + return NS_OK; } NS_IMETHODIMP_(PRInt32) @@ -167,3 +231,98 @@ nsEventQueueImpl::Create(nsISupports *aOuter, } return rv; } + +// ---------------- nsPIEventQueueChain ----------------- + +NS_IMETHODIMP +nsEventQueueImpl::AppendQueue(nsIEventQueue *aQueue) +{ + nsresult rv; + nsIEventQueue *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; + + // XXX probably wants a threadlock + GetYoungest(&end); // addrefs. released by Unlink. + nsCOMPtr endChain(do_QueryInterface(end)); + if (endChain) { + endChain->SetYounger(queueChain); + queueChain->SetElder(endChain); + NS_RELEASE(aQueue); // the addref from the constructor + rv = NS_OK; + } + return rv; +} + +NS_IMETHODIMP +nsEventQueueImpl::Unlink() +{ + nsPIEventQueueChain *young = mYoungerQueue, + *old = mElderQueue; + + // this is probably OK, but for now let's at least know if it happens + NS_ASSERTION(!mYoungerQueue, "event queue chain broken in middle"); + + // break links early in case the Release cascades back onto us + mYoungerQueue = 0; + mElderQueue = 0; + + if (young) + young->SetElder(old); + if (old) { + old->SetYounger(young); + if (!young) + NS_RELEASE(mElderQueue); // release addref from AppendQueue + } + 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) +{ + nsIEventQueue *answer = NULL; + + if (mYoungerQueue) + mYoungerQueue->GetYoungestActive(&answer); + if (answer == NULL && mAcceptingEvents && mCouldHaveEvents) { + answer = NS_STATIC_CAST(nsIEventQueue *, this); + NS_ADDREF(answer); + } + *aQueue = answer; + 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; +} + diff --git a/xpcom/threads/nsEventQueue.h b/xpcom/threads/nsEventQueue.h index 0e798682c818..75cb61b9b5a4 100644 --- a/xpcom/threads/nsEventQueue.h +++ b/xpcom/threads/nsEventQueue.h @@ -19,10 +19,12 @@ #include "prmon.h" #include "nsIEventQueue.h" +#include "nsPIEventQueueChain.h" static NS_DEFINE_IID(kIEventQueueIID, NS_IEVENTQUEUE_IID); -class nsEventQueueImpl : public nsIEventQueue +class nsEventQueueImpl : public nsIEventQueue, + public nsPIEventQueueChain { public: nsEventQueueImpl(); @@ -32,20 +34,20 @@ public: NS_DECL_ISUPPORTS // nsIEventQueue interface... - NS_IMETHOD_(PRStatus) PostEvent(PLEvent* aEvent); - NS_IMETHOD PostSynchronousEvent(PLEvent* aEvent, void** aResult); + NS_IMETHOD_(PRStatus) PostEvent(PLEvent* aEvent); + NS_IMETHOD PostSynchronousEvent(PLEvent* aEvent, void** aResult); NS_IMETHOD ProcessPendingEvents(); - NS_IMETHOD EventLoop(); + NS_IMETHOD EventLoop(); NS_IMETHOD EventAvailable(PRBool& aResult); - NS_IMETHOD GetEvent(PLEvent** aResult); + NS_IMETHOD GetEvent(PLEvent** aResult); NS_IMETHOD HandleEvent(PLEvent* aEvent); NS_IMETHOD_(PRInt32) GetEventQueueSelectFD(); - NS_IMETHOD Init(); - NS_IMETHOD InitFromPLQueue(PLEventQueue* aQueue); + NS_IMETHOD Init(); + NS_IMETHOD InitFromPLQueue(PLEventQueue* aQueue); NS_IMETHOD EnterMonitor(); NS_IMETHOD ExitMonitor(); @@ -56,14 +58,35 @@ public: NS_IMETHOD IsQueueOnCurrentThread(PRBool *aResult); - // Helpers - static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + NS_IMETHOD StopAcceptingEvents(); - static const nsCID& CID() { static nsCID cid = NS_EVENTQUEUE_CID; return cid; } + // Helpers + static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + + static const nsCID& CID() { static nsCID cid = NS_EVENTQUEUE_CID; return cid; } + + // 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 SetElder(nsPIEventQueueChain *aQueue); private: - PLEventQueue* mEventQueue; + PLEventQueue *mEventQueue; + PRBool mAcceptingEvents, // accept new events or pass them on? + mCouldHaveEvents; // accepting new ones, or still have old ones? + nsPIEventQueueChain *mYoungerQueue, + *mElderQueue; + + void NotifyObservers(const char *aTopic); + + void CheckForDeactivation() { + if (mCouldHaveEvents && !mAcceptingEvents && !PL_EventAvailable(mEventQueue)) { + mCouldHaveEvents = PR_FALSE; + Release(); + } + } }; - - diff --git a/xpcom/threads/nsEventQueueService.cpp b/xpcom/threads/nsEventQueueService.cpp index 513da2b89049..80017c49bce3 100644 --- a/xpcom/threads/nsEventQueueService.cpp +++ b/xpcom/threads/nsEventQueueService.cpp @@ -21,97 +21,140 @@ #include "prmon.h" #include "nsComponentManager.h" #include "nsIEventQueue.h" +#include "nsPIEventQueueChain.h" static NS_DEFINE_CID(kEventQueueCID, NS_EVENTQUEUE_CID); -EventQueueStack::EventQueueStack(EventQueueStack* next) -:mNextQueue(next) -{ - // Create our thread queue using the component manager - if (NS_FAILED(nsComponentManager::CreateInstance(kEventQueueCID, NULL, NS_GET_IID(nsIEventQueue), - (void**)&mEventQueue))) { - mEventQueue = NULL; - } +//////////////////////////////////////////////////////////////////////////////// - if (mEventQueue) { - if (NS_FAILED(mEventQueue->Init())) - mEventQueue = NULL; - } -} +// XXX move to nsID.h or nsHashtable.h? (copied from nsComponentManager.cpp) +class ThreadKey: public nsHashKey { +private: + const PRThread* id; + +public: + ThreadKey(const PRThread* aID) { + id = aID; + } + + PRUint32 HashValue(void) const { + return (PRUint32)id; + } -EventQueueStack::~EventQueueStack() -{ - // Destroy our thread queue. - NS_IF_RELEASE(mEventQueue); + PRBool Equals(const nsHashKey *aKey) const { + return (id == ((const ThreadKey *) aKey)->id); + } - if (mNextQueue) - { - delete mNextQueue; - } -} - -nsIEventQueue* EventQueueStack::GetEventQueue() -{ - if (mEventQueue) { - NS_ADDREF(mEventQueue); - } - return mEventQueue; -} - -EventQueueStack* EventQueueStack::GetNext() -{ - return mNextQueue; -} - -void EventQueueStack::SetNext(EventQueueStack* aStack) -{ - mNextQueue = aStack; -} + nsHashKey *Clone(void) const { + return new ThreadKey(id); + } +}; //////////////////////////////////////////////////////////////////////////////// +/* + * EventQueueEntry maintains the data associated with each entry in + * the EventQueue service's hash table... + * + * It derives from nsISupports merely as a convienence since the entries are + * reference counted... + */ +class EventQueueEntry : public nsISupports +{ +public: + EventQueueEntry(); + virtual ~EventQueueEntry(); + + // nsISupports interface... + NS_DECL_ISUPPORTS + + nsIEventQueue* GetEventQueue(void); // addrefs! + nsresult MakeNewQueue(nsIEventQueue **aQueue); + + nsresult AddQueue(void); + void RemoveQueue(nsIEventQueue *aQueue); // queue goes dark, and is released + +private: + nsIEventQueue *mQueue; +}; + /* nsISupports interface implementation... */ NS_IMPL_ISUPPORTS0(EventQueueEntry) EventQueueEntry::EventQueueEntry() { NS_INIT_REFCNT(); - - mQueueStack = new EventQueueStack(); + MakeNewQueue(&mQueue); + NS_ASSERTION(mQueue, "EventQueueEntry constructor failed"); } EventQueueEntry::~EventQueueEntry() { - // Delete our stack - delete mQueueStack; + NS_IF_RELEASE(mQueue); } +// Return the active event queue on our chain nsIEventQueue* EventQueueEntry::GetEventQueue(void) { - // Return the current event queue on our stack. nsIEventQueue* answer = NULL; - if (mQueueStack) - answer = mQueueStack->GetEventQueue(); // This call addrefs the queue - return answer; + + if (mQueue) { + nsCOMPtr ourChain(do_QueryInterface(mQueue)); + if (ourChain) + ourChain->GetYoungestActive(&answer); + else { + NS_ADDREF(mQueue); + answer = mQueue; + } + } + return answer; } -void EventQueueEntry::PushQueue(void) +nsresult EventQueueEntry::MakeNewQueue(nsIEventQueue **aQueue) { - // Make a new thread queue, connect it to our current stack, and then - // set it to be the top of our stack. - mQueueStack = new EventQueueStack(mQueueStack); + nsIEventQueue *queue = 0; + nsresult rv; + + rv = nsComponentManager::CreateInstance(kEventQueueCID, NULL, + NS_GET_IID(nsIEventQueue), (void**) &queue); + + if (NS_SUCCEEDED(rv)) { + rv = queue->Init(); + if (NS_FAILED(rv)) { + NS_RELEASE(queue); + queue = 0; // redundant, but makes me feel better + } + } + *aQueue = queue; + return rv; } -void EventQueueEntry::PopQueue(void) +nsresult EventQueueEntry::AddQueue(void) { - EventQueueStack* popped = mQueueStack; - if (mQueueStack) { - mQueueStack = mQueueStack->GetNext(); - popped->SetNext(NULL); - } + nsIEventQueue *newQueue = NULL; + nsresult rv = NS_ERROR_NOT_INITIALIZED; - // This will result in the queue being released. - delete popped; + if (mQueue) { + rv = MakeNewQueue(&newQueue); + + // add it to our chain of queues + if (NS_SUCCEEDED(rv)) { + nsCOMPtr ourChain(do_QueryInterface(mQueue)); + if (ourChain) + ourChain->AppendQueue(newQueue); + else + NS_RELEASE(newQueue); + } + } + return rv; +} + +void EventQueueEntry::RemoveQueue(nsIEventQueue *aQueue) +{ + aQueue->StopAcceptingEvents(); + NS_RELEASE(aQueue); + // it's now gone dark, and will be deleted and unlinked as soon as + // everyone else lets go } //////////////////////////////////////////////////////////////////////////////// @@ -173,7 +216,7 @@ nsEventQueueServiceImpl::CreateThreadEventQueue(void) /* Enter the lock which protects the EventQ hashtable... */ PR_EnterMonitor(mEventQMonitor); - /* Only create one event queue per thread... */ + /* create only one event queue chain per thread... */ evQueueEntry = (EventQueueEntry*)mEventQTable->Get(&key); if (NULL == evQueueEntry) { evQueueEntry = new EventQueueEntry(); @@ -240,17 +283,21 @@ nsEventQueueServiceImpl::CreateFromPLEventQueue(PLEventQueue* aPLEventQueue, nsI 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() +nsEventQueueServiceImpl::PushThreadEventQueue(nsIEventQueue **aNewQueue) { - nsresult rv = NS_OK; + nsresult rv = NS_OK; ThreadKey key(PR_GetCurrentThread()); EventQueueEntry* evQueueEntry; + NS_ASSERTION(aNewQueue, "PushThreadEventQueue called with null param"); + *aNewQueue = NULL; + /* Enter the lock which protects the EventQ hashtable... */ PR_EnterMonitor(mEventQMonitor); - /* Only create one event queue per thread... */ evQueueEntry = (EventQueueEntry*)mEventQTable->Get(&key); if (NULL == evQueueEntry) { evQueueEntry = new EventQueueEntry(); @@ -260,13 +307,16 @@ nsEventQueueServiceImpl::PushThreadEventQueue() } mEventQTable->Put(&key, evQueueEntry); } - else { - // An entry was already present. We need to push a new - // queue onto our stack. - evQueueEntry->PushQueue(); - } + else { + // An entry was already present. We need to push a new + // queue onto our stack. + rv = evQueueEntry->AddQueue(); + } - NS_ADDREF(evQueueEntry); + if (NS_SUCCEEDED(rv)) { + *aNewQueue = evQueueEntry->GetEventQueue(); + NS_ADDREF(evQueueEntry); + } done: // Release the EventQ lock... @@ -274,8 +324,9 @@ done: return rv; } +// disable and release the given queue (though the last one won't be released) NS_IMETHODIMP -nsEventQueueServiceImpl::PopThreadEventQueue(void) +nsEventQueueServiceImpl::PopThreadEventQueue(nsIEventQueue *aQueue) { nsresult rv = NS_OK; ThreadKey key(PR_GetCurrentThread()); @@ -293,10 +344,11 @@ nsEventQueueServiceImpl::PopThreadEventQueue(void) if (0 == refcnt) { mEventQTable->Remove(&key); } - else { - // We must be popping. - evQueueEntry->PopQueue(); - } + else { + // We must be popping. (note: doesn't this always want to be executed?) + // aQueue->ProcessPendingEvents(); // (theoretically not necessary) + evQueueEntry->RemoveQueue(aQueue); + } } else { rv = NS_ERROR_FAILURE; } diff --git a/xpcom/threads/nsEventQueueService.h b/xpcom/threads/nsEventQueueService.h index 293e55692a80..c604d8d92db2 100644 --- a/xpcom/threads/nsEventQueueService.h +++ b/xpcom/threads/nsEventQueueService.h @@ -27,31 +27,6 @@ class nsIEventQueue; //////////////////////////////////////////////////////////////////////////////// -// XXX move to nsID.h or nsHashtable.h? (copied from nsComponentManager.cpp) -class ThreadKey: public nsHashKey { -private: - const PRThread* id; - -public: - ThreadKey(const PRThread* aID) { - id = aID; - } - - PRUint32 HashValue(void) const { - return (PRUint32)id; - } - - PRBool Equals(const nsHashKey *aKey) const { - return (id == ((const ThreadKey *) aKey)->id); - } - - nsHashKey *Clone(void) const { - return new ThreadKey(id); - } -}; - -//////////////////////////////////////////////////////////////////////////////// - /* This class is used with the EventQueueEntries to allow us to nest event queues */ class EventQueueStack @@ -71,33 +46,6 @@ private: //////////////////////////////////////////////////////////////////////////////// -/* - * This class maintains the data associated with each entry in the EventQueue - * service's hash table... - * - * It derives from nsISupports merely as a convienence since the entries are - * reference counted... - */ -class EventQueueEntry : public nsISupports -{ -public: - EventQueueEntry(); - virtual ~EventQueueEntry(); - - // nsISupports interface... - NS_DECL_ISUPPORTS - - nsIEventQueue* GetEventQueue(void); - - void PushQueue(void); - void PopQueue(void); - -private: - EventQueueStack* mQueueStack; -}; - -//////////////////////////////////////////////////////////////////////////////// - class nsEventQueueServiceImpl : public nsIEventQueueService { public: @@ -117,8 +65,8 @@ public: NS_IMETHOD CreateFromPLEventQueue(PLEventQueue* aPLEventQueue, nsIEventQueue** aResult); - NS_IMETHOD PushThreadEventQueue(void); - NS_IMETHOD PopThreadEventQueue(void); + NS_IMETHOD PushThreadEventQueue(nsIEventQueue **aNewQueue); + NS_IMETHOD PopThreadEventQueue(nsIEventQueue *aQueue); #ifdef XP_MAC NS_IMETHOD ProcessEvents(); diff --git a/xpcom/threads/nsIEventQueue.h b/xpcom/threads/nsIEventQueue.h index 256634d84fb7..0865cb3d8abc 100644 --- a/xpcom/threads/nsIEventQueue.h +++ b/xpcom/threads/nsIEventQueue.h @@ -46,14 +46,14 @@ public: NS_IMETHOD ProcessPendingEvents() = 0; NS_IMETHOD EventLoop() = 0; - NS_IMETHOD EventAvailable(PRBool& aResult) = 0; - NS_IMETHOD GetEvent(PLEvent** aResult) = 0; + NS_IMETHOD EventAvailable(PRBool& aResult) = 0; + NS_IMETHOD GetEvent(PLEvent** aResult) = 0; NS_IMETHOD HandleEvent(PLEvent* aEvent) = 0; NS_IMETHOD_(PRInt32) GetEventQueueSelectFD() = 0; - NS_IMETHOD Init() = 0; - NS_IMETHOD InitFromPLQueue(PLEventQueue* aQueue) = 0; + NS_IMETHOD Init() = 0; + NS_IMETHOD InitFromPLQueue(PLEventQueue* aQueue) = 0; NS_IMETHOD EnterMonitor() = 0; NS_IMETHOD ExitMonitor() = 0; @@ -62,6 +62,10 @@ public: NS_IMETHOD GetPLEventQueue(PLEventQueue** aEventQueue) = 0; NS_IMETHOD IsQueueOnCurrentThread(PRBool *aResult) = 0; + + // effectively kill the queue. warning: the queue is allowed to delete + // itself any time after this. + NS_IMETHOD StopAcceptingEvents() = 0; }; #endif /* nsIEventQueue_h___ */ diff --git a/xpcom/threads/nsIEventQueueService.h b/xpcom/threads/nsIEventQueueService.h index fe662552be7d..b170dd294b80 100644 --- a/xpcom/threads/nsIEventQueueService.h +++ b/xpcom/threads/nsIEventQueueService.h @@ -41,15 +41,19 @@ class nsIEventQueueService : public nsISupports { public: - static const nsIID& GetIID() { static nsIID iid = NS_IEVENTQUEUESERVICE_IID; return iid; } + static const nsIID& GetIID() { static nsIID iid = NS_IEVENTQUEUESERVICE_IID; return iid; } NS_IMETHOD CreateThreadEventQueue(void) = 0; NS_IMETHOD DestroyThreadEventQueue(void) = 0; - NS_IMETHOD CreateFromPLEventQueue(PLEventQueue* aPLEventQueue, nsIEventQueue** aResult) = 0; + NS_IMETHOD CreateFromPLEventQueue(PLEventQueue* aPLEventQueue, nsIEventQueue** aResult) = 0; - NS_IMETHOD PushThreadEventQueue(void) = 0; - NS_IMETHOD PopThreadEventQueue(void) = 0; + // Add a new event queue for the current thread, making it the "current" + // queue. Return that queue in aNewQueue, addrefed. + NS_IMETHOD PushThreadEventQueue(nsIEventQueue **aNewQueue) = 0; + + // release and disable the queue + NS_IMETHOD PopThreadEventQueue(nsIEventQueue *aQueue) = 0; NS_IMETHOD GetThreadEventQueue(PRThread* aThread, nsIEventQueue** aResult) = 0;