Timeout.h (5665B)
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 #ifndef mozilla_dom_timeout_h 8 #define mozilla_dom_timeout_h 9 10 #include "GeckoProfiler.h" 11 #include "mozilla/LinkedList.h" 12 #include "mozilla/TimeStamp.h" 13 #include "mozilla/dom/PopupBlocker.h" 14 #include "nsCycleCollectionParticipant.h" 15 #include "nsGlobalWindowInner.h" 16 #include "nsTHashMap.h" 17 18 namespace mozilla::dom { 19 20 class TimeoutHandler; 21 22 /* 23 * Timeout struct that holds information about each script 24 * timeout. Holds a strong reference to an nsITimeoutHandler, which 25 * abstracts the language specific cruft. 26 */ 27 class Timeout final : protected LinkedListElement<RefPtr<Timeout>> { 28 public: 29 Timeout(); 30 31 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(Timeout) 32 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Timeout) 33 34 enum class Reason : uint8_t { 35 eTimeoutOrInterval, 36 eIdleCallbackTimeout, 37 eAbortSignalTimeout, 38 eDelayedWebTaskTimeout, 39 eJSTimeout, 40 }; 41 42 struct TimeoutIdAndReason { 43 int32_t mId; 44 Reason mReason; 45 }; 46 47 class TimeoutHashKey : public PLDHashEntryHdr { 48 public: 49 typedef const TimeoutIdAndReason& KeyType; 50 typedef const TimeoutIdAndReason* KeyTypePointer; 51 52 explicit TimeoutHashKey(KeyTypePointer aKey) : mValue(*aKey) {} 53 TimeoutHashKey(TimeoutHashKey&& aOther) 54 : PLDHashEntryHdr(std::move(aOther)), 55 mValue(std::move(aOther.mValue)) {} 56 ~TimeoutHashKey() = default; 57 58 KeyType GetKey() const { return mValue; } 59 bool KeyEquals(KeyTypePointer aKey) const { 60 return aKey->mId == mValue.mId && aKey->mReason == mValue.mReason; 61 } 62 63 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } 64 static PLDHashNumber HashKey(KeyTypePointer aKey) { 65 return aKey->mId | (static_cast<uint8_t>(aKey->mReason) << 31); 66 } 67 enum { ALLOW_MEMMOVE = true }; 68 69 private: 70 const TimeoutIdAndReason mValue; 71 }; 72 73 class TimeoutSet : public nsTHashMap<TimeoutHashKey, Timeout*> { 74 public: 75 NS_INLINE_DECL_REFCOUNTING(TimeoutSet); 76 77 private: 78 ~TimeoutSet() = default; 79 }; 80 81 void SetWhenOrTimeRemaining(const TimeStamp& aBaseTime, 82 const TimeDuration& aDelay); 83 84 // Can only be called when not frozen. 85 const TimeStamp& When() const; 86 87 const TimeStamp& SubmitTime() const; 88 89 // Can only be called when frozen. 90 const TimeDuration& TimeRemaining() const; 91 92 void SetTimeoutContainer(TimeoutSet* aTimeouts) { 93 MOZ_ASSERT(mTimeoutId != 0); 94 TimeoutIdAndReason key = {mTimeoutId, mReason}; 95 if (mTimeouts) { 96 mTimeouts->Remove(key); 97 } 98 mTimeouts = aTimeouts; 99 if (mTimeouts) { 100 mTimeouts->InsertOrUpdate(key, this); 101 } 102 } 103 104 // Override some LinkedListElement methods so that remove() 105 // calls can call SetTimeoutContainer. 106 Timeout* getNext() { return LinkedListElement<RefPtr<Timeout>>::getNext(); } 107 108 void setNext(Timeout* aNext) { 109 return LinkedListElement<RefPtr<Timeout>>::setNext(aNext); 110 } 111 112 Timeout* getPrevious() { 113 return LinkedListElement<RefPtr<Timeout>>::getPrevious(); 114 } 115 116 void remove() { 117 SetTimeoutContainer(nullptr); 118 LinkedListElement<RefPtr<Timeout>>::remove(); 119 } 120 121 UniquePtr<ProfileChunkedBuffer> TakeProfilerBacktrace() { 122 return std::move(mCause); 123 } 124 125 private: 126 // mWhen and mTimeRemaining can't be in a union, sadly, because they 127 // have constructors. 128 // Nominal time to run this timeout. Use only when timeouts are not 129 // frozen. 130 TimeStamp mWhen; 131 132 // Remaining time to wait. Used only when timeouts are frozen. 133 TimeDuration mTimeRemaining; 134 135 // Time that the timeout started, restarted, or was frozen. Useful for 136 // logging time from (virtual) start of a timer until the time it fires 137 // (or is cancelled, etc) 138 TimeStamp mSubmitTime; 139 140 ~Timeout(); 141 142 public: 143 // Public member variables in this section. Please don't add to this list 144 // or mix methods with these. The interleaving public/private sections 145 // is necessary as we migrate members to private while still trying to 146 // keep decent binary packing. 147 148 // Global object for which this timeout fires 149 RefPtr<nsIGlobalObject> mGlobal; 150 151 // The language-specific information about the callback. 152 RefPtr<TimeoutHandler> mScriptHandler; 153 154 RefPtr<TimeoutSet> mTimeouts; 155 156 // Interval 157 TimeDuration mInterval; 158 159 UniquePtr<ProfileChunkedBuffer> mCause; 160 161 // Returned as value of setTimeout() 162 int32_t mTimeoutId; 163 164 // Identifies which firing level this Timeout is being processed in 165 // when sync loops trigger nested firing. 166 uint32_t mFiringId; 167 168 #ifdef DEBUG 169 int64_t mFiringIndex; 170 #endif 171 172 // The popup state at timeout creation time if not created from 173 // another timeout 174 PopupBlocker::PopupControlState mPopupState; 175 176 // Used to allow several reasons for setting a timeout, where each 177 // 'Reason' value is using a possibly overlapping set of id:s. 178 Reason mReason; 179 180 // Between 0 and DOM_CLAMP_TIMEOUT_NESTING_LEVEL. Currently we don't 181 // care about nesting levels beyond that value. 182 uint8_t mNestingLevel; 183 184 // True if the timeout was cleared 185 bool mCleared; 186 187 // True if this is one of the timeouts that are currently running 188 bool mRunning; 189 190 // True if this is a repeating/interval timer 191 bool mIsInterval; 192 193 protected: 194 friend class LinkedList<RefPtr<Timeout>>; 195 friend class LinkedListElement<RefPtr<Timeout>>; 196 }; 197 198 } // namespace mozilla::dom 199 200 #endif // mozilla_dom_timeout_h