VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.cpp@ 101993

最後變更 在這個檔案從101993是 101993,由 vboxsync 提交於 13 月 前

libs/xpcom: Convert nsEventQueue.cpp from PR_LOG to IPRT's logging infrastructure, bugref:10545

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 15.5 KB
 
1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is Mozilla Communicator client code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38#include "nsCOMPtr.h"
39#include "nsEventQueue.h"
40#include "nsIEventQueueService.h"
41#include "nsIThread.h"
42
43#include "nsIServiceManager.h"
44#include "nsIObserverService.h"
45
46#include "nsString.h"
47
48#ifdef NS_DEBUG
49#include "prprf.h"
50#endif
51
52#include <VBox/log.h>
53
54// in a real system, these would be members in a header class...
55static const char gActivatedNotification[] = "nsIEventQueueActivated";
56static const char gDestroyedNotification[] = "nsIEventQueueDestroyed";
57
58nsEventQueueImpl::nsEventQueueImpl()
59{
60 NS_ADDREF_THIS();
61 /* The slightly weird ownership model for eventqueues goes like this:
62
63 General:
64 There's an addref from the factory generally held by whoever asked for
65 the queue. The queue addrefs itself (right here) and releases itself
66 after someone calls StopAcceptingEvents() on the queue and when it is
67 dark and empty (in CheckForDeactivation()).
68
69 Chained queues:
70
71 Eldest queue:
72 The eldest queue in a chain is held on to by the EventQueueService
73 in a hash table, so it is possible that the eldest queue may not be
74 released until the EventQueueService is shutdown.
75 You may not call StopAcceptingEvents() on this queue until you have
76 done so on all younger queues.
77
78 General:
79 Each queue holds a reference to their immediate elder link and a weak
80 reference to their immediate younger link. Because you must shut down
81 queues from youngest to eldest, all the references will be removed.
82
83 It happens something like:
84 queue->StopAcceptingEvents()
85 {
86 CheckForDeactivation()
87 {
88 -- hopefully we are able to shutdown now --
89 Unlink()
90 {
91 -- remove the reference we hold to our elder queue --
92 -- NULL out our elder queues weak reference to us --
93 }
94 RELEASE ourself (to balance the ADDREF here in the constructor)
95 -- and we should go away. --
96 }
97 }
98
99
100 Notes:
101 A dark queue no longer accepts events. An empty queue simply has no events.
102 */
103
104 Log(("EventQueue: Created [queue=%lx]\n",(long)mEventQueue));
105
106 mYoungerQueue = nsnull;
107 mEventQueue = nsnull;
108 mAcceptingEvents = PR_TRUE;
109 mCouldHaveEvents = PR_TRUE;
110}
111
112nsEventQueueImpl::~nsEventQueueImpl()
113{
114 Unlink();
115
116 Log(("EventQueue: Destroyed [queue=%lx]\n",(long)mEventQueue));
117
118 if (mEventQueue) {
119 NotifyObservers(gDestroyedNotification);
120 PL_DestroyEventQueue(mEventQueue);
121 }
122}
123
124NS_IMETHODIMP
125nsEventQueueImpl::Init(PRBool aNative)
126{
127 PRThread *thread = PR_GetCurrentThread();
128 if (aNative)
129 mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", thread);
130 else
131 mEventQueue = PL_CreateMonitoredEventQueue("Thread event queue...", thread);
132 NotifyObservers(gActivatedNotification);
133 return NS_OK;
134}
135
136NS_IMETHODIMP
137nsEventQueueImpl::InitFromPRThread(PRThread* thread, PRBool aNative)
138{
139 if (thread == NS_CURRENT_THREAD)
140 {
141 thread = PR_GetCurrentThread();
142 }
143 else if (thread == NS_UI_THREAD)
144 {
145 nsCOMPtr<nsIThread> mainIThread;
146 nsresult rv;
147
148 // Get the primordial thread
149 rv = nsIThread::GetMainThread(getter_AddRefs(mainIThread));
150 if (NS_FAILED(rv)) return rv;
151
152 rv = mainIThread->GetPRThread(&thread);
153 if (NS_FAILED(rv)) return rv;
154 }
155
156 if (aNative)
157 mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", thread);
158 else
159 mEventQueue = PL_CreateMonitoredEventQueue("Thread event queue...", thread);
160 NotifyObservers(gActivatedNotification);
161 return NS_OK;
162}
163
164NS_IMETHODIMP
165nsEventQueueImpl::InitFromPLQueue(PLEventQueue* aQueue)
166{
167 mEventQueue = aQueue;
168 NotifyObservers(gActivatedNotification);
169 return NS_OK;
170}
171
172/* nsISupports interface implementation... */
173NS_IMPL_THREADSAFE_ISUPPORTS3(nsEventQueueImpl,
174 nsIEventQueue,
175 nsIEventTarget,
176 nsPIEventQueueChain)
177
178/* nsIEventQueue interface implementation... */
179
180NS_IMETHODIMP
181nsEventQueueImpl::StopAcceptingEvents()
182{
183 // this assertion is bogus. I should be able to shut down the eldest queue,
184 // as long as there are no younger children
185
186
187 NS_ASSERTION(mElderQueue || !mYoungerQueue, "attempted to disable eldest queue in chain");
188 mAcceptingEvents = PR_FALSE;
189 CheckForDeactivation();
190
191 Log(("EventQueue: StopAccepting [queue=%lx, accept=%d, could=%d]\n",
192 (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
193 return NS_OK;
194}
195
196// utility funtion to send observers a notification
197void
198nsEventQueueImpl::NotifyObservers(const char *aTopic)
199{
200 nsresult rv;
201
202 nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1", &rv);
203 if (NS_SUCCEEDED(rv)) {
204 nsCOMPtr<nsIEventQueue> kungFuDeathGrip(this);
205 nsCOMPtr<nsISupports> us(do_QueryInterface(kungFuDeathGrip));
206 os->NotifyObservers(us, aTopic, NULL);
207 }
208}
209
210
211NS_IMETHODIMP
212nsEventQueueImpl::InitEvent(PLEvent* aEvent,
213 void* owner,
214 PLHandleEventProc handler,
215 PLDestroyEventProc destructor)
216{
217 PL_InitEvent(aEvent, owner, handler, destructor);
218 return NS_OK;
219}
220
221
222NS_IMETHODIMP
223nsEventQueueImpl::PostEvent(PLEvent* aEvent)
224{
225 if (!mAcceptingEvents) {
226
227 Log(("EventQueue: Punt posted event [queue=%lx, accept=%d, could=%d]\n",
228 (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
229
230 nsresult rv = NS_ERROR_FAILURE;
231 NS_ASSERTION(mElderQueue, "event dropped because event chain is dead");
232 if (mElderQueue) {
233 nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
234 if (elder)
235 rv = elder->PostEvent(aEvent);
236 }
237 return rv;
238 }
239
240 Log(("EventQueue: Posting event [queue=%lx]\n", (long)mEventQueue));
241 return PL_PostEvent(mEventQueue, aEvent) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
242}
243
244NS_IMETHODIMP
245nsEventQueueImpl::PostSynchronousEvent(PLEvent* aEvent, void** aResult)
246{
247 if (!mAcceptingEvents) {
248 Log(("EventQueue: Punt posted synchronous event [queue=%lx, accept=%d, could=%d]\n",
249 (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
250
251 nsresult rv = NS_ERROR_NO_INTERFACE;
252 NS_ASSERTION(mElderQueue, "event dropped because event chain is dead");
253 if (mElderQueue) {
254 nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
255 if (elder)
256 rv = elder->PostSynchronousEvent(aEvent, aResult);
257 return rv;
258 }
259 return NS_ERROR_ABORT;
260 }
261
262 Log(("EventQueue: Posting synchronous event [queue=%lx]\n", (long)mEventQueue));
263 void* result = PL_PostSynchronousEvent(mEventQueue, aEvent);
264 if (aResult)
265 *aResult = result;
266
267 return NS_OK;
268}
269
270NS_IMETHODIMP
271nsEventQueueImpl::EnterMonitor()
272{
273 PL_ENTER_EVENT_QUEUE_MONITOR(mEventQueue);
274 return NS_OK;
275}
276
277NS_IMETHODIMP
278nsEventQueueImpl::ExitMonitor()
279{
280 PL_EXIT_EVENT_QUEUE_MONITOR(mEventQueue);
281 return NS_OK;
282}
283
284
285NS_IMETHODIMP
286nsEventQueueImpl::RevokeEvents(void* owner)
287{
288 PL_RevokeEvents(mEventQueue, owner);
289 if (mElderQueue) {
290 nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
291 if (elder)
292 elder->RevokeEvents(owner);
293 }
294 return NS_OK;
295}
296
297
298NS_IMETHODIMP
299nsEventQueueImpl::GetPLEventQueue(PLEventQueue** aEventQueue)
300{
301 if (!mEventQueue)
302 return NS_ERROR_NULL_POINTER;
303
304 *aEventQueue = mEventQueue;
305 return NS_OK;
306}
307
308NS_IMETHODIMP
309nsEventQueueImpl::IsOnCurrentThread(PRBool *aResult)
310{
311 *aResult = PL_IsQueueOnCurrentThread( mEventQueue );
312 return NS_OK;
313}
314
315
316NS_IMETHODIMP
317nsEventQueueImpl::IsQueueNative(PRBool *aResult)
318{
319 *aResult = PL_IsQueueNative(mEventQueue);
320 return NS_OK;
321}
322
323NS_IMETHODIMP
324nsEventQueueImpl::PendingEvents(PRBool *aResult)
325{
326 *aResult = PL_EventAvailable(mEventQueue);
327 if (!*aResult && mElderQueue) {
328 nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
329 if (elder)
330 return elder->EventAvailable(*aResult);
331 }
332 return NS_OK;
333}
334
335
336NS_IMETHODIMP
337nsEventQueueImpl::ProcessPendingEvents()
338{
339 PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
340
341 NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
342
343 if (!correctThread)
344 return NS_ERROR_FAILURE;
345
346 Log(("EventQueue: Process pending [queue=%lx, accept=%d, could=%d]\n",
347 (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
348 PL_ProcessPendingEvents(mEventQueue);
349
350 // if we're no longer accepting events and there are still events in the
351 // queue, then process remaining events.
352 if (!mAcceptingEvents && PL_EventAvailable(mEventQueue))
353 PL_ProcessPendingEvents(mEventQueue);
354
355 CheckForDeactivation();
356
357 if (mElderQueue) {
358 nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
359 if (elder)
360 elder->ProcessPendingEvents();
361 }
362
363 return NS_OK;
364}
365
366NS_IMETHODIMP
367nsEventQueueImpl::EventLoop()
368{
369 PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
370
371 NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
372
373 if (!correctThread)
374 return NS_ERROR_FAILURE;
375
376 PL_EventLoop(mEventQueue);
377 return NS_OK;
378}
379
380NS_IMETHODIMP
381nsEventQueueImpl::EventAvailable(PRBool& aResult)
382{
383 aResult = PL_EventAvailable(mEventQueue);
384 return NS_OK;
385}
386
387NS_IMETHODIMP
388nsEventQueueImpl::GetEvent(PLEvent** aResult)
389{
390 *aResult = PL_GetEvent(mEventQueue);
391 CheckForDeactivation();
392 return NS_OK;
393}
394
395NS_IMETHODIMP
396nsEventQueueImpl::HandleEvent(PLEvent* aEvent)
397{
398 PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
399 NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
400 if (!correctThread)
401 return NS_ERROR_FAILURE;
402
403 Log(("EventQueue: handle event [queue=%lx, accept=%d, could=%d]\n",
404 (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
405
406 PL_HandleEvent(aEvent);
407 return NS_OK;
408}
409
410NS_IMETHODIMP
411nsEventQueueImpl::WaitForEvent(PLEvent** aResult)
412{
413 PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
414 NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
415 if (!correctThread)
416 return NS_ERROR_FAILURE;
417
418 Log(("EventQueue: wait for event [queue=%lx, accept=%d, could=%d]\n",
419 (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
420
421 *aResult = PL_WaitForEvent(mEventQueue);
422 CheckForDeactivation();
423 return NS_OK;
424}
425
426NS_IMETHODIMP_(PRInt32)
427nsEventQueueImpl::GetEventQueueSelectFD()
428{
429 return PL_GetEventQueueSelectFD(mEventQueue);
430}
431
432NS_METHOD
433nsEventQueueImpl::Create(nsISupports *aOuter,
434 REFNSIID aIID,
435 void **aResult)
436{
437 nsEventQueueImpl* evt = new nsEventQueueImpl();
438 if (evt == NULL)
439 return NS_ERROR_OUT_OF_MEMORY;
440 nsresult rv = evt->QueryInterface(aIID, aResult);
441 if (NS_FAILED(rv)) {
442 delete evt;
443 }
444 return rv;
445}
446
447// ---------------- nsPIEventQueueChain -----------------
448
449NS_IMETHODIMP
450nsEventQueueImpl::AppendQueue(nsIEventQueue *aQueue)
451{
452 nsresult rv;
453 nsCOMPtr<nsIEventQueue> end;
454 nsCOMPtr<nsPIEventQueueChain> queueChain(do_QueryInterface(aQueue));
455
456 if (!aQueue)
457 return NS_ERROR_NO_INTERFACE;
458
459/* this would be nice
460 NS_ASSERTION(aQueue->mYoungerQueue == NULL && aQueue->mElderQueue == NULL,
461 "event queue repeatedly appended to queue chain");
462*/
463 rv = NS_ERROR_NO_INTERFACE;
464
465#ifdef NS_DEBUG
466 int depth = 0;
467 nsEventQueueImpl *next = this;
468 while (next && depth < 100) {
469 next = NS_STATIC_CAST(nsEventQueueImpl *, next->mYoungerQueue);
470 ++depth;
471 }
472 if (depth > 5) {
473 char warning[80];
474 PR_snprintf(warning, sizeof(warning),
475 "event queue chain length is %d. this is almost certainly a leak.", depth);
476 NS_WARNING(warning);
477 }
478#endif
479
480 // (be careful doing this outside nsEventQueueService's mEventQMonitor)
481
482 GetYoungest(getter_AddRefs(end));
483 nsCOMPtr<nsPIEventQueueChain> endChain(do_QueryInterface(end));
484 if (endChain) {
485 endChain->SetYounger(queueChain);
486 queueChain->SetElder(endChain);
487 rv = NS_OK;
488 }
489 return rv;
490}
491
492NS_IMETHODIMP
493nsEventQueueImpl::Unlink()
494{
495 nsCOMPtr<nsPIEventQueueChain> young = mYoungerQueue,
496 old = mElderQueue;
497
498 Log(("EventQueue: unlink [queue=%lx, younger=%lx, elder=%lx]\n",
499 (long)mEventQueue,(long)mYoungerQueue, (long)mElderQueue.get()));
500
501 // this is probably OK, but shouldn't happen by design, so tell me if it does
502 NS_ASSERTION(!mYoungerQueue, "event queue chain broken in middle");
503
504 // break links early in case the Release cascades back onto us
505 mYoungerQueue = nsnull;
506 mElderQueue = nsnull;
507
508 if (young)
509 young->SetElder(old);
510 if (old) {
511 old->SetYounger(young);
512 }
513 return NS_OK;
514}
515
516NS_IMETHODIMP
517nsEventQueueImpl::GetYoungest(nsIEventQueue **aQueue)
518{
519 if (mYoungerQueue)
520 return mYoungerQueue->GetYoungest(aQueue);
521
522 nsIEventQueue *answer = NS_STATIC_CAST(nsIEventQueue *, this);
523 NS_ADDREF(answer);
524 *aQueue = answer;
525 return NS_OK;
526}
527
528NS_IMETHODIMP
529nsEventQueueImpl::GetYoungestActive(nsIEventQueue **aQueue)
530{
531 nsCOMPtr<nsIEventQueue> answer;
532
533 if (mYoungerQueue)
534 mYoungerQueue->GetYoungestActive(getter_AddRefs(answer));
535 if (!answer) {
536 if (mAcceptingEvents && mCouldHaveEvents)
537 answer = NS_STATIC_CAST(nsIEventQueue *, this);
538 }
539 *aQueue = answer;
540 NS_IF_ADDREF(*aQueue);
541 return NS_OK;
542}
543
544NS_IMETHODIMP
545nsEventQueueImpl::SetYounger(nsPIEventQueueChain *aQueue)
546{
547 mYoungerQueue = aQueue;
548 return NS_OK;
549}
550
551NS_IMETHODIMP
552nsEventQueueImpl::SetElder(nsPIEventQueueChain *aQueue)
553{
554 mElderQueue = aQueue;
555 return NS_OK;
556}
557
558NS_IMETHODIMP
559nsEventQueueImpl::GetYounger(nsIEventQueue **aQueue)
560{
561 if (!mYoungerQueue) {
562 *aQueue = nsnull;
563 return NS_OK;
564 }
565 return mYoungerQueue->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&aQueue);
566}
567
568NS_IMETHODIMP
569nsEventQueueImpl::GetElder(nsIEventQueue **aQueue)
570{
571 if (!mElderQueue) {
572 *aQueue = nsnull;
573 return NS_OK;
574 }
575 return mElderQueue->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&aQueue);
576}
577
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette