xpcom/threads/LazyIdleThread.h

changeset 0
6474c204b198
     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__

mercurial