Bumping manifests a=b2g-bump
[gecko.git] / xpcom / threads / nsEventQueue.cpp
blob4e5f9fa631ca09a0f0d7a636f328f929933aec31
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsEventQueue.h"
8 #include "nsAutoPtr.h"
9 #include "prlog.h"
10 #include "nsThreadUtils.h"
11 #include "prthread.h"
12 #include "mozilla/ChaosMode.h"
14 using namespace mozilla;
16 #ifdef PR_LOGGING
17 static PRLogModuleInfo*
18 GetLog()
20 static PRLogModuleInfo* sLog;
21 if (!sLog) {
22 sLog = PR_NewLogModule("nsEventQueue");
24 return sLog;
26 #endif
27 #ifdef LOG
28 #undef LOG
29 #endif
30 #define LOG(args) PR_LOG(GetLog(), PR_LOG_DEBUG, args)
32 nsEventQueue::nsEventQueue()
33 : mReentrantMonitor("nsEventQueue.mReentrantMonitor")
34 , mHead(nullptr)
35 , mTail(nullptr)
36 , mOffsetHead(0)
37 , mOffsetTail(0)
41 nsEventQueue::~nsEventQueue()
43 // It'd be nice to be able to assert that no one else is holding the monitor,
44 // but NSPR doesn't really expose APIs for it.
45 NS_ASSERTION(IsEmpty(),
46 "Non-empty event queue being destroyed; events being leaked.");
48 if (mHead) {
49 FreePage(mHead);
53 bool
54 nsEventQueue::GetEvent(bool aMayWait, nsIRunnable** aResult)
57 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
59 while (IsEmpty()) {
60 if (!aMayWait) {
61 if (aResult) {
62 *aResult = nullptr;
64 return false;
66 LOG(("EVENTQ(%p): wait begin\n", this));
67 mon.Wait();
68 LOG(("EVENTQ(%p): wait end\n", this));
71 if (aResult) {
72 *aResult = mHead->mEvents[mOffsetHead++];
74 // Check if mHead points to empty Page
75 if (mOffsetHead == EVENTS_PER_PAGE) {
76 Page* dead = mHead;
77 mHead = mHead->mNext;
78 FreePage(dead);
79 mOffsetHead = 0;
84 return true;
87 void
88 nsEventQueue::PutEvent(nsIRunnable* aRunnable)
90 // Avoid calling AddRef+Release while holding our monitor.
91 nsRefPtr<nsIRunnable> event(aRunnable);
93 if (ChaosMode::isActive()) {
94 // With probability 0.5, yield so other threads have a chance to
95 // dispatch events to this queue first.
96 if (ChaosMode::randomUint32LessThan(2)) {
97 PR_Sleep(PR_INTERVAL_NO_WAIT);
101 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
103 if (!mHead) {
104 mHead = NewPage();
105 MOZ_ASSERT(mHead);
107 mTail = mHead;
108 mOffsetHead = 0;
109 mOffsetTail = 0;
110 } else if (mOffsetTail == EVENTS_PER_PAGE) {
111 Page* page = NewPage();
112 MOZ_ASSERT(page);
114 mTail->mNext = page;
115 mTail = page;
116 mOffsetTail = 0;
119 event.swap(mTail->mEvents[mOffsetTail]);
120 ++mOffsetTail;
121 LOG(("EVENTQ(%p): notify\n", this));
122 mon.NotifyAll();