Coverage Report

Created: 2018-09-25 14:53

/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