1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/threads/LazyIdleThread.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,220 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef mozilla_lazyidlethread_h__ 1.11 +#define mozilla_lazyidlethread_h__ 1.12 + 1.13 +#ifndef MOZILLA_INTERNAL_API 1.14 +#error "This header is only usable from within libxul (MOZILLA_INTERNAL_API)." 1.15 +#endif 1.16 + 1.17 +#include "nsIObserver.h" 1.18 +#include "nsIThreadInternal.h" 1.19 +#include "nsITimer.h" 1.20 + 1.21 +#include "mozilla/Mutex.h" 1.22 +#include "nsCOMPtr.h" 1.23 +#include "nsTArray.h" 1.24 +#include "nsString.h" 1.25 +#include "mozilla/Attributes.h" 1.26 + 1.27 +#define IDLE_THREAD_TOPIC "thread-shutting-down" 1.28 + 1.29 +namespace mozilla { 1.30 + 1.31 +/** 1.32 + * This class provides a basic event target that creates its thread lazily and 1.33 + * destroys its thread after a period of inactivity. It may be created on any 1.34 + * thread but it may only be used from the thread on which it is created. If it 1.35 + * is created on the main thread then it will automatically join its thread on 1.36 + * XPCOM shutdown using the Observer Service. 1.37 + */ 1.38 +class LazyIdleThread MOZ_FINAL : public nsIThread, 1.39 + public nsITimerCallback, 1.40 + public nsIThreadObserver, 1.41 + public nsIObserver 1.42 +{ 1.43 +public: 1.44 + NS_DECL_THREADSAFE_ISUPPORTS 1.45 + NS_DECL_NSIEVENTTARGET 1.46 + NS_DECL_NSITHREAD 1.47 + NS_DECL_NSITIMERCALLBACK 1.48 + NS_DECL_NSITHREADOBSERVER 1.49 + NS_DECL_NSIOBSERVER 1.50 + 1.51 + enum ShutdownMethod { 1.52 + AutomaticShutdown = 0, 1.53 + ManualShutdown 1.54 + }; 1.55 + 1.56 + /** 1.57 + * Create a new LazyIdleThread that will destroy its thread after the given 1.58 + * number of milliseconds. 1.59 + */ 1.60 + LazyIdleThread(uint32_t aIdleTimeoutMS, 1.61 + const nsCSubstring& aName, 1.62 + ShutdownMethod aShutdownMethod = AutomaticShutdown, 1.63 + nsIObserver* aIdleObserver = nullptr); 1.64 + 1.65 + /** 1.66 + * Add an observer that will be notified when the thread is idle and about to 1.67 + * be shut down. The aSubject argument can be QueryInterface'd to an nsIThread 1.68 + * that can be used to post cleanup events. The aTopic argument will be 1.69 + * IDLE_THREAD_TOPIC, and aData will be null. The LazyIdleThread does not add 1.70 + * a reference to the observer to avoid circular references as it is assumed 1.71 + * to be the owner. It is the caller's responsibility to clear this observer 1.72 + * if the pointer becomes invalid. 1.73 + */ 1.74 + void SetWeakIdleObserver(nsIObserver* aObserver); 1.75 + 1.76 + /** 1.77 + * Disable the idle timeout for this thread. No effect if the timeout is 1.78 + * already disabled. 1.79 + */ 1.80 + void DisableIdleTimeout(); 1.81 + 1.82 + /** 1.83 + * Enable the idle timeout. No effect if the timeout is already enabled. 1.84 + */ 1.85 + void EnableIdleTimeout(); 1.86 + 1.87 +private: 1.88 + /** 1.89 + * Calls Shutdown(). 1.90 + */ 1.91 + ~LazyIdleThread(); 1.92 + 1.93 + /** 1.94 + * Called just before dispatching to mThread. 1.95 + */ 1.96 + void PreDispatch(); 1.97 + 1.98 + /** 1.99 + * Makes sure a valid thread lives in mThread. 1.100 + */ 1.101 + nsresult EnsureThread(); 1.102 + 1.103 + /** 1.104 + * Called on mThread to set up the thread observer. 1.105 + */ 1.106 + void InitThread(); 1.107 + 1.108 + /** 1.109 + * Called on mThread to clean up the thread observer. 1.110 + */ 1.111 + void CleanupThread(); 1.112 + 1.113 + /** 1.114 + * Called on the main thread when mThread believes itself to be idle. Sets up 1.115 + * the idle timer. 1.116 + */ 1.117 + void ScheduleTimer(); 1.118 + 1.119 + /** 1.120 + * Called when we are shutting down mThread. 1.121 + */ 1.122 + nsresult ShutdownThread(); 1.123 + 1.124 + /** 1.125 + * Deletes this object. Used to delay calling mThread->Shutdown() during the 1.126 + * final release (during a GC, for instance). 1.127 + */ 1.128 + void SelfDestruct(); 1.129 + 1.130 + /** 1.131 + * Returns true if events should be queued rather than immediately dispatched 1.132 + * to mThread. Currently only happens when the thread is shutting down. 1.133 + */ 1.134 + bool UseRunnableQueue() { 1.135 + return !!mQueuedRunnables; 1.136 + } 1.137 + 1.138 + /** 1.139 + * Protects data that is accessed on both threads. 1.140 + */ 1.141 + mozilla::Mutex mMutex; 1.142 + 1.143 + /** 1.144 + * Touched on both threads but set before mThread is created. Used to direct 1.145 + * timer events to the owning thread. 1.146 + */ 1.147 + nsCOMPtr<nsIThread> mOwningThread; 1.148 + 1.149 + /** 1.150 + * Only accessed on the owning thread. Set by EnsureThread(). 1.151 + */ 1.152 + nsCOMPtr<nsIThread> mThread; 1.153 + 1.154 + /** 1.155 + * Protected by mMutex. Created when mThread has no pending events and fired 1.156 + * at mOwningThread. Any thread that dispatches to mThread will take ownership 1.157 + * of the timer and fire a separate cancel event to the owning thread. 1.158 + */ 1.159 + nsCOMPtr<nsITimer> mIdleTimer; 1.160 + 1.161 + /** 1.162 + * Idle observer. Called when the thread is about to be shut down. Released 1.163 + * only when Shutdown() is called. 1.164 + */ 1.165 + nsIObserver* mIdleObserver; 1.166 + 1.167 + /** 1.168 + * Temporary storage for events that happen to be dispatched while we're in 1.169 + * the process of shutting down our real thread. 1.170 + */ 1.171 + nsTArray<nsCOMPtr<nsIRunnable> >* mQueuedRunnables; 1.172 + 1.173 + /** 1.174 + * The number of milliseconds a thread should be idle before dying. 1.175 + */ 1.176 + const uint32_t mIdleTimeoutMS; 1.177 + 1.178 + /** 1.179 + * The number of events that are pending on mThread. A nonzero value means 1.180 + * that the thread cannot be cleaned up. 1.181 + */ 1.182 + uint32_t mPendingEventCount; 1.183 + 1.184 + /** 1.185 + * The number of times that mThread has dispatched an idle notification. Any 1.186 + * timer that fires while this count is nonzero can safely be ignored as 1.187 + * another timer will be on the way. 1.188 + */ 1.189 + uint32_t mIdleNotificationCount; 1.190 + 1.191 + /** 1.192 + * Whether or not the thread should automatically shutdown. If the owner 1.193 + * specified ManualShutdown at construction time then the owner should take 1.194 + * care to call Shutdown() manually when appropriate. 1.195 + */ 1.196 + ShutdownMethod mShutdownMethod; 1.197 + 1.198 + /** 1.199 + * Only accessed on the owning thread. Set to true when Shutdown() has been 1.200 + * called and prevents EnsureThread() from recreating mThread. 1.201 + */ 1.202 + bool mShutdown; 1.203 + 1.204 + /** 1.205 + * Set from CleanupThread and lasting until the thread has shut down. Prevents 1.206 + * further idle notifications during the shutdown process. 1.207 + */ 1.208 + bool mThreadIsShuttingDown; 1.209 + 1.210 + /** 1.211 + * Whether or not the idle timeout is enabled. 1.212 + */ 1.213 + bool mIdleTimeoutEnabled; 1.214 + 1.215 + /** 1.216 + * Name of the thread, set on the actual thread after it gets created. 1.217 + */ 1.218 + nsCString mName; 1.219 +}; 1.220 + 1.221 +} // namespace mozilla 1.222 + 1.223 +#endif // mozilla_lazyidlethread_h__