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.h149
1 files changed, 149 insertions, 0 deletions
diff --git a/netwerk/cache2/CacheIOThread.h b/netwerk/cache2/CacheIOThread.h
new file mode 100644
index 0000000000..4cb8a964b8
--- /dev/null
+++ b/netwerk/cache2/CacheIOThread.h
@@ -0,0 +1,149 @@
+/* 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 "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
+// cancel any long blocking synchronous IO. Must be predeclared here
+// since including windows.h breaks stuff with number of macro definition
+// conflicts.
+class NativeThreadHandle;
+} // namespace detail
+
+class CacheIOThread final : public nsIThreadObserver {
+ virtual ~CacheIOThread();
+
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSITHREADOBSERVER
+
+ CacheIOThread();
+
+ using EventQueue = nsTArray<nsCOMPtr<nsIRunnable>>;
+
+ 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);
+
+ uint32_t EventCounter() const { return mEventCounter; }
+
+ /**
+ * 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) MOZ_REQUIRES(mMonitor);
+ bool EventsPending(uint32_t aLastLevel = LAST_LEVEL);
+ nsresult DispatchInternal(already_AddRefed<nsIRunnable> aRunnable,
+ uint32_t aLevel);
+ bool YieldInternal();
+
+ static CacheIOThread* sSelf;
+
+ mozilla::Monitor mMonitor{"CacheIOThread"};
+ PRThread* mThread{nullptr};
+ // Only set in Init(), before the thread is started, which reads it but never
+ // writes
+ UniquePtr<detail::NativeThreadHandle> mNativeThreadHandle;
+ Atomic<nsIThread*> mXPCOMThread{nullptr};
+ Atomic<uint32_t, Relaxed> mLowestLevelWaiting{LAST_LEVEL};
+ uint32_t mCurrentlyExecutingLevel{0}; // only accessed on CacheIO Thread
+
+ // 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] MOZ_GUARDED_BY(mMonitor);
+ // Raised when nsIEventTarget.Dispatch() is called on this thread
+ Atomic<bool, Relaxed> mHasXPCOMEvents{false};
+ // See YieldAndRerun() above
+ bool mRerunCurrentEvent{false}; // Only accessed on the cache thread
+ // Signal to process all pending events and then shutdown
+ // Synchronized by mMonitor
+ bool mShutdown MOZ_GUARDED_BY(mMonitor){false};
+ // 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{0};
+ // Event counter that increases with every event processed.
+ Atomic<uint32_t, Relaxed> mEventCounter{0};
+#ifdef DEBUG
+ bool mInsideLoop MOZ_GUARDED_BY(mMonitor){true};
+#endif
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif