Context.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef mozilla_dom_cache_Context_h
  6. #define mozilla_dom_cache_Context_h
  7. #include "mozilla/dom/cache/Types.h"
  8. #include "nsCOMPtr.h"
  9. #include "nsISupportsImpl.h"
  10. #include "nsProxyRelease.h"
  11. #include "nsString.h"
  12. #include "nsTArray.h"
  13. #include "nsTObserverArray.h"
  14. class nsIEventTarget;
  15. class nsIThread;
  16. namespace mozilla {
  17. namespace dom {
  18. namespace quota {
  19. class DirectoryLock;
  20. } // namespace quota
  21. namespace cache {
  22. class Action;
  23. class Manager;
  24. // The Context class is RAII-style class for managing IO operations within the
  25. // Cache.
  26. //
  27. // When a Context is created it performs the complicated steps necessary to
  28. // initialize the QuotaManager. Action objects dispatched on the Context are
  29. // delayed until this initialization is complete. They are then allow to
  30. // execute on any specified thread. Once all references to the Context are
  31. // gone, then the steps necessary to release the QuotaManager are performed.
  32. // After initialization the Context holds a self reference, so it will stay
  33. // alive until one of three conditions occur:
  34. //
  35. // 1) The Manager will call Context::AllowToClose() when all of the actors
  36. // have removed themselves as listener. This means an idle context with
  37. // no active DOM objects will close gracefully.
  38. // 2) The QuotaManager aborts all operations so it can delete the files.
  39. // In this case the QuotaManager calls Client::AbortOperations() which
  40. // in turn cancels all existing Action objects and then marks the Manager
  41. // as invalid.
  42. // 3) Browser shutdown occurs and the Manager calls Context::CancelAll().
  43. //
  44. // In either case, though, the Action objects must be destroyed first to
  45. // allow the Context to be destroyed.
  46. //
  47. // While the Context performs operations asynchronously on threads, all of
  48. // methods in its public interface must be called on the same thread
  49. // originally used to create the Context.
  50. //
  51. // As an invariant, all Context objects must be destroyed before permitting
  52. // the "profile-before-change" shutdown event to complete. This is ensured
  53. // via the code in ShutdownObserver.cpp.
  54. class Context final
  55. {
  56. typedef mozilla::dom::quota::DirectoryLock DirectoryLock;
  57. public:
  58. // Define a class allowing other threads to hold the Context alive. This also
  59. // allows these other threads to safely close or cancel the Context.
  60. class ThreadsafeHandle final
  61. {
  62. friend class Context;
  63. public:
  64. void AllowToClose();
  65. void InvalidateAndAllowToClose();
  66. private:
  67. explicit ThreadsafeHandle(Context* aContext);
  68. ~ThreadsafeHandle();
  69. // disallow copying
  70. ThreadsafeHandle(const ThreadsafeHandle&) = delete;
  71. ThreadsafeHandle& operator=(const ThreadsafeHandle&) = delete;
  72. void AllowToCloseOnOwningThread();
  73. void InvalidateAndAllowToCloseOnOwningThread();
  74. void ContextDestroyed(Context* aContext);
  75. // Cleared to allow the Context to close. Only safe to access on
  76. // owning thread.
  77. RefPtr<Context> mStrongRef;
  78. // Used to support cancelation even while the Context is already allowed
  79. // to close. Cleared by ~Context() calling ContextDestroyed(). Only
  80. // safe to access on owning thread.
  81. Context* mWeakRef;
  82. nsCOMPtr<nsIThread> mOwningThread;
  83. NS_INLINE_DECL_THREADSAFE_REFCOUNTING(cache::Context::ThreadsafeHandle)
  84. };
  85. // Different objects hold references to the Context while some work is being
  86. // performed asynchronously. These objects must implement the Activity
  87. // interface and register themselves with the AddActivity(). When they are
  88. // destroyed they must call RemoveActivity(). This allows the Context to
  89. // cancel any outstanding Activity work when the Context is cancelled.
  90. class Activity
  91. {
  92. public:
  93. virtual void Cancel() = 0;
  94. virtual bool MatchesCacheId(CacheId aCacheId) const = 0;
  95. };
  96. // Create a Context attached to the given Manager. The given Action
  97. // will run on the QuotaManager IO thread. Note, this Action must
  98. // be execute synchronously.
  99. static already_AddRefed<Context>
  100. Create(Manager* aManager, nsIThread* aTarget,
  101. Action* aInitAction, Context* aOldContext);
  102. // Execute given action on the target once the quota manager has been
  103. // initialized.
  104. //
  105. // Only callable from the thread that created the Context.
  106. void Dispatch(Action* aAction);
  107. // Cancel any Actions running or waiting to run. This should allow the
  108. // Context to be released and Listener::RemoveContext() will be called
  109. // when complete.
  110. //
  111. // Only callable from the thread that created the Context.
  112. void CancelAll();
  113. // True if CancelAll() has been called.
  114. bool IsCanceled() const;
  115. // Like CancelAll(), but also marks the Manager as "invalid".
  116. void Invalidate();
  117. // Remove any self references and allow the Context to be released when
  118. // there are no more Actions to process.
  119. void AllowToClose();
  120. // Cancel any Actions running or waiting to run that operate on the given
  121. // cache ID.
  122. //
  123. // Only callable from the thread that created the Context.
  124. void CancelForCacheId(CacheId aCacheId);
  125. void AddActivity(Activity* aActivity);
  126. void RemoveActivity(Activity* aActivity);
  127. const QuotaInfo&
  128. GetQuotaInfo() const
  129. {
  130. return mQuotaInfo;
  131. }
  132. // Tell the Context that some state information has been orphaned in the
  133. // data store and won't be cleaned up. The Context will leave the marker
  134. // in place to trigger cleanup the next times its opened.
  135. void NoteOrphanedData();
  136. private:
  137. class Data;
  138. class QuotaInitRunnable;
  139. class ActionRunnable;
  140. enum State
  141. {
  142. STATE_CONTEXT_PREINIT,
  143. STATE_CONTEXT_INIT,
  144. STATE_CONTEXT_READY,
  145. STATE_CONTEXT_CANCELED
  146. };
  147. struct PendingAction
  148. {
  149. nsCOMPtr<nsIEventTarget> mTarget;
  150. RefPtr<Action> mAction;
  151. };
  152. Context(Manager* aManager, nsIThread* aTarget, Action* aInitAction);
  153. ~Context();
  154. void Init(Context* aOldContext);
  155. void Start();
  156. void DispatchAction(Action* aAction, bool aDoomData = false);
  157. void OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
  158. already_AddRefed<DirectoryLock> aDirectoryLock);
  159. already_AddRefed<ThreadsafeHandle>
  160. CreateThreadsafeHandle();
  161. void
  162. SetNextContext(Context* aNextContext);
  163. void
  164. DoomTargetData();
  165. RefPtr<Manager> mManager;
  166. nsCOMPtr<nsIThread> mTarget;
  167. RefPtr<Data> mData;
  168. State mState;
  169. bool mOrphanedData;
  170. QuotaInfo mQuotaInfo;
  171. RefPtr<QuotaInitRunnable> mInitRunnable;
  172. RefPtr<Action> mInitAction;
  173. nsTArray<PendingAction> mPendingActions;
  174. // Weak refs since activites must remove themselves from this list before
  175. // being destroyed by calling RemoveActivity().
  176. typedef nsTObserverArray<Activity*> ActivityList;
  177. ActivityList mActivityList;
  178. // The ThreadsafeHandle may have a strong ref back to us. This creates
  179. // a ref-cycle that keeps the Context alive. The ref-cycle is broken
  180. // when ThreadsafeHandle::AllowToClose() is called.
  181. RefPtr<ThreadsafeHandle> mThreadsafeHandle;
  182. RefPtr<DirectoryLock> mDirectoryLock;
  183. RefPtr<Context> mNextContext;
  184. public:
  185. NS_INLINE_DECL_REFCOUNTING(cache::Context)
  186. };
  187. } // namespace cache
  188. } // namespace dom
  189. } // namespace mozilla
  190. #endif // mozilla_dom_cache_Context_h