tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CacheIOThread.h (5143B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef CacheIOThread__h__
      6 #define CacheIOThread__h__
      7 
      8 #include "nsIThreadInternal.h"
      9 #include "nsISupportsImpl.h"
     10 #include "prthread.h"
     11 #include "nsTArray.h"
     12 #include "mozilla/Monitor.h"
     13 #include "mozilla/Atomics.h"
     14 #include "mozilla/UniquePtr.h"
     15 
     16 class nsIRunnable;
     17 
     18 namespace mozilla {
     19 namespace net {
     20 
     21 namespace detail {
     22 // A class keeping platform specific information needed to
     23 // cancel any long blocking synchronous IO.  Must be predeclared here
     24 // since including windows.h breaks stuff with number of macro definition
     25 // conflicts.
     26 class NativeThreadHandle;
     27 }  // namespace detail
     28 
     29 class CacheIOThread final : public nsIThreadObserver {
     30  virtual ~CacheIOThread();
     31 
     32 public:
     33  NS_DECL_THREADSAFE_ISUPPORTS
     34  NS_DECL_NSITHREADOBSERVER
     35 
     36  CacheIOThread();
     37 
     38  // We have LAST_LEVEL times queues, so keep the inline storage reasonable.
     39  using EventQueue = AutoTArray<nsCOMPtr<nsIRunnable>, 32>;
     40 
     41  enum ELevel : uint32_t {
     42    OPEN_PRIORITY,
     43    READ_PRIORITY,
     44    MANAGEMENT,  // Doesn't do any actual I/O
     45    OPEN,
     46    READ,
     47    WRITE_PRIORITY,
     48    WRITE,
     49    INDEX,
     50    EVICT,
     51    LAST_LEVEL,
     52 
     53    // This is actually executed as the first level, but we want this enum
     54    // value merely as an indicator while other values are used as indexes
     55    // to the queue array.  Hence put at end and not as the first.
     56    XPCOM_LEVEL
     57  };
     58 
     59  nsresult Init();
     60  nsresult Dispatch(nsIRunnable* aRunnable, uint32_t aLevel);
     61  nsresult Dispatch(already_AddRefed<nsIRunnable>, uint32_t aLevel);
     62  // Makes sure that any previously posted event to OPEN or OPEN_PRIORITY
     63  // levels (such as file opennings and dooms) are executed before aRunnable
     64  // that is intended to evict stuff from the cache.
     65  nsresult DispatchAfterPendingOpens(nsIRunnable* aRunnable);
     66  bool IsCurrentThread();
     67 
     68  uint32_t QueueSize(bool highPriority);
     69 
     70  uint32_t EventCounter() const { return mEventCounter; }
     71 
     72  /**
     73   * Callable only on this thread, checks if there is an event waiting in
     74   * the event queue with a higher execution priority.  If so, the result
     75   * is true and the current event handler should break it's work and return
     76   * from Run() method immediately.  The event handler will be rerun again
     77   * when all more priority events are processed.  Events pending after this
     78   * handler (i.e. the one that called YieldAndRerun()) will not execute sooner
     79   * then this handler is executed w/o a call to YieldAndRerun().
     80   */
     81  static bool YieldAndRerun() { return sSelf ? sSelf->YieldInternal() : false; }
     82 
     83  void Shutdown();
     84  // This method checks if there is a long blocking IO on the
     85  // IO thread and tries to cancel it.  It waits maximum of
     86  // two seconds.
     87  void CancelBlockingIO();
     88  already_AddRefed<nsIEventTarget> Target();
     89 
     90  // A stack class used to annotate running interruptable I/O event
     91  class Cancelable {
     92    bool mCancelable;
     93 
     94   public:
     95    explicit Cancelable(bool aCancelable);
     96    ~Cancelable();
     97  };
     98 
     99  // Memory reporting
    100  size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
    101  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
    102 
    103 private:
    104  static void ThreadFunc(void* aClosure);
    105  void ThreadFunc();
    106  void LoopOneLevel(uint32_t aLevel) MOZ_REQUIRES(mMonitor);
    107  bool EventsPending(uint32_t aLastLevel = LAST_LEVEL);
    108  nsresult DispatchInternal(already_AddRefed<nsIRunnable> aRunnable,
    109                            uint32_t aLevel);
    110  bool YieldInternal();
    111 
    112  static CacheIOThread* sSelf;
    113 
    114  mozilla::Monitor mMonitor{"CacheIOThread"};
    115  PRThread* mThread{nullptr};
    116  // Only set in Init(), before the thread is started, which reads it but never
    117  // writes
    118  UniquePtr<detail::NativeThreadHandle> mNativeThreadHandle;
    119  Atomic<nsIThread*> mXPCOMThread{nullptr};
    120  Atomic<uint32_t, Relaxed> mLowestLevelWaiting{LAST_LEVEL};
    121  uint32_t mCurrentlyExecutingLevel{0};  // only accessed on CacheIO Thread
    122 
    123  // Keeps the length of the each event queue, since LoopOneLevel moves all
    124  // events into a local array.
    125  Atomic<int32_t> mQueueLength[LAST_LEVEL];
    126 
    127  EventQueue mEventQueue[LAST_LEVEL] MOZ_GUARDED_BY(mMonitor);
    128  // Raised when nsIEventTarget.Dispatch() is called on this thread
    129  Atomic<bool, Relaxed> mHasXPCOMEvents{false};
    130  // See YieldAndRerun() above
    131  bool mRerunCurrentEvent{false};  // Only accessed on the cache thread
    132  // Signal to process all pending events and then shutdown
    133  // Synchronized by mMonitor
    134  bool mShutdown MOZ_GUARDED_BY(mMonitor){false};
    135  // If > 0 there is currently an I/O operation on the thread that
    136  // can be canceled when after shutdown, see the Shutdown() method
    137  // for usage. Made a counter to allow nesting of the Cancelable class.
    138  Atomic<uint32_t, Relaxed> mIOCancelableEvents{0};
    139  // Event counter that increases with every event processed.
    140  Atomic<uint32_t, Relaxed> mEventCounter{0};
    141 #ifdef DEBUG
    142  bool mInsideLoop MOZ_GUARDED_BY(mMonitor){true};
    143 #endif
    144 };
    145 
    146 }  // namespace net
    147 }  // namespace mozilla
    148 
    149 #endif