From b048c0396ee491c87ce6d8114a183f8c6c0308af Mon Sep 17 00:00:00 2001 From: "danm%netscape.com" Date: Sat, 4 Mar 2000 03:17:01 +0000 Subject: [PATCH] add API to EventQueueService for creating a monitored event queue. part of bug 25979. r=dougt r=jar git-svn-id: svn://10.0.0.236/trunk@62207 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/xpcom/threads/nsEventQueue.cpp | 24 +++++++--- mozilla/xpcom/threads/nsEventQueue.h | 5 ++- mozilla/xpcom/threads/nsEventQueueService.cpp | 44 +++++++++++++------ mozilla/xpcom/threads/nsEventQueueService.h | 11 +++-- mozilla/xpcom/threads/nsIEventQueue.h | 5 ++- mozilla/xpcom/threads/nsIEventQueueService.h | 27 +++++++++++- mozilla/xpcom/threads/plevent.c | 13 ++++-- mozilla/xpcom/threads/plevent.h | 6 +++ 8 files changed, 103 insertions(+), 32 deletions(-) diff --git a/mozilla/xpcom/threads/nsEventQueue.cpp b/mozilla/xpcom/threads/nsEventQueue.cpp index c2ee105bb70..ed0b440140d 100644 --- a/mozilla/xpcom/threads/nsEventQueue.cpp +++ b/mozilla/xpcom/threads/nsEventQueue.cpp @@ -86,15 +86,19 @@ nsEventQueueImpl::~nsEventQueueImpl() } NS_IMETHODIMP -nsEventQueueImpl::Init() +nsEventQueueImpl::Init(PRBool aNative) { - mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", PR_GetCurrentThread()); + PRThread *thread = PR_GetCurrentThread(); + if (aNative) + mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", thread); + else + mEventQueue = PL_CreateMonitoredEventQueue("Thread event queue...", thread); NotifyObservers(gActivatedNotification); return NS_OK; } NS_IMETHODIMP -nsEventQueueImpl::InitFromPRThread(PRThread* thread) +nsEventQueueImpl::InitFromPRThread(PRThread* thread, PRBool aNative) { if (thread == NS_CURRENT_THREAD) { @@ -112,8 +116,11 @@ nsEventQueueImpl::InitFromPRThread(PRThread* thread) rv = mainIThread->GetPRThread(&thread); if (NS_FAILED(rv)) return rv; } - - mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", thread); + + if (aNative) + mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", thread); + else + mEventQueue = PL_CreateMonitoredEventQueue("Thread event queue...", thread); NotifyObservers(gActivatedNotification); return NS_OK; } @@ -274,6 +281,13 @@ nsEventQueueImpl::IsQueueOnCurrentThread(PRBool *aResult) } +NS_IMETHODIMP +nsEventQueueImpl::IsQueueNative(PRBool *aResult) +{ + *aResult = PL_IsQueueNative(mEventQueue); + return NS_OK; +} + NS_IMETHODIMP nsEventQueueImpl::ProcessPendingEvents() { diff --git a/mozilla/xpcom/threads/nsEventQueue.h b/mozilla/xpcom/threads/nsEventQueue.h index 51612a3e11d..e03e3c2df80 100644 --- a/mozilla/xpcom/threads/nsEventQueue.h +++ b/mozilla/xpcom/threads/nsEventQueue.h @@ -53,8 +53,8 @@ public: NS_IMETHOD_(PRInt32) GetEventQueueSelectFD(); - NS_IMETHOD Init(); - NS_IMETHOD InitFromPRThread(PRThread* thread); + NS_IMETHOD Init(PRBool aNative); + NS_IMETHOD InitFromPRThread(PRThread* thread, PRBool aNative); NS_IMETHOD InitFromPLQueue(PLEventQueue* aQueue); NS_IMETHOD EnterMonitor(); @@ -65,6 +65,7 @@ public: NS_IMETHOD GetPLEventQueue(PLEventQueue** aEventQueue); NS_IMETHOD IsQueueOnCurrentThread(PRBool *aResult); + NS_IMETHOD IsQueueNative(PRBool *aResult); NS_IMETHOD StopAcceptingEvents(); diff --git a/mozilla/xpcom/threads/nsEventQueueService.cpp b/mozilla/xpcom/threads/nsEventQueueService.cpp index 05a001f6f2e..95da1c6b79e 100644 --- a/mozilla/xpcom/threads/nsEventQueueService.cpp +++ b/mozilla/xpcom/threads/nsEventQueueService.cpp @@ -78,16 +78,17 @@ public: class EventQueueEntry : public nsISupports { public: - EventQueueEntry(nsEventQueueServiceImpl *aService, ThreadKey &aKey); + EventQueueEntry(nsEventQueueServiceImpl *aService, ThreadKey &aKey, + PRBool aNative); virtual ~EventQueueEntry(); // nsISupports interface... NS_DECL_ISUPPORTS nsIEventQueue* GetEventQueue(void); // addrefs! - nsresult MakeNewQueue(PRThread* thread, nsIEventQueue **aQueue); nsresult AddQueue(void); + void RemoveQueue(nsIEventQueue *aQueue); // queue goes dark, and is released ThreadKey *TheThreadKey(void) { return &mHashKey; } @@ -99,6 +100,9 @@ public: { return mNextEntry; } private: + nsresult MakeNewQueue(PRThread* thread, PRBool aNative, + nsIEventQueue **aQueue); + nsIEventQueue *mQueue; ThreadKey mHashKey; nsEventQueueServiceImpl *mService; // weak reference, obviously @@ -109,12 +113,12 @@ private: /* nsISupports interface implementation... */ NS_IMPL_ISUPPORTS0(EventQueueEntry) -EventQueueEntry::EventQueueEntry(nsEventQueueServiceImpl *aService, ThreadKey &aKey) : +EventQueueEntry::EventQueueEntry(nsEventQueueServiceImpl *aService, ThreadKey &aKey, PRBool aNative) : mHashKey(aKey), mPrevEntry(0), mNextEntry(0) { NS_INIT_REFCNT(); mService = aService; - MakeNewQueue(aKey.id, &mQueue); + MakeNewQueue(aKey.id, aNative, &mQueue); NS_ASSERTION(mQueue, "EventQueueEntry constructor failed"); if (mService) mService->AddEventQueueEntry(this); @@ -144,7 +148,9 @@ nsIEventQueue* EventQueueEntry::GetEventQueue(void) return answer; } -nsresult EventQueueEntry::MakeNewQueue(PRThread* thread, nsIEventQueue **aQueue) +nsresult EventQueueEntry::MakeNewQueue(PRThread* thread, + PRBool aNative, + nsIEventQueue **aQueue) { nsIEventQueue *queue = 0; nsresult rv; @@ -153,7 +159,7 @@ nsresult EventQueueEntry::MakeNewQueue(PRThread* thread, nsIEventQueue **aQueue) NS_GET_IID(nsIEventQueue), (void**) &queue); if (NS_SUCCEEDED(rv)) { - rv = queue->InitFromPRThread(thread); + rv = queue->InitFromPRThread(thread, aNative); if (NS_FAILED(rv)) { NS_RELEASE(queue); queue = 0; // redundant, but makes me feel better @@ -165,11 +171,13 @@ nsresult EventQueueEntry::MakeNewQueue(PRThread* thread, nsIEventQueue **aQueue) nsresult EventQueueEntry::AddQueue(void) { + PRBool native; nsIEventQueue *newQueue = NULL; nsresult rv = NS_ERROR_NOT_INITIALIZED; if (mQueue) { - rv = MakeNewQueue(PR_GetCurrentThread(), &newQueue); + mQueue->IsQueueNative(&native); + rv = MakeNewQueue(PR_GetCurrentThread(), native, &newQueue); // add it to our chain of queues if (NS_SUCCEEDED(rv)) { @@ -301,21 +309,27 @@ NS_IMPL_ISUPPORTS1(nsEventQueueServiceImpl,nsIEventQueueService) /* nsIEventQueueService interface implementation... */ NS_IMETHODIMP -nsEventQueueServiceImpl::CreateThreadEventQueue(void) +nsEventQueueServiceImpl::CreateThreadEventQueue() { - return CreateEventQueue(PR_GetCurrentThread()); + return CreateEventQueue(PR_GetCurrentThread(), PR_TRUE); +} + +NS_IMETHODIMP +nsEventQueueServiceImpl::CreateMonitoredThreadEventQueue() +{ + return CreateEventQueue(PR_GetCurrentThread(), PR_FALSE); } NS_IMETHODIMP nsEventQueueServiceImpl::CreateFromIThread( - nsIThread *aThread, nsIEventQueue **aResult) + nsIThread *aThread, PRBool aNative, nsIEventQueue **aResult) { nsresult rv; PRThread *prThread; rv = aThread->GetPRThread(&prThread); if (NS_SUCCEEDED(rv)) { - rv = CreateEventQueue(prThread); // addrefs + rv = CreateEventQueue(prThread, aNative); // addrefs if (NS_SUCCEEDED(rv)) rv = GetThreadEventQueue(prThread, aResult); // doesn't addref } @@ -323,7 +337,7 @@ nsEventQueueServiceImpl::CreateFromIThread( } NS_IMETHODIMP -nsEventQueueServiceImpl::CreateEventQueue(PRThread *aThread) +nsEventQueueServiceImpl::CreateEventQueue(PRThread *aThread, PRBool aNative) { nsresult rv = NS_OK; ThreadKey key(aThread); @@ -335,7 +349,7 @@ nsEventQueueServiceImpl::CreateEventQueue(PRThread *aThread) /* create only one event queue chain per thread... */ evQueueEntry = (EventQueueEntry*)mEventQTable->Get(&key); if (NULL == evQueueEntry) { - evQueueEntry = new EventQueueEntry(this, key); + evQueueEntry = new EventQueueEntry(this, key, aNative); if (NULL == evQueueEntry) { rv = NS_ERROR_OUT_OF_MEMORY; goto done; @@ -447,8 +461,10 @@ nsEventQueueServiceImpl::PushThreadEventQueue(nsIEventQueue **aNewQueue) PR_EnterMonitor(mEventQMonitor); evQueueEntry = (EventQueueEntry*)mEventQTable->Get(&key); + NS_ASSERTION(evQueueEntry, "pushed event queue on top of nothing"); if (NULL == evQueueEntry) { - evQueueEntry = new EventQueueEntry(this, key); + // shouldn't happen. as a fallback, we guess you wanted a native queue + evQueueEntry = new EventQueueEntry(this, key, PR_TRUE); if (NULL == evQueueEntry) { rv = NS_ERROR_OUT_OF_MEMORY; goto done; diff --git a/mozilla/xpcom/threads/nsEventQueueService.h b/mozilla/xpcom/threads/nsEventQueueService.h index 5fc1dceb1b7..c5ef2962533 100644 --- a/mozilla/xpcom/threads/nsEventQueueService.h +++ b/mozilla/xpcom/threads/nsEventQueueService.h @@ -57,12 +57,14 @@ public: NS_DECL_ISUPPORTS // nsIEventQueueService interface... - NS_IMETHOD CreateThreadEventQueue(void); + NS_IMETHOD CreateThreadEventQueue(); + NS_IMETHOD CreateMonitoredThreadEventQueue(); NS_IMETHOD DestroyThreadEventQueue(void); NS_IMETHOD GetThreadEventQueue(PRThread* aThread, nsIEventQueue** aResult); NS_IMETHOD ResolveEventQueue(nsIEventQueue* queueOrConstant, nsIEventQueue* *resultQueue); - NS_IMETHOD CreateFromIThread(nsIThread *aThread, nsIEventQueue **aResult); + NS_IMETHOD CreateFromIThread(nsIThread *aThread, PRBool aNative, + nsIEventQueue **aResult); NS_IMETHOD CreateFromPLEventQueue(PLEventQueue* aPLEventQueue, nsIEventQueue** aResult); NS_IMETHOD PushThreadEventQueue(nsIEventQueue **aNewQueue); @@ -70,7 +72,10 @@ public: private: - NS_IMETHOD CreateEventQueue(PRThread *aThread); + /* 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); void AddEventQueueEntry(EventQueueEntry *aEntry); void RemoveEventQueueEntry(EventQueueEntry *aEntry); diff --git a/mozilla/xpcom/threads/nsIEventQueue.h b/mozilla/xpcom/threads/nsIEventQueue.h index 6003f8a0e44..28b80e63564 100644 --- a/mozilla/xpcom/threads/nsIEventQueue.h +++ b/mozilla/xpcom/threads/nsIEventQueue.h @@ -60,8 +60,8 @@ public: NS_IMETHOD_(PRInt32) GetEventQueueSelectFD() = 0; - NS_IMETHOD Init() = 0; - NS_IMETHOD InitFromPRThread(PRThread* thread) = 0; + NS_IMETHOD Init(PRBool aNative) = 0; + NS_IMETHOD InitFromPRThread(PRThread* thread, PRBool aNative) = 0; NS_IMETHOD InitFromPLQueue(PLEventQueue* aQueue) = 0; NS_IMETHOD EnterMonitor() = 0; @@ -71,6 +71,7 @@ public: NS_IMETHOD GetPLEventQueue(PLEventQueue** aEventQueue) = 0; NS_IMETHOD IsQueueOnCurrentThread(PRBool *aResult) = 0; + NS_IMETHOD IsQueueNative(PRBool *aResult) = 0; // effectively kill the queue. warning: the queue is allowed to delete // itself any time after this. diff --git a/mozilla/xpcom/threads/nsIEventQueueService.h b/mozilla/xpcom/threads/nsIEventQueueService.h index cfd98551b09..b3a69384cae 100644 --- a/mozilla/xpcom/threads/nsIEventQueueService.h +++ b/mozilla/xpcom/threads/nsIEventQueueService.h @@ -55,10 +55,33 @@ class nsIEventQueueService : public nsISupports public: static const nsIID& GetIID() { static nsIID iid = NS_IEVENTQUEUESERVICE_IID; return iid; } - NS_IMETHOD CreateThreadEventQueue(void) = 0; + /** + * 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 + */ + NS_IMETHOD CreateThreadEventQueue() = 0; + + /** + * 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 + */ + NS_IMETHOD CreateMonitoredThreadEventQueue() = 0; + + /** + * 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. + */ NS_IMETHOD DestroyThreadEventQueue(void) = 0; - NS_IMETHOD CreateFromIThread(nsIThread *aThread, nsIEventQueue **aResult) = 0; + NS_IMETHOD CreateFromIThread(nsIThread *aThread, PRBool aNative, + nsIEventQueue **aResult) = 0; NS_IMETHOD CreateFromPLEventQueue(PLEventQueue* aPLEventQueue, nsIEventQueue** aResult) = 0; // Add a new event queue for the current thread, making it the "current" diff --git a/mozilla/xpcom/threads/plevent.c b/mozilla/xpcom/threads/plevent.c index 27603650ced..0c249934e02 100644 --- a/mozilla/xpcom/threads/plevent.c +++ b/mozilla/xpcom/threads/plevent.c @@ -168,17 +168,16 @@ static PLEventQueue * self->removeMsg = PR_TRUE; #endif PR_INIT_CLIST(&self->queue); - if ( qtype == EventQueueIsNative ) - { + if ( qtype == EventQueueIsNative ) { err = _pl_SetupNativeNotifier(self); if (err) goto error; + _md_CreateEventQueue( self ); } - _md_CreateEventQueue( self ); return self; error: if (mon != NULL) - PR_DestroyMonitor(mon); + PR_DestroyMonitor(mon); PR_DELETE(self); return NULL; } /* end _pl_CreateEventQueue() */ @@ -929,6 +928,12 @@ PL_IsQueueOnCurrentThread( PLEventQueue *queue ) return PR_FALSE; } /* end PL_IsQueueOnCurrentThread() */ +PR_EXTERN(PRBool) +PL_IsQueueNative(PLEventQueue *queue) +{ + return queue->type == EventQueueIsNative ? PR_TRUE : PR_FALSE; +} + #if defined(WIN16) || defined(_WIN32) /* ** Global Instance handle... diff --git a/mozilla/xpcom/threads/plevent.h b/mozilla/xpcom/threads/plevent.h index a769024279a..46874156962 100644 --- a/mozilla/xpcom/threads/plevent.h +++ b/mozilla/xpcom/threads/plevent.h @@ -393,6 +393,12 @@ PL_GetEventQueueSelectFD(PLEventQueue* self); PR_EXTERN(PRBool) PL_IsQueueOnCurrentThread( PLEventQueue *queue ); +/* +** Returns whether the queue is native (true) or monitored (false) +*/ +PR_EXTERN(PRBool) +PL_IsQueueNative(PLEventQueue *queue); + /******************************************************************************* * Event Operations ******************************************************************************/