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