mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
event queues own and delete themselves when they're done. bug 15856 r:hyatt@netscape.com
This commit is contained in:
parent
81e0c798a7
commit
588868b60c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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___ */
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user