1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsInputStreamPump_h__
7 #define nsInputStreamPump_h__
9 #include "nsIInputStreamPump.h"
10 #include "nsIAsyncInputStream.h"
11 #include "nsIThreadRetargetableRequest.h"
13 #include "mozilla/Attributes.h"
14 #include "mozilla/RecursiveMutex.h"
17 # include "MainThreadUtils.h"
18 # include "nsISerialEventTarget.h"
23 class nsIStreamListener
;
25 #define NS_INPUT_STREAM_PUMP_IID \
27 0x42f1cc9b, 0xdf5f, 0x4c9b, { \
28 0xbd, 0x71, 0x8d, 0x4a, 0xe2, 0x27, 0xc1, 0x8a \
32 class nsInputStreamPump final
: public nsIInputStreamPump
,
33 public nsIInputStreamCallback
,
34 public nsIThreadRetargetableRequest
{
35 ~nsInputStreamPump() = default;
38 using RecursiveMutexAutoLock
= mozilla::RecursiveMutexAutoLock
;
39 using RecursiveMutexAutoUnlock
= mozilla::RecursiveMutexAutoUnlock
;
40 NS_DECL_THREADSAFE_ISUPPORTS
42 NS_DECL_NSIINPUTSTREAMPUMP
43 NS_DECL_NSIINPUTSTREAMCALLBACK
44 NS_DECL_NSITHREADRETARGETABLEREQUEST
45 NS_DECLARE_STATIC_IID_ACCESSOR(NS_INPUT_STREAM_PUMP_IID
)
49 static nsresult
Create(nsInputStreamPump
** result
, nsIInputStream
* stream
,
50 uint32_t segsize
= 0, uint32_t segcount
= 0,
51 bool closeWhenDone
= false,
52 nsISerialEventTarget
* mainThreadTarget
= nullptr);
54 using PeekSegmentFun
= void (*)(void*, const uint8_t*, uint32_t);
56 * Peek into the first chunk of data that's in the stream. Note that this
57 * method will not call the callback when there is no data in the stream.
58 * The callback will be called at most once.
60 * The data from the stream will not be consumed, i.e. the pump's listener
61 * can still read all the data
63 * Do not call before asyncRead. Do not call after onStopRequest.
65 nsresult
PeekStream(PeekSegmentFun callback
, void* closure
);
68 * Dispatched (to the main thread) by OnStateStop if it's called off main
69 * thread. Updates mState based on return value of OnStateStop.
71 nsresult
CallOnStateStop();
74 enum { STATE_IDLE
, STATE_START
, STATE_TRANSFER
, STATE_STOP
, STATE_DEAD
};
76 nsresult
EnsureWaiting();
77 uint32_t OnStateStart();
78 uint32_t OnStateTransfer();
79 uint32_t OnStateStop();
80 nsresult
CreateBufferedStreamIfNeeded() MOZ_REQUIRES(mMutex
);
82 // This should optimize away in non-DEBUG builds
83 MOZ_ALWAYS_INLINE
void AssertOnThread() const MOZ_REQUIRES(mMutex
) {
85 MOZ_ASSERT(mTargetThread
->IsOnCurrentThread());
87 MOZ_ASSERT(NS_IsMainThread());
91 uint32_t mState
MOZ_GUARDED_BY(mMutex
){STATE_IDLE
};
92 nsCOMPtr
<nsILoadGroup
> mLoadGroup
MOZ_GUARDED_BY(mMutex
);
93 // mListener is written on a single thread (either MainThread or an
94 // off-MainThread thread), read from that thread and perhaps others (in
95 // RetargetDeliveryTo)
96 nsCOMPtr
<nsIStreamListener
> mListener
MOZ_GUARDED_BY(mMutex
);
97 nsCOMPtr
<nsISerialEventTarget
> mTargetThread
MOZ_GUARDED_BY(mMutex
);
98 nsCOMPtr
<nsISerialEventTarget
> mLabeledMainThreadTarget
99 MOZ_GUARDED_BY(mMutex
);
100 nsCOMPtr
<nsIInputStream
> mStream
MOZ_GUARDED_BY(mMutex
);
101 // mAsyncStream is written on a single thread (either MainThread or an
102 // off-MainThread thread), and lives from AsyncRead() to OnStateStop().
103 nsCOMPtr
<nsIAsyncInputStream
> mAsyncStream
MOZ_GUARDED_BY(mMutex
);
104 uint64_t mStreamOffset
MOZ_GUARDED_BY(mMutex
){0};
105 uint64_t mStreamLength
MOZ_GUARDED_BY(mMutex
){0};
106 uint32_t mSegSize
MOZ_GUARDED_BY(mMutex
){0};
107 uint32_t mSegCount
MOZ_GUARDED_BY(mMutex
){0};
108 nsresult mStatus
MOZ_GUARDED_BY(mMutex
){NS_OK
};
109 uint32_t mSuspendCount
MOZ_GUARDED_BY(mMutex
){0};
110 uint32_t mLoadFlags
MOZ_GUARDED_BY(mMutex
){LOAD_NORMAL
};
111 bool mIsPending
MOZ_GUARDED_BY(mMutex
){false};
112 // True while in OnInputStreamReady, calling OnStateStart, OnStateTransfer
113 // and OnStateStop. Used to prevent calls to AsyncWait during callbacks.
114 bool mProcessingCallbacks
MOZ_GUARDED_BY(mMutex
){false};
115 // True if waiting on the "input stream ready" callback.
116 bool mWaitingForInputStreamReady
MOZ_GUARDED_BY(mMutex
){false};
117 bool mCloseWhenDone
MOZ_GUARDED_BY(mMutex
){false};
118 bool mRetargeting
MOZ_GUARDED_BY(mMutex
){false};
119 bool mAsyncStreamIsBuffered
MOZ_GUARDED_BY(mMutex
){false};
120 // Indicate whether nsInputStreamPump is used completely off main thread.
121 // If true, OnStateStop() is executed off main thread. Set at creation.
122 const bool mOffMainThread
;
123 // Protects state/member var accesses across multiple threads.
124 mozilla::RecursiveMutex mMutex
{"nsInputStreamPump"};
127 NS_DEFINE_STATIC_IID_ACCESSOR(nsInputStreamPump
, NS_INPUT_STREAM_PUMP_IID
)
129 #endif // !nsInputStreamChannel_h__