~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/xpcom/threads/nsEventQueue.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

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