File: nsInputStreamPump.h

package info (click to toggle)
firefox 149.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,767,760 kB
  • sloc: cpp: 7,416,064; javascript: 6,752,859; ansic: 3,774,850; python: 1,250,473; xml: 641,578; asm: 439,191; java: 186,617; sh: 56,634; makefile: 18,856; objc: 13,092; perl: 12,763; pascal: 5,960; yacc: 4,583; cs: 3,846; lex: 1,720; ruby: 1,002; php: 436; lisp: 258; awk: 105; sql: 66; sed: 53; csh: 10; exp: 6
file content (134 lines) | stat: -rw-r--r-- 5,357 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 nsInputStreamPump_h_
#define nsInputStreamPump_h_

#include "nsIInputStreamPump.h"
#include "nsIAsyncInputStream.h"
#include "nsIThreadRetargetableRequest.h"
#include "nsCOMPtr.h"
#include "mozilla/Attributes.h"
#include "mozilla/RecursiveMutex.h"

#ifdef DEBUG
#  include "MainThreadUtils.h"
#  include "nsISerialEventTarget.h"
#endif

class nsIInputStream;
class nsILoadGroup;
class nsIStreamListener;

#define NS_INPUT_STREAM_PUMP_IID \
  {0x42f1cc9b, 0xdf5f, 0x4c9b, {0xbd, 0x71, 0x8d, 0x4a, 0xe2, 0x27, 0xc1, 0x8a}}

class nsInputStreamPump final : public nsIInputStreamPump,
                                public nsIInputStreamCallback,
                                public nsIThreadRetargetableRequest {
  ~nsInputStreamPump() = default;

 public:
  using RecursiveMutexAutoLock = mozilla::RecursiveMutexAutoLock;
  using RecursiveMutexAutoUnlock = mozilla::RecursiveMutexAutoUnlock;
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSIREQUEST
  NS_DECL_NSIINPUTSTREAMPUMP
  NS_DECL_NSIINPUTSTREAMCALLBACK
  NS_DECL_NSITHREADRETARGETABLEREQUEST
  NS_INLINE_DECL_STATIC_IID(NS_INPUT_STREAM_PUMP_IID)

  nsInputStreamPump();

  static nsresult Create(nsInputStreamPump** result, nsIInputStream* stream,
                         uint32_t segsize = 0, uint32_t segcount = 0,
                         bool closeWhenDone = false,
                         nsISerialEventTarget* mainThreadTarget = nullptr);

  using PeekSegmentFun = void (*)(void*, const uint8_t*, uint32_t);
  /**
   * Peek into the first chunk of data that's in the stream. Note that this
   * method will not call the callback when there is no data in the stream.
   * The callback will be called at most once.
   *
   * The data from the stream will not be consumed, i.e. the pump's listener
   * can still read all the data
   *
   * Do not call before asyncRead. Do not call after onStopRequest.
   */
  nsresult PeekStream(PeekSegmentFun callback, void* closure);

  /**
   * Dispatched (to the main thread) by OnStateStop if it's called off main
   * thread. Updates mState based on return value of OnStateStop.
   */
  nsresult CallOnStateStop();

  /**
   * Used by nsPipe to dispatch events with increased priority.
   */
  void SetHighPriority(bool aHighPriority) {
    mHighPriorityStream = aHighPriority;
  }
  bool IsHighPriority() { return mHighPriorityStream; }

 protected:
  enum { STATE_IDLE, STATE_START, STATE_TRANSFER, STATE_STOP, STATE_DEAD };

  nsresult EnsureWaiting();
  uint32_t OnStateStart();
  uint32_t OnStateTransfer();
  uint32_t OnStateStop();
  nsresult CreateBufferedStreamIfNeeded() MOZ_REQUIRES(mMutex);

  // This should optimize away in non-DEBUG builds
  MOZ_ALWAYS_INLINE void AssertOnThread() const MOZ_REQUIRES(mMutex) {
    if (mOffMainThread) {
      MOZ_ASSERT(mTargetThread->IsOnCurrentThread());
    } else {
      MOZ_ASSERT(NS_IsMainThread());
    }
  }

  uint32_t mState MOZ_GUARDED_BY(mMutex){STATE_IDLE};
  nsCOMPtr<nsILoadGroup> mLoadGroup MOZ_GUARDED_BY(mMutex);
  // mListener is written on a single thread (either MainThread or an
  // off-MainThread thread), read from that thread and perhaps others (in
  // RetargetDeliveryTo)
  nsCOMPtr<nsIStreamListener> mListener MOZ_GUARDED_BY(mMutex);
  nsCOMPtr<nsISerialEventTarget> mTargetThread MOZ_GUARDED_BY(mMutex);
  nsCOMPtr<nsISerialEventTarget> mLabeledMainThreadTarget
      MOZ_GUARDED_BY(mMutex);
  nsCOMPtr<nsIInputStream> mStream MOZ_GUARDED_BY(mMutex);
  // mAsyncStream is written on a single thread (either MainThread or an
  // off-MainThread thread), and lives from AsyncRead() to OnStateStop().
  nsCOMPtr<nsIAsyncInputStream> mAsyncStream MOZ_GUARDED_BY(mMutex);
  uint64_t mStreamOffset MOZ_GUARDED_BY(mMutex){0};
  uint64_t mStreamLength MOZ_GUARDED_BY(mMutex){0};
  uint32_t mSegSize MOZ_GUARDED_BY(mMutex){0};
  uint32_t mSegCount MOZ_GUARDED_BY(mMutex){0};
  nsresult mStatus MOZ_GUARDED_BY(mMutex){NS_OK};
  uint32_t mSuspendCount MOZ_GUARDED_BY(mMutex){0};
  uint32_t mLoadFlags MOZ_GUARDED_BY(mMutex){LOAD_NORMAL};
  bool mIsPending MOZ_GUARDED_BY(mMutex){false};
  // True while in OnInputStreamReady, calling OnStateStart, OnStateTransfer
  // and OnStateStop. Used to prevent calls to AsyncWait during callbacks.
  bool mProcessingCallbacks MOZ_GUARDED_BY(mMutex){false};
  // True if waiting on the "input stream ready" callback.
  bool mWaitingForInputStreamReady MOZ_GUARDED_BY(mMutex){false};
  bool mCloseWhenDone MOZ_GUARDED_BY(mMutex){false};
  bool mRetargeting MOZ_GUARDED_BY(mMutex){false};
  bool mAsyncStreamIsBuffered MOZ_GUARDED_BY(mMutex){false};
  // Indicate whether nsInputStreamPump is used completely off main thread.
  // If true, OnStateStop() is executed off main thread. Set at creation.
  const bool mOffMainThread;
  // Protects state/member var accesses across multiple threads.
  mozilla::RecursiveMutex mMutex{"nsInputStreamPump"};
  // Whether events from this input stream should be dispatched
  // with increased priority
  mozilla::Atomic<bool, mozilla::Relaxed> mHighPriorityStream{false};
};

#endif  // !nsInputStreamChannel_h_