From aa4dd41e454bb9245f1feb70f16b12cadebe00a1 Mon Sep 17 00:00:00 2001 From: "darin%meer.net" Date: Thu, 9 Oct 2003 01:54:07 +0000 Subject: [PATCH] fixes bug 193917 "incorporate changes from bz's comments in bug 176919" r+sr=bzbarsky git-svn-id: svn://10.0.0.236/trunk@147780 18797224-902f-48f8-a5cc-f745e15eee43 --- .../base/public/nsIAsyncStreamCopier.idl | 2 +- .../base/public/nsIInputStreamChannel.idl | 3 + .../base/public/nsIInputStreamPump.idl | 14 +++ .../base/public/nsISocketTransport.idl | 28 ++++-- mozilla/netwerk/base/public/nsITransport.idl | 53 ++++++++++ .../netwerk/base/src/nsInputStreamChannel.cpp | 7 ++ .../netwerk/base/src/nsInputStreamPump.cpp | 19 +++- .../netwerk/base/src/nsSocketTransport2.cpp | 22 +++-- .../base/src/nsSocketTransportService2.cpp | 5 + .../cache/public/nsICacheEntryDescriptor.idl | 6 +- .../cache/src/nsCacheEntryDescriptor.cpp | 2 +- .../netwerk/cache/src/nsDiskCacheStreams.cpp | 1 - mozilla/xpcom/io/nsIPipe.idl | 96 +++++++++++++++++++ mozilla/xpcom/io/nsInputStreamTee.cpp | 8 ++ mozilla/xpcom/io/nsPipe3.cpp | 7 +- mozilla/xpcom/tests/TestPipes.cpp | 8 +- mozilla/xpcom/threads/nsEventQueueUtils.h | 8 +- 17 files changed, 249 insertions(+), 40 deletions(-) diff --git a/mozilla/netwerk/base/public/nsIAsyncStreamCopier.idl b/mozilla/netwerk/base/public/nsIAsyncStreamCopier.idl index 5890087a50c..cc8a7cdb401 100644 --- a/mozilla/netwerk/base/public/nsIAsyncStreamCopier.idl +++ b/mozilla/netwerk/base/public/nsIAsyncStreamCopier.idl @@ -81,7 +81,7 @@ interface nsIAsyncStreamCopier : nsIRequest * @param aObserver * receives notifications. * @param aObserverContext - * passed to listener methods. + * passed to observer methods. */ void asyncCopy(in nsIRequestObserver aObserver, in nsISupports aObserverContext); diff --git a/mozilla/netwerk/base/public/nsIInputStreamChannel.idl b/mozilla/netwerk/base/public/nsIInputStreamChannel.idl index 06e94ae7b27..1d726fd9ce8 100644 --- a/mozilla/netwerk/base/public/nsIInputStreamChannel.idl +++ b/mozilla/netwerk/base/public/nsIInputStreamChannel.idl @@ -62,6 +62,9 @@ interface nsIInputStreamChannel : nsIChannel * Otherwise, the stream will be read on a background thread. * * This attribute can only be changed before the channel is opened. + * + * @throws NS_ERROR_IN_PROGRESS if the setter is called after the channel + * has been opened. */ attribute nsIInputStream contentStream; }; diff --git a/mozilla/netwerk/base/public/nsIInputStreamPump.idl b/mozilla/netwerk/base/public/nsIInputStreamPump.idl index f4f83d0a32f..089a500e870 100644 --- a/mozilla/netwerk/base/public/nsIInputStreamPump.idl +++ b/mozilla/netwerk/base/public/nsIInputStreamPump.idl @@ -40,6 +40,20 @@ interface nsIInputStream; interface nsIStreamListener; +/** + * nsIInputStreamPump + * + * This interface provides a means to configure and use a input stream pump + * instance. The input stream pump will asynchronously read from a input + * stream, and push data to a nsIStreamListener instance. It utilizes the + * current thread's nsIEventTarget in order to make reading from the stream + * asynchronous. + * + * If the given stream supports nsIAsyncInputStream, then the stream pump will + * call the stream's AsyncWait method to drive the stream listener. Otherwise, + * the stream will be read on a background thread utilizing the stream + * transport service. More details are provided below. + */ [scriptable, uuid(f7dd8d87-efa7-48cc-9d94-df488df0b3f9)] interface nsIInputStreamPump : nsIRequest { diff --git a/mozilla/netwerk/base/public/nsISocketTransport.idl b/mozilla/netwerk/base/public/nsISocketTransport.idl index 168482197d2..5384cb2beba 100644 --- a/mozilla/netwerk/base/public/nsISocketTransport.idl +++ b/mozilla/netwerk/base/public/nsISocketTransport.idl @@ -40,12 +40,13 @@ interface nsIInterfaceRequestor; interface nsISocketEventSink; -[ptr] native PRNetAddrStar(union PRNetAddr); +native PRNetAddr(union PRNetAddr); /** * nsISocketTransport * - * NOTE: This is a free-threaded interface. + * NOTE: This is a free-threaded interface, meaning that the methods on + * this interface may be called from any thread. */ [scriptable, uuid(1e372001-ca12-4507-8405-3267d4e0c1fd)] interface nsISocketTransport : nsITransport @@ -64,18 +65,18 @@ interface nsISocketTransport : nsITransport * Returns the IP address for the underlying socket connection. This * attribute is only defined once a connection has been established. */ - [noscript] void getAddress(in PRNetAddrStar netAddr); + [noscript] PRNetAddr getAddress(); /** - * Security info object returned from the PSM socket provider. This object - * supports nsISSLSocketControl, nsITransportSecurityInfo, and possibly - * other interfaces. + * Security info object returned from the secure socket provider. This + * object supports nsISSLSocketControl, nsITransportSecurityInfo, and + * possibly other interfaces. */ readonly attribute nsISupports securityInfo; /** - * Security notification callbacks passed to PSM via nsISSLSocketControl at - * socket creation time. + * Security notification callbacks passed to the secure socket provider + * via nsISSLSocketControl at socket creation time. * * NOTE: this attribute cannot be changed once a stream has been opened. */ @@ -94,13 +95,20 @@ interface nsISocketTransport : nsITransport * with existing error codes in Necko, these status codes are confined * within a very limited context where no error codes may appear, so there * is no ambiguity. + * + * The values of these status codes must never change. + * + * The status codes appear in near-chronological order (not in numeric + * order). STATUS_RESOLVING may be skipped if the host does not need to be + * resolved. STATUS_WAITING_FOR is an optional status code, which the impl + * of this interface may choose not to generate. */ const unsigned long STATUS_RESOLVING = 0x804b0003; + const unsigned long STATUS_CONNECTING_TO = 0x804b0007; const unsigned long STATUS_CONNECTED_TO = 0x804b0004; const unsigned long STATUS_SENDING_TO = 0x804b0005; - const unsigned long STATUS_RECEIVING_FROM = 0x804b0006; - const unsigned long STATUS_CONNECTING_TO = 0x804b0007; const unsigned long STATUS_WAITING_FOR = 0x804b000a; + const unsigned long STATUS_RECEIVING_FROM = 0x804b0006; }; %{C++ diff --git a/mozilla/netwerk/base/public/nsITransport.idl b/mozilla/netwerk/base/public/nsITransport.idl index c14c9a176a2..24bba22e4df 100644 --- a/mozilla/netwerk/base/public/nsITransport.idl +++ b/mozilla/netwerk/base/public/nsITransport.idl @@ -42,6 +42,21 @@ interface nsIOutputStream; interface nsITransportEventSink; interface nsIEventTarget; +/** + * nsITransport + * + * This interface provides a common way of accessing i/o streams connected + * to some resource. This interface does not in any way specify the resource. + * It provides methods to open blocking or non-blocking, buffered or unbuffered + * streams to the resource. The name "transport" is meant to connote the + * inherent data transfer implied by this interface (i.e., data is being + * transfered in some fashion via the streams exposed by this interface). + * + * A transport can have an event sink associated with it. The event sink + * receives transport-specific events as the transfer is occuring. For a + * socket transport, these events can include status about the connection. + * See nsISocketTransport for more info about socket transport specifics. + */ [scriptable, uuid(cbb0baeb-5fcb-408b-a2be-9f8fc98d0af1)] interface nsITransport : nsISupports { @@ -54,6 +69,25 @@ interface nsITransport : nsISupports /** * Open an input stream on this transport. * + * Flags have the following meaning: + * + * OPEN_BLOCKING + * If specified, then the resulting stream will have blocking stream + * semantics. This means that if the stream has no data and is not + * closed, then reading from it will block the calling thread until + * at least one byte is available or until the stream is closed. + * If this flag is NOT specified, then the stream has non-blocking + * stream semantics. This means that if the stream has no data and is + * not closed, then reading from it returns NS_BASE_STREAM_WOULD_BLOCK. + * In addition, in non-blocking mode, the stream is guaranteed to + * support nsIAsyncInputStream. This interface allows the consumer of + * the stream to be notified when the stream can again be read. + * + * OPEN_UNBUFFERED + * If specified, the resulting stream may not support ReadSegments. + * ReadSegments is only gauranteed to be implemented when this flag is + * NOT specified. + * * @param aFlags * optional transport specific flags. * @param aSegmentSize @@ -70,6 +104,25 @@ interface nsITransport : nsISupports /** * Open an output stream on this transport. * + * Flags have the following meaning: + * + * OPEN_BLOCKING + * If specified, then the resulting stream will have blocking stream + * semantics. This means that if the stream is full and is not closed, + * then writing to it will block the calling thread until ALL of the + * data can be written or until the stream is closed. If this flag is + * NOT specified, then the stream has non-blocking stream semantics. + * This means that if the stream is full and is not closed, then writing + * to it returns NS_BASE_STREAM_WOULD_BLOCK. In addition, in non- + * blocking mode, the stream is guaranteed to support + * nsIAsyncOutputStream. This interface allows the consumer of the + * stream to be notified when the stream can again accept more data. + * + * OPEN_UNBUFFERED + * If specified, the resulting stream may not support WriteSegments and + * WriteFrom. WriteSegments and WriteFrom are only gauranteed to be + * implemented when this flag is NOT specified. + * * @param aFlags * optional transport specific flags. * @param aSegmentSize diff --git a/mozilla/netwerk/base/src/nsInputStreamChannel.cpp b/mozilla/netwerk/base/src/nsInputStreamChannel.cpp index ea743e70541..88e139a2994 100644 --- a/mozilla/netwerk/base/src/nsInputStreamChannel.cpp +++ b/mozilla/netwerk/base/src/nsInputStreamChannel.cpp @@ -283,6 +283,8 @@ nsInputStreamChannel::Open(nsIInputStream **result) NS_ENSURE_TRUE(mContentStream, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(!mPump, NS_ERROR_IN_PROGRESS); + // XXX this won't work if mContentStream is non-blocking. + NS_ADDREF(*result = mContentStream); return NS_OK; } @@ -293,6 +295,11 @@ nsInputStreamChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) NS_ENSURE_TRUE(mContentStream, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(!mPump, NS_ERROR_IN_PROGRESS); + // if content length is unknown, then we must guess... in this case, we + // assume the stream can tell us. if the stream is a pipe, then this will + // not work. in that case, we hope that the user of this interface would + // have set our content length to PR_UINT32_MAX to cause us to read until + // end of stream. if (mContentLength == -1) mContentStream->Available((PRUint32 *) &mContentLength); diff --git a/mozilla/netwerk/base/src/nsInputStreamPump.cpp b/mozilla/netwerk/base/src/nsInputStreamPump.cpp index 3c35d3004d7..8e806c080ed 100644 --- a/mozilla/netwerk/base/src/nsInputStreamPump.cpp +++ b/mozilla/netwerk/base/src/nsInputStreamPump.cpp @@ -64,7 +64,7 @@ static PRLogModuleInfo *gStreamPumpLog = nsnull; nsInputStreamPump::nsInputStreamPump() : mState(STATE_IDLE) , mStreamOffset(0) - , mStreamLength(~0U) + , mStreamLength(PR_UINT32_MAX) , mStatus(NS_OK) , mSuspendCount(0) , mLoadFlags(LOAD_NORMAL) @@ -84,6 +84,9 @@ nsInputStreamPump::~nsInputStreamPump() nsresult nsInputStreamPump::EnsureWaiting() { + // no need to worry about multiple threads... an input stream pump lives + // on only one thread. + if (!mWaiting) { nsresult rv = mAsyncStream->AsyncWait(this, 0, 0, mEventQ); if (NS_FAILED(rv)) { @@ -244,8 +247,20 @@ nsInputStreamPump::AsyncRead(nsIStreamListener *listener, nsISupports *ctxt) rv = mStream->IsNonBlocking(&nonBlocking); if (NS_FAILED(rv)) return rv; - if (nonBlocking) + if (nonBlocking) { mAsyncStream = do_QueryInterface(mStream); + // + // if the stream supports nsIAsyncInputStream, and if we need to seek + // to a starting offset, then we must do so here. in the non-async + // stream case, the stream transport service will take care of seeking + // for us. + // + if (mAsyncStream && (mStreamOffset != PR_UINT32_MAX)) { + nsCOMPtr seekable = do_QueryInterface(mStream); + if (seekable) + seekable->Seek(nsISeekableStream::NS_SEEK_SET, mStreamOffset); + } + } if (!mAsyncStream) { // ok, let's use the stream transport service to read this stream. diff --git a/mozilla/netwerk/base/src/nsSocketTransport2.cpp b/mozilla/netwerk/base/src/nsSocketTransport2.cpp index 4cb6cd4ed6c..abc904d393b 100644 --- a/mozilla/netwerk/base/src/nsSocketTransport2.cpp +++ b/mozilla/netwerk/base/src/nsSocketTransport2.cpp @@ -119,7 +119,7 @@ static PRErrorCode RandomizeConnectError(PRErrorCode code) { // // To test out these errors, load http://www.yahoo.com/. It should load - // correctly despite the random occurance of there errors. + // correctly despite the random occurance of these errors. // int n = rand(); if (n > RAND_MAX/2) { @@ -209,6 +209,8 @@ nsSocketInputStream::OnSocketReady(nsresult condition) LOG(("nsSocketInputStream::OnSocketReady [this=%x cond=%x]\n", this, condition)); + NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); + nsCOMPtr callback; { nsAutoLock lock(mTransport->mLock); @@ -450,6 +452,8 @@ nsSocketOutputStream::OnSocketReady(nsresult condition) LOG(("nsSocketOutputStream::OnSocketReady [this=%x cond=%x]\n", this, condition)); + NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); + nsCOMPtr callback; { nsAutoLock lock(mTransport->mLock); @@ -683,7 +687,7 @@ nsSocketTransport::~nsSocketTransport() PRUint32 i; for (i=0; iOnTransportStatus(this, status, progress, ~0U); + sink->OnTransportStatus(this, status, progress, PR_UINT32_MAX); } nsresult @@ -1133,8 +1137,10 @@ nsSocketTransport::OnMsgInputClosed(nsresult reason) LOG(("nsSocketTransport::OnMsgInputClosed [this=%x reason=%x]\n", this, reason)); + NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); + mInputClosed = PR_TRUE; - // check if event should effect entire transport + // check if event should affect entire transport if (NS_FAILED(reason) && (reason != NS_BASE_STREAM_CLOSED)) mCondition = reason; // XXX except if NS_FAILED(mCondition), right?? else if (mOutputClosed) @@ -1153,8 +1159,10 @@ nsSocketTransport::OnMsgOutputClosed(nsresult reason) LOG(("nsSocketTransport::OnMsgOutputClosed [this=%x reason=%x]\n", this, reason)); + NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); + mOutputClosed = PR_TRUE; - // check if event should effect entire transport + // check if event should affect entire transport if (NS_FAILED(reason) && (reason != NS_BASE_STREAM_CLOSED)) mCondition = reason; // XXX except if NS_FAILED(mCondition), right?? else if (mInputClosed) @@ -1372,6 +1380,8 @@ nsSocketTransport::OnSocketDetached(PRFileDesc *fd) LOG(("nsSocketTransport::OnSocketDetached [this=%x cond=%x]\n", this, mCondition)); + NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); + // if we didn't initiate this detach, then be sure to pass an error // condition up to our consumers. (e.g., STS is shutting down.) if (NS_SUCCEEDED(mCondition)) diff --git a/mozilla/netwerk/base/src/nsSocketTransportService2.cpp b/mozilla/netwerk/base/src/nsSocketTransportService2.cpp index 99bb84653fe..ba615aa5888 100644 --- a/mozilla/netwerk/base/src/nsSocketTransportService2.cpp +++ b/mozilla/netwerk/base/src/nsSocketTransportService2.cpp @@ -92,6 +92,7 @@ nsSocketTransportService::nsSocketTransportService() PR_INIT_CLIST(&mEventQ); PR_INIT_CLIST(&mPendingSocketQ); + NS_ASSERTION(!gSocketTransportService, "must not instantiate twice"); gSocketTransportService = this; } @@ -145,6 +146,8 @@ nsSocketTransportService::NotifyWhenCanAttachSocket(PLEvent *event) { LOG(("nsSocketTransportService::NotifyWhenCanAttachSocket\n")); + NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); + if (CanAttachSocket()) { NS_WARNING("should have called CanAttachSocket"); return PostEvent(event); @@ -159,6 +162,8 @@ nsSocketTransportService::AttachSocket(PRFileDesc *fd, nsASocketHandler *handler { LOG(("nsSocketTransportService::AttachSocket [handler=%x]\n", handler)); + NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); + SocketContext sock; sock.mFD = fd; sock.mHandler = handler; diff --git a/mozilla/netwerk/cache/public/nsICacheEntryDescriptor.idl b/mozilla/netwerk/cache/public/nsICacheEntryDescriptor.idl index 8254aba3515..e2357ea0009 100644 --- a/mozilla/netwerk/cache/public/nsICacheEntryDescriptor.idl +++ b/mozilla/netwerk/cache/public/nsICacheEntryDescriptor.idl @@ -57,7 +57,8 @@ interface nsICacheEntryDescriptor : nsICacheEntryInfo * stream MAY implement nsISeekableStream. * * @param offset - * read starting from this offset into the cached data. + * read starting from this offset into the cached data. an offset + * beyond the end of the stream has undefined consequences. * * @return blocking, unbuffered input stream. */ @@ -73,7 +74,8 @@ interface nsICacheEntryDescriptor : nsICacheEntryInfo * truncated to the specified offset. * * @param offset - * write starting from this offset into the cached data. + * write starting from this offset into the cached data. an offset + * beyond the end of the stream has undefined consequences. * * @return blocking, unbuffered output stream. */ diff --git a/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.cpp b/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.cpp index 6788ab1ff17..f69ed613e3d 100644 --- a/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.cpp +++ b/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.cpp @@ -589,7 +589,7 @@ nsOutputStreamWrapper::LazyInit() nsresult nsCacheEntryDescriptor:: nsOutputStreamWrapper::OnWrite(PRUint32 count) { - if (count > 0x7FFFFFFF) return NS_ERROR_UNEXPECTED; + if (count > PR_INT32_MAX) return NS_ERROR_UNEXPECTED; return mDescriptor->RequestDataSizeChange((PRInt32)count); } diff --git a/mozilla/netwerk/cache/src/nsDiskCacheStreams.cpp b/mozilla/netwerk/cache/src/nsDiskCacheStreams.cpp index da05d72fe67..630b515680d 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheStreams.cpp +++ b/mozilla/netwerk/cache/src/nsDiskCacheStreams.cpp @@ -746,7 +746,6 @@ nsresult nsDiskCacheStreamIO::Seek(PRInt32 whence, PRInt32 offset) { PRInt32 newPos; - //nsAutoLock lock(nsCacheService::ServiceLock()); // grab service lock if (!mBinding) return NS_ERROR_NOT_AVAILABLE; if (PRUint32(offset) > mStreamEnd) return NS_ERROR_FAILURE; diff --git a/mozilla/xpcom/io/nsIPipe.idl b/mozilla/xpcom/io/nsIPipe.idl index 8fa0902b701..8e269352a83 100644 --- a/mozilla/xpcom/io/nsIPipe.idl +++ b/mozilla/xpcom/io/nsIPipe.idl @@ -40,6 +40,34 @@ interface nsIMemory; +/** + * nsIPipe represents an in-process buffer that can be read using nsIInputStream + * and written using nsIOutputStream. The reader and writer of a pipe do not + * have to be on the same thread. As a result, the pipe is an ideal mechanism + * to bridge data exchange between two threads. For example, a worker thread + * might write data to a pipe from which the main thread will read. + * + * Each end of the pipe can be either blocking or non-blocking. Recall that a + * non-blocking stream will return NS_BASE_STREAM_WOULD_BLOCK if it cannot be + * read or written to without blocking the calling thread. For example, if you + * try to read from an empty pipe that has not yet been closed, then if that + * pipe's input end is non-blocking, then the read call will fail immediately + * with NS_BASE_STREAM_WOULD_BLOCK as the error condition. However, if that + * pipe's input end is blocking, then the read call will not return until the + * pipe has data or until the pipe is closed. This example presumes that the + * pipe is being filled asynchronously on some background thread. + * + * The pipe supports nsIAsyncInputStream and nsIAsyncOutputStream, which give + * the user of a non-blocking pipe the ability to wait for the pipe to become + * ready again. For example, in the case of an empty non-blocking pipe, the + * user can call AsyncWait on the input end of the pipe to be notified when + * the pipe has data to read (or when the pipe becomes closed). + * + * NS_NewPipe2 and NS_NewPipe provide convenient pipe constructors. In most + * cases nsIPipe is not actually used. It is usually enough to just get + * references to the pipe's input and output end. In which case, the pipe is + * automatically closed when the respective pipe ends are released. + */ [scriptable, uuid(f4211abc-61b3-11d4-9877-00c04fa0cf4a)] interface nsIPipe : nsISupports { @@ -52,10 +80,21 @@ interface nsIPipe : nsISupports in unsigned long segmentCount, in nsIMemory segmentAllocator); + /** + * The pipe's input end, which also implements nsISearchableInputStream. + */ readonly attribute nsIAsyncInputStream inputStream; + + /** + * The pipe's output end. + */ readonly attribute nsIAsyncOutputStream outputStream; }; +/** + * XXX this interface doesn't really belong in here. It is here because + * currently nsPipeInputStream is the only implementation of this interface. + */ [scriptable, uuid(8C39EF62-F7C9-11d4-98F5-001083010E9B)] interface nsISearchableInputStream : nsISupports { @@ -77,6 +116,35 @@ interface nsISearchableInputStream : nsISupports %{C++ +/** + * NS_NewPipe2 + * + * This function supercedes NS_NewPipe. It differs from NS_NewPipe in two + * major ways: + * (1) returns nsIAsyncInputStream and nsIAsyncOutputStream, so it is + * not necessary to QI in order to access these interfaces. + * (2) the size of the pipe is determined by the number of segments + * times the size of each segment. + * + * @param pipeIn + * resulting input end of the pipe + * @param pipeOut + * resulting output end of the pipe + * @param nonBlockingInput + * true specifies non-blocking input stream behavior + * @param nonBlockingOutput + * true specifies non-blocking output stream behavior + * @param segmentSize + * specifies the segment size in bytes (pass 0 to use default value) + * @param segmentCount + * specifies the max number of segments (pass 0 to use default value) + * passing PR_UINT32_MAX here causes the pipe to have "infinite" space. + * this mode can be useful in some cases, but should always be used with + * caution. the default value for this parameter is a finite value. + * @param segmentAlloc + * pass reference to nsIMemory to have all pipe allocations use this + * allocator (pass null to use the default allocator) + */ extern NS_COM nsresult NS_NewPipe2(nsIAsyncInputStream **pipeIn, nsIAsyncOutputStream **pipeOut, @@ -86,6 +154,34 @@ NS_NewPipe2(nsIAsyncInputStream **pipeIn, PRUint32 segmentCount = 0, nsIMemory *segmentAlloc = nsnull); +/** + * NS_NewPipe + * + * Preserved for backwards compatibility. Plus, this interface is more + * amiable in certain contexts (e.g., when you don't need the pipe's async + * capabilities). + * + * @param pipeIn + * resulting input end of the pipe + * @param pipeOut + * resulting output end of the pipe + * @param segmentSize + * specifies the segment size in bytes (pass 0 to use default value) + * @param maxSize + * specifies the max size of the pipe (pass 0 to use default value) + * number of segments is maxSize / segmentSize, and maxSize must be a + * multiple of segmentSize. passing PR_UINT32_MAX here causes the + * pipe to have "infinite" space. this mode can be useful in some + * cases, but should always be used with caution. the default value + * for this parameter is a finite value. + * @param nonBlockingInput + * true specifies non-blocking input stream behavior + * @param nonBlockingOutput + * true specifies non-blocking output stream behavior + * @param segmentAlloc + * pass reference to nsIMemory to have all pipe allocations use this + * allocator (pass null to use the default allocator) + */ inline nsresult NS_NewPipe(nsIInputStream **pipeIn, nsIOutputStream **pipeOut, diff --git a/mozilla/xpcom/io/nsInputStreamTee.cpp b/mozilla/xpcom/io/nsInputStreamTee.cpp index 005198443ae..8841237f9b9 100644 --- a/mozilla/xpcom/io/nsInputStreamTee.cpp +++ b/mozilla/xpcom/io/nsInputStreamTee.cpp @@ -183,6 +183,14 @@ nsInputStreamTee::GetSource(nsIInputStream **source) NS_IMETHODIMP nsInputStreamTee::SetSink(nsIOutputStream *sink) { +#ifdef DEBUG + if (sink) { + PRBool nonBlocking; + nsresult rv = sink->IsNonBlocking(&nonBlocking); + if (NS_FAILED(rv) || nonBlocking) + NS_ERROR("sink should be a blocking stream"); + } +#endif mSink = sink; return NS_OK; } diff --git a/mozilla/xpcom/io/nsPipe3.cpp b/mozilla/xpcom/io/nsPipe3.cpp index 94db7765bc3..98a5d046f61 100644 --- a/mozilla/xpcom/io/nsPipe3.cpp +++ b/mozilla/xpcom/io/nsPipe3.cpp @@ -319,7 +319,6 @@ nsPipe::nsPipe() , mWriteLimit(nsnull) , mStatus(NS_OK) { - NS_INIT_ISUPPORTS(); } nsPipe::~nsPipe() @@ -760,7 +759,7 @@ nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer, rv = writer(this, closure, segment, *readCount, segmentLen, &writeCount); - if (NS_FAILED(rv) || (writeCount == 0)) { + if (NS_FAILED(rv) || writeCount == 0) { count = 0; // any errors returned from the writer end here: do not // propogate to the caller of ReadSegments. @@ -768,6 +767,7 @@ nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer, break; } + NS_ASSERTION(writeCount <= segmentLen, "wrote more than expected"); segment += writeCount; segmentLen -= writeCount; count -= writeCount; @@ -1095,7 +1095,7 @@ nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader, rv = reader(this, closure, segment, *writeCount, segmentLen, &readCount); - if (NS_FAILED(rv) || (readCount == 0)) { + if (NS_FAILED(rv) || readCount == 0) { count = 0; // any errors returned from the reader end here: do not // propogate to the caller of WriteSegments. @@ -1103,6 +1103,7 @@ nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader, break; } + NS_ASSERTION(readCount <= segmentLen, "read more than expected"); segment += readCount; segmentLen -= readCount; count -= readCount; diff --git a/mozilla/xpcom/tests/TestPipes.cpp b/mozilla/xpcom/tests/TestPipes.cpp index cb8ff64f0e5..e43b5de64d4 100644 --- a/mozilla/xpcom/tests/TestPipes.cpp +++ b/mozilla/xpcom/tests/TestPipes.cpp @@ -401,9 +401,7 @@ TestPipeObserver() //////////////////////////////////////////////////////////////////////////////// -class nsPump : /*public nsIInputStreamObserver, - public nsIOutputStreamObserver,*/ - public nsIRunnable +class nsPump : public nsIRunnable { public: NS_DECL_ISUPPORTS @@ -489,14 +487,12 @@ TestChainedPipes() len = len * rand() / RAND_MAX; len = PR_MAX(1, len); rv = WriteAll(out1, buf, len, &writeCount); - //rv = out1->Write(buf, len, &writeCount); if (NS_FAILED(rv)) return rv; NS_ASSERTION(writeCount == len, "didn't write enough"); total += writeCount; if (gTrace) printf("wrote %d bytes: %s\n", writeCount, buf); - //out1->Flush(); // wakes up the pump PR_smprintf_free(buf); } @@ -638,8 +634,6 @@ main(int argc, char* argv[]) TestSearch("baz", 2); #endif - //rv = TestPipeObserver(); - //NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipeObserver failed"); rv = TestChainedPipes(); NS_ASSERTION(NS_SUCCEEDED(rv), "TestChainedPipes failed"); RunTests(16, 1); diff --git a/mozilla/xpcom/threads/nsEventQueueUtils.h b/mozilla/xpcom/threads/nsEventQueueUtils.h index f4a0eb2c04e..5df2e406f23 100644 --- a/mozilla/xpcom/threads/nsEventQueueUtils.h +++ b/mozilla/xpcom/threads/nsEventQueueUtils.h @@ -45,14 +45,8 @@ inline nsresult NS_GetEventQueueService(nsIEventQueueService **result) { - nsresult rv; - static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); - nsCOMPtr eqs = do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - NS_ADDREF(*result = eqs); - return NS_OK; + return CallGetService(kEventQueueServiceCID, result); } inline nsresult