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"
12 #include "mozilla/Monitor.h"
13 #include "mozilla/DebugOnly.h"
14 #include "mozilla/Atomics.h"
15 #include "mozilla/UniquePtr.h"
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
27 class NativeThreadHandle
;
30 class CacheIOThread final
: public nsIThreadObserver
{
31 virtual ~CacheIOThread();
34 NS_DECL_THREADSAFE_ISUPPORTS
35 NS_DECL_NSITHREADOBSERVER
39 using EventQueue
= nsTArray
<nsCOMPtr
<nsIRunnable
>>;
41 enum ELevel
: uint32_t {
44 MANAGEMENT
, // Doesn't do any actual I/O
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.
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();
68 uint32_t QueueSize(bool highPriority
);
70 uint32_t EventCounter() const { return mEventCounter
; }
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().
81 static bool YieldAndRerun() { return sSelf
? sSelf
->YieldInternal() : false; }
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
87 void CancelBlockingIO();
88 already_AddRefed
<nsIEventTarget
> Target();
90 // A stack class used to annotate running interruptable I/O event
95 explicit Cancelable(bool aCancelable
);
100 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf
) const;
101 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf
) const;
104 static void ThreadFunc(void* aClosure
);
106 void LoopOneLevel(uint32_t aLevel
) MOZ_REQUIRES(mMonitor
);
107 bool EventsPending(uint32_t aLastLevel
= LAST_LEVEL
);
108 nsresult
DispatchInternal(already_AddRefed
<nsIRunnable
> aRunnable
,
110 bool YieldInternal();
112 static CacheIOThread
* sSelf
;
114 mozilla::Monitor mMonitor
{"CacheIOThread"};
115 PRThread
* mThread
{nullptr};
116 // Only set in Init(), before the thread is started, which reads it but never
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
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
];
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};
142 bool mInsideLoop
MOZ_GUARDED_BY(mMonitor
){true};
147 } // namespace mozilla