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/. */
6
7 #include "mozilla/EventQueue.h"
8
9 #include "GeckoProfiler.h"
10 #include "nsIRunnable.h"
11
12 using namespace mozilla;
13 using namespace mozilla::detail;
14
15 template <size_t ItemsPerPage>
EventQueueInternal(EventQueuePriority aPriority)16 EventQueueInternal<ItemsPerPage>::EventQueueInternal(
17 EventQueuePriority aPriority) {}
18
19 template <size_t ItemsPerPage>
PutEvent(already_AddRefed<nsIRunnable> && aEvent,EventQueuePriority aPriority,const MutexAutoLock & aProofOfLock,mozilla::TimeDuration * aDelay)20 void EventQueueInternal<ItemsPerPage>::PutEvent(
21 already_AddRefed<nsIRunnable>&& aEvent, EventQueuePriority aPriority,
22 const MutexAutoLock& aProofOfLock, mozilla::TimeDuration* aDelay) {
23 #ifdef MOZ_GECKO_PROFILER
24 // Sigh, this doesn't check if this thread is being profiled
25 if (profiler_is_active()) {
26 // check to see if the profiler has been enabled since the last PutEvent
27 while (mDispatchTimes.Count() < mQueue.Count()) {
28 mDispatchTimes.Push(TimeStamp());
29 }
30 mDispatchTimes.Push(aDelay ? TimeStamp::Now() - *aDelay : TimeStamp::Now());
31 }
32 #endif
33
34 nsCOMPtr<nsIRunnable> event(aEvent);
35 mQueue.Push(std::move(event));
36 }
37
38 template <size_t ItemsPerPage>
GetEvent(EventQueuePriority * aPriority,const MutexAutoLock & aProofOfLock,mozilla::TimeDuration * aLastEventDelay)39 already_AddRefed<nsIRunnable> EventQueueInternal<ItemsPerPage>::GetEvent(
40 EventQueuePriority* aPriority, const MutexAutoLock& aProofOfLock,
41 mozilla::TimeDuration* aLastEventDelay) {
42 if (mQueue.IsEmpty()) {
43 if (aLastEventDelay) {
44 *aLastEventDelay = TimeDuration();
45 }
46 return nullptr;
47 }
48
49 if (aPriority) {
50 *aPriority = EventQueuePriority::Normal;
51 }
52
53 #ifdef MOZ_GECKO_PROFILER
54 // We always want to clear the dispatch times, even if the profiler is turned
55 // off, because we want to empty the (previously-collected) dispatch times, if
56 // any, from when the profiler was turned on. We only want to do something
57 // interesting with the dispatch times if the profiler is turned on, though.
58 if (!mDispatchTimes.IsEmpty()) {
59 TimeStamp dispatch_time = mDispatchTimes.Pop();
60 if (profiler_is_active()) {
61 if (!dispatch_time.IsNull()) {
62 if (aLastEventDelay) {
63 *aLastEventDelay = TimeStamp::Now() - dispatch_time;
64 }
65 }
66 }
67 } else if (profiler_is_active()) {
68 if (aLastEventDelay) {
69 // if we just turned on the profiler, we don't have dispatch
70 // times for events already in the queue.
71 *aLastEventDelay = TimeDuration();
72 }
73 }
74 #endif
75
76 nsCOMPtr<nsIRunnable> result = mQueue.Pop();
77 return result.forget();
78 }
79
80 template <size_t ItemsPerPage>
IsEmpty(const MutexAutoLock & aProofOfLock)81 bool EventQueueInternal<ItemsPerPage>::IsEmpty(
82 const MutexAutoLock& aProofOfLock) {
83 return mQueue.IsEmpty();
84 }
85
86 template <size_t ItemsPerPage>
HasReadyEvent(const MutexAutoLock & aProofOfLock)87 bool EventQueueInternal<ItemsPerPage>::HasReadyEvent(
88 const MutexAutoLock& aProofOfLock) {
89 return !IsEmpty(aProofOfLock);
90 }
91
92 template <size_t ItemsPerPage>
Count(const MutexAutoLock & aProofOfLock) const93 size_t EventQueueInternal<ItemsPerPage>::Count(
94 const MutexAutoLock& aProofOfLock) const {
95 return mQueue.Count();
96 }
97