event queues own and delete themselves when they're done. bug 15856 r:hyatt@netscape.com

This commit is contained in:
danm%netscape.com 1999-10-18 14:59:57 +00:00
parent 81e0c798a7
commit 588868b60c
6 changed files with 359 additions and 169 deletions

View File

@ -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<nsIEventQueue> 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<nsIEventQueue> 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<nsPIEventQueueChain> 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<nsPIEventQueueChain> 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;
}

View File

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

View File

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

View File

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

View File

@ -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___ */

View File

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