netwerk/cache2/CacheIOThread.h
author Gregor Wagner <gwagner@mozilla.com>
Fri, 12 Feb 2016 19:21:30 +0100
changeset 388242 b65c9eaa99ab0d00ebaca3ac81f66260c63a78c5
parent 319855 1725b75a6604ee303ed83236c0caed41671de849
child 336257 ca3e12a665c020b6d26768dbd2235f73d8b20064
permissions -rw-r--r--
merge mc -> pine

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef CacheIOThread__h__
#define CacheIOThread__h__

#include "nsIThreadInternal.h"
#include "nsISupportsImpl.h"
#include "prthread.h"
#include "nsTArray.h"
#include "nsAutoPtr.h"
#include "mozilla/Monitor.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Atomics.h"

class nsIRunnable;

namespace mozilla {
namespace net {

class CacheIOThread : public nsIThreadObserver
{
  virtual ~CacheIOThread();

public:
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSITHREADOBSERVER

  CacheIOThread();

  enum ELevel {
    OPEN_PRIORITY,
    READ_PRIORITY,
    OPEN,
    READ,
    MANAGEMENT,
    WRITE,
    CLOSE = WRITE,
    INDEX,
    EVICT,
    LAST_LEVEL,

    // This is actually executed as the first level, but we want this enum
    // value merely as an indicator while other values are used as indexes
    // to the queue array.  Hence put at end and not as the first.
    XPCOM_LEVEL
  };

  nsresult Init();
  nsresult Dispatch(nsIRunnable* aRunnable, uint32_t aLevel);
  // Makes sure that any previously posted event to OPEN or OPEN_PRIORITY
  // levels (such as file opennings and dooms) are executed before aRunnable
  // that is intended to evict stuff from the cache.
  nsresult DispatchAfterPendingOpens(nsIRunnable* aRunnable);
  bool IsCurrentThread();

  /**
   * Callable only on this thread, checks if there is an event waiting in
   * the event queue with a higher execution priority.  If so, the result
   * is true and the current event handler should break it's work and return
   * from Run() method immediately.  The event handler will be rerun again
   * when all more priority events are processed.  Events pending after this
   * handler (i.e. the one that called YieldAndRerun()) will not execute sooner
   * then this handler is executed w/o a call to YieldAndRerun().
   */
  static bool YieldAndRerun()
  {
    return sSelf ? sSelf->YieldInternal() : false;
  }

  nsresult Shutdown();
  already_AddRefed<nsIEventTarget> Target();

  // Memory reporting
  size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;

private:
  static void ThreadFunc(void* aClosure);
  void ThreadFunc();
  void LoopOneLevel(uint32_t aLevel);
  bool EventsPending(uint32_t aLastLevel = LAST_LEVEL);
  nsresult DispatchInternal(nsIRunnable* aRunnable, uint32_t aLevel);
  bool YieldInternal();

  static CacheIOThread* sSelf;

  mozilla::Monitor mMonitor;
  PRThread* mThread;
  Atomic<nsIThread *> mXPCOMThread;
  Atomic<uint32_t, Relaxed> mLowestLevelWaiting;
  uint32_t mCurrentlyExecutingLevel;
  nsTArray<nsCOMPtr<nsIRunnable> > mEventQueue[LAST_LEVEL];

  Atomic<bool, Relaxed> mHasXPCOMEvents;
  bool mRerunCurrentEvent;
  bool mShutdown;
  DebugOnly<bool> mInsideLoop;
};

} // namespace net
} // namespace mozilla

#endif