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
This commit is contained in:
darin%meer.net
2003-10-09 01:54:07 +00:00
parent 49e6d5cfc2
commit aa4dd41e45
17 changed files with 249 additions and 40 deletions

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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;