/* 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/. */
/** * An event used to perform initialization off the main thread.
*/ class AsyncApplyBufferingPolicyEvent final : public Runnable { public: /** * @param aCopier * The nsAsyncStreamCopier requesting the information.
*/ explicit AsyncApplyBufferingPolicyEvent(nsAsyncStreamCopier* aCopier)
: mozilla::Runnable("AsyncApplyBufferingPolicyEvent"),
mCopier(aCopier),
mTarget(GetCurrentSerialEventTarget()) {}
void nsAsyncStreamCopier::OnAsyncCopyComplete(void* closure, nsresult status) { // AddRef'd in AsyncCopy. Will be released at the end of the method.
RefPtr<nsAsyncStreamCopier> self = dont_AddRef((nsAsyncStreamCopier*)closure);
self->Complete(status);
}
/** * Detect whether the input or the output stream is buffered, * bufferize one of them if neither is buffered.
*/
nsresult nsAsyncStreamCopier::ApplyBufferingPolicy() { // This function causes I/O, it must not be executed on the main // thread.
MOZ_ASSERT(!NS_IsMainThread());
if (NS_OutputStreamIsBuffered(mSink)) { // Sink is buffered, no need to perform additional buffering
mMode = NS_ASYNCCOPY_VIA_WRITESEGMENTS; return NS_OK;
} if (NS_InputStreamIsBuffered(mSource)) { // Source is buffered, no need to perform additional buffering
mMode = NS_ASYNCCOPY_VIA_READSEGMENTS; return NS_OK;
}
// No buffering, let's buffer the sink
nsresult rv;
nsCOMPtr<nsIBufferedOutputStream> sink =
do_CreateInstance(NS_BUFFEREDOUTPUTSTREAM_CONTRACTID, &rv); if (NS_FAILED(rv)) { return rv;
}
rv = sink->Init(mSink, mChunkSize); if (NS_FAILED(rv)) { return rv;
}
if (observer) { // build proxy for observer events
rv = NS_NewRequestObserverProxy(getter_AddRefs(mObserver), observer, ctx); if (NS_FAILED(rv)) return rv;
}
// from this point forward, AsyncCopy is going to return NS_OK. any errors // will be reported via OnStopRequest.
{
MutexAutoLock lock(mLock);
mIsPending = true;
}
if (mObserver) {
rv = mObserver->OnStartRequest(AsRequest()); if (NS_FAILED(rv)) Cancel(rv);
}
if (!mShouldSniffBuffering) { // No buffer sniffing required, let's proceed
AsyncCopyInternal(); return NS_OK;
}
if (NS_IsMainThread()) { // Don't perform buffer sniffing on the main thread
nsCOMPtr<nsIRunnable> event = new AsyncApplyBufferingPolicyEvent(this);
rv = mTarget->Dispatch(event, NS_DISPATCH_NORMAL); if (NS_FAILED(rv)) {
Cancel(rv);
} return NS_OK;
}
// We're not going to block the main thread, so let's sniff here
rv = ApplyBufferingPolicy(); if (NS_FAILED(rv)) {
Cancel(rv);
}
AsyncCopyInternal(); return NS_OK;
}
// Launch async copy. // All errors are reported through the observer. void nsAsyncStreamCopier::AsyncCopyInternal() {
MOZ_ASSERT(mMode == NS_ASYNCCOPY_VIA_READSEGMENTS ||
mMode == NS_ASYNCCOPY_VIA_WRITESEGMENTS);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.