nsInputStreamPump.h (4974B)
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/. */ 5 6 #ifndef nsInputStreamPump_h__ 7 #define nsInputStreamPump_h__ 8 9 #include "nsIInputStreamPump.h" 10 #include "nsIAsyncInputStream.h" 11 #include "nsIThreadRetargetableRequest.h" 12 #include "nsCOMPtr.h" 13 #include "mozilla/Attributes.h" 14 #include "mozilla/RecursiveMutex.h" 15 16 #ifdef DEBUG 17 # include "MainThreadUtils.h" 18 # include "nsISerialEventTarget.h" 19 #endif 20 21 class nsIInputStream; 22 class nsILoadGroup; 23 class nsIStreamListener; 24 25 #define NS_INPUT_STREAM_PUMP_IID \ 26 {0x42f1cc9b, 0xdf5f, 0x4c9b, {0xbd, 0x71, 0x8d, 0x4a, 0xe2, 0x27, 0xc1, 0x8a}} 27 28 class nsInputStreamPump final : public nsIInputStreamPump, 29 public nsIInputStreamCallback, 30 public nsIThreadRetargetableRequest { 31 ~nsInputStreamPump() = default; 32 33 public: 34 using RecursiveMutexAutoLock = mozilla::RecursiveMutexAutoLock; 35 using RecursiveMutexAutoUnlock = mozilla::RecursiveMutexAutoUnlock; 36 NS_DECL_THREADSAFE_ISUPPORTS 37 NS_DECL_NSIREQUEST 38 NS_DECL_NSIINPUTSTREAMPUMP 39 NS_DECL_NSIINPUTSTREAMCALLBACK 40 NS_DECL_NSITHREADRETARGETABLEREQUEST 41 NS_INLINE_DECL_STATIC_IID(NS_INPUT_STREAM_PUMP_IID) 42 43 nsInputStreamPump(); 44 45 static nsresult Create(nsInputStreamPump** result, nsIInputStream* stream, 46 uint32_t segsize = 0, uint32_t segcount = 0, 47 bool closeWhenDone = false, 48 nsISerialEventTarget* mainThreadTarget = nullptr); 49 50 using PeekSegmentFun = void (*)(void*, const uint8_t*, uint32_t); 51 /** 52 * Peek into the first chunk of data that's in the stream. Note that this 53 * method will not call the callback when there is no data in the stream. 54 * The callback will be called at most once. 55 * 56 * The data from the stream will not be consumed, i.e. the pump's listener 57 * can still read all the data 58 * 59 * Do not call before asyncRead. Do not call after onStopRequest. 60 */ 61 nsresult PeekStream(PeekSegmentFun callback, void* closure); 62 63 /** 64 * Dispatched (to the main thread) by OnStateStop if it's called off main 65 * thread. Updates mState based on return value of OnStateStop. 66 */ 67 nsresult CallOnStateStop(); 68 69 protected: 70 enum { STATE_IDLE, STATE_START, STATE_TRANSFER, STATE_STOP, STATE_DEAD }; 71 72 nsresult EnsureWaiting(); 73 uint32_t OnStateStart(); 74 uint32_t OnStateTransfer(); 75 uint32_t OnStateStop(); 76 nsresult CreateBufferedStreamIfNeeded() MOZ_REQUIRES(mMutex); 77 78 // This should optimize away in non-DEBUG builds 79 MOZ_ALWAYS_INLINE void AssertOnThread() const MOZ_REQUIRES(mMutex) { 80 if (mOffMainThread) { 81 MOZ_ASSERT(mTargetThread->IsOnCurrentThread()); 82 } else { 83 MOZ_ASSERT(NS_IsMainThread()); 84 } 85 } 86 87 uint32_t mState MOZ_GUARDED_BY(mMutex){STATE_IDLE}; 88 nsCOMPtr<nsILoadGroup> mLoadGroup MOZ_GUARDED_BY(mMutex); 89 // mListener is written on a single thread (either MainThread or an 90 // off-MainThread thread), read from that thread and perhaps others (in 91 // RetargetDeliveryTo) 92 nsCOMPtr<nsIStreamListener> mListener MOZ_GUARDED_BY(mMutex); 93 nsCOMPtr<nsISerialEventTarget> mTargetThread MOZ_GUARDED_BY(mMutex); 94 nsCOMPtr<nsISerialEventTarget> mLabeledMainThreadTarget 95 MOZ_GUARDED_BY(mMutex); 96 nsCOMPtr<nsIInputStream> mStream MOZ_GUARDED_BY(mMutex); 97 // mAsyncStream is written on a single thread (either MainThread or an 98 // off-MainThread thread), and lives from AsyncRead() to OnStateStop(). 99 nsCOMPtr<nsIAsyncInputStream> mAsyncStream MOZ_GUARDED_BY(mMutex); 100 uint64_t mStreamOffset MOZ_GUARDED_BY(mMutex){0}; 101 uint64_t mStreamLength MOZ_GUARDED_BY(mMutex){0}; 102 uint32_t mSegSize MOZ_GUARDED_BY(mMutex){0}; 103 uint32_t mSegCount MOZ_GUARDED_BY(mMutex){0}; 104 nsresult mStatus MOZ_GUARDED_BY(mMutex){NS_OK}; 105 uint32_t mSuspendCount MOZ_GUARDED_BY(mMutex){0}; 106 uint32_t mLoadFlags MOZ_GUARDED_BY(mMutex){LOAD_NORMAL}; 107 bool mIsPending MOZ_GUARDED_BY(mMutex){false}; 108 // True while in OnInputStreamReady, calling OnStateStart, OnStateTransfer 109 // and OnStateStop. Used to prevent calls to AsyncWait during callbacks. 110 bool mProcessingCallbacks MOZ_GUARDED_BY(mMutex){false}; 111 // True if waiting on the "input stream ready" callback. 112 bool mWaitingForInputStreamReady MOZ_GUARDED_BY(mMutex){false}; 113 bool mCloseWhenDone MOZ_GUARDED_BY(mMutex){false}; 114 bool mRetargeting MOZ_GUARDED_BY(mMutex){false}; 115 bool mAsyncStreamIsBuffered MOZ_GUARDED_BY(mMutex){false}; 116 // Indicate whether nsInputStreamPump is used completely off main thread. 117 // If true, OnStateStop() is executed off main thread. Set at creation. 118 const bool mOffMainThread; 119 // Protects state/member var accesses across multiple threads. 120 mozilla::RecursiveMutex mMutex{"nsInputStreamPump"}; 121 }; 122 123 #endif // !nsInputStreamChannel_h__