summaryrefslogtreecommitdiffstats
path: root/netwerk/cache2/CacheIOThread.h
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/cache2/CacheIOThread.h')
-rw-r--r--netwerk/cache2/CacheIOThread.h147
1 files changed, 147 insertions, 0 deletions
diff --git a/netwerk/cache2/CacheIOThread.h b/netwerk/cache2/CacheIOThread.h
new file mode 100644
index 000000000..ea71f7df0
--- /dev/null
+++ b/netwerk/cache2/CacheIOThread.h
@@ -0,0 +1,147 @@
+/* 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"
+#include "mozilla/UniquePtr.h"
+
+class nsIRunnable;
+
+namespace mozilla {
+namespace net {
+
+namespace detail {
+// A class keeping platform specific information needed to watch and
+// cancel any long blocking synchronous IO. Must be predeclared here
+// since including windows.h breaks stuff with number of macro definition
+// conflicts.
+class BlockingIOWatcher;
+}
+
+class CacheIOThread : public nsIThreadObserver
+{
+ virtual ~CacheIOThread();
+
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSITHREADOBSERVER
+
+ CacheIOThread();
+
+ typedef nsTArray<nsCOMPtr<nsIRunnable>> EventQueue;
+
+ enum ELevel : uint32_t {
+ OPEN_PRIORITY,
+ READ_PRIORITY,
+ MANAGEMENT, // Doesn't do any actual I/O
+ OPEN,
+ READ,
+ WRITE_PRIORITY,
+ 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);
+ nsresult Dispatch(already_AddRefed<nsIRunnable>, 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();
+
+ uint32_t QueueSize(bool highPriority);
+
+ /**
+ * 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;
+ }
+
+ void Shutdown();
+ // This method checks if there is a long blocking IO on the
+ // IO thread and tries to cancel it. It waits maximum of
+ // two seconds.
+ void CancelBlockingIO();
+ already_AddRefed<nsIEventTarget> Target();
+
+ // A stack class used to annotate running interruptable I/O event
+ class Cancelable
+ {
+ bool mCancelable;
+ public:
+ explicit Cancelable(bool aCancelable);
+ ~Cancelable();
+ };
+
+ // 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(already_AddRefed<nsIRunnable> aRunnable, uint32_t aLevel);
+ bool YieldInternal();
+
+ static CacheIOThread* sSelf;
+
+ mozilla::Monitor mMonitor;
+ PRThread* mThread;
+ UniquePtr<detail::BlockingIOWatcher> mBlockingIOWatcher;
+ Atomic<nsIThread *> mXPCOMThread;
+ Atomic<uint32_t, Relaxed> mLowestLevelWaiting;
+ uint32_t mCurrentlyExecutingLevel;
+
+ // Keeps the length of the each event queue, since LoopOneLevel moves all
+ // events into a local array.
+ Atomic<int32_t> mQueueLength[LAST_LEVEL];
+
+ EventQueue mEventQueue[LAST_LEVEL];
+ // Raised when nsIEventTarget.Dispatch() is called on this thread
+ Atomic<bool, Relaxed> mHasXPCOMEvents;
+ // See YieldAndRerun() above
+ bool mRerunCurrentEvent;
+ // Signal to process all pending events and then shutdown
+ // Synchronized by mMonitor
+ bool mShutdown;
+ // If > 0 there is currently an I/O operation on the thread that
+ // can be canceled when after shutdown, see the Shutdown() method
+ // for usage. Made a counter to allow nesting of the Cancelable class.
+ Atomic<uint32_t, Relaxed> mIOCancelableEvents;
+#ifdef DEBUG
+ bool mInsideLoop;
+#endif
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif