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 TimerThread_h___ 8 #define TimerThread_h___ 9 10 #include "nsIObserver.h" 11 #include "nsIRunnable.h" 12 #include "nsIThread.h" 13 14 #include "nsTimerImpl.h" 15 #include "nsThreadUtils.h" 16 17 #include "nsTArray.h" 18 19 #include "mozilla/Atomics.h" 20 #include "mozilla/Attributes.h" 21 #include "mozilla/Monitor.h" 22 #include "mozilla/UniquePtr.h" 23 24 #include <algorithm> 25 26 namespace mozilla { 27 class TimeStamp; 28 } // namespace mozilla 29 30 class TimerThread final : public mozilla::Runnable, public nsIObserver { 31 public: 32 typedef mozilla::Monitor Monitor; 33 typedef mozilla::TimeStamp TimeStamp; 34 typedef mozilla::TimeDuration TimeDuration; 35 36 TimerThread(); 37 nsresult InitLocks(); 38 39 NS_DECL_ISUPPORTS_INHERITED 40 NS_DECL_NSIRUNNABLE 41 NS_DECL_NSIOBSERVER 42 43 nsresult Shutdown(); 44 45 nsresult AddTimer(nsTimerImpl* aTimer); 46 nsresult RemoveTimer(nsTimerImpl* aTimer); 47 TimeStamp FindNextFireTimeForCurrentThread(TimeStamp aDefault, 48 uint32_t aSearchBound); 49 50 void DoBeforeSleep(); 51 void DoAfterSleep(); 52 IsOnTimerThread()53 bool IsOnTimerThread() const { 54 return mThread->SerialEventTarget()->IsOnCurrentThread(); 55 } 56 57 uint32_t AllowedEarlyFiringMicroseconds() const; 58 59 private: 60 ~TimerThread(); 61 62 bool mInitialized; 63 64 // These internal helper methods must be called while mMonitor is held. 65 // AddTimerInternal returns false if the insertion failed. 66 bool AddTimerInternal(nsTimerImpl* aTimer); 67 bool RemoveTimerInternal(nsTimerImpl* aTimer); 68 void RemoveLeadingCanceledTimersInternal(); 69 void RemoveFirstTimerInternal(); 70 nsresult Init(); 71 72 already_AddRefed<nsTimerImpl> PostTimerEvent( 73 already_AddRefed<nsTimerImpl> aTimerRef); 74 75 nsCOMPtr<nsIThread> mThread; 76 Monitor mMonitor; 77 78 bool mShutdown; 79 bool mWaiting; 80 bool mNotified; 81 bool mSleeping; 82 83 class Entry final : public nsTimerImplHolder { 84 const TimeStamp mTimeout; 85 86 public: Entry(const TimeStamp & aMinTimeout,const TimeStamp & aTimeout,nsTimerImpl * aTimerImpl)87 Entry(const TimeStamp& aMinTimeout, const TimeStamp& aTimeout, 88 nsTimerImpl* aTimerImpl) 89 : nsTimerImplHolder(aTimerImpl), 90 mTimeout(std::max(aMinTimeout, aTimeout)) {} 91 Value()92 nsTimerImpl* Value() const { return mTimerImpl; } 93 Take()94 already_AddRefed<nsTimerImpl> Take() { 95 if (mTimerImpl) { 96 mTimerImpl->SetHolder(nullptr); 97 } 98 return mTimerImpl.forget(); 99 } 100 UniquePtrLessThan(mozilla::UniquePtr<Entry> & aLeft,mozilla::UniquePtr<Entry> & aRight)101 static bool UniquePtrLessThan(mozilla::UniquePtr<Entry>& aLeft, 102 mozilla::UniquePtr<Entry>& aRight) { 103 // This is reversed because std::push_heap() sorts the "largest" to 104 // the front of the heap. We want that to be the earliest timer. 105 return aRight->mTimeout < aLeft->mTimeout; 106 } 107 Timeout()108 TimeStamp Timeout() const { return mTimeout; } 109 }; 110 111 nsTArray<mozilla::UniquePtr<Entry>> mTimers; 112 uint32_t mAllowedEarlyFiringMicroseconds; 113 }; 114 115 #endif /* TimerThread_h___ */ 116