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