Added PR_LOG stuff.

This commit is contained in:
warren%netscape.com 1999-06-15 04:57:07 +00:00
parent 847f7d87f9
commit d1a7f6e578
6 changed files with 305 additions and 176 deletions

View File

@ -49,8 +49,7 @@ void XXXNeverCalled()
nsVoidArray();
NS_GetNumberOfAtoms();
nsFileURL(NULL);
// NS_NewPipe(NULL, NULL);
NS_NewPipe2(NULL, NULL, 0, 0);
NS_NewPipe(NULL, NULL, 0, 0, 0, NULL);
nsFileSpec s;
NS_NewIOFileStream(NULL, s, 0, 0);
nsInputFileStream(s, 0, 0);

View File

@ -42,13 +42,15 @@ nsBuffer::nsBuffer()
NS_IMETHODIMP
nsBuffer::Init(PRUint32 growBySize, PRUint32 maxSize,
nsIAllocator* allocator)
nsIBufferObserver* observer, nsIAllocator* allocator)
{
NS_ASSERTION(sizeof(PRCList) <= SEGMENT_OVERHEAD,
"need to change SEGMENT_OVERHEAD size");
NS_ASSERTION(growBySize > SEGMENT_OVERHEAD, "bad growBySize");
mGrowBySize = growBySize;
mMaxSize = maxSize;
mObserver = observer;
NS_IF_ADDREF(mObserver);
mAllocator = allocator;
NS_ADDREF(mAllocator);
return NS_OK;
@ -56,6 +58,7 @@ nsBuffer::Init(PRUint32 growBySize, PRUint32 maxSize,
nsBuffer::~nsBuffer()
{
NS_IF_RELEASE(mObserver);
NS_IF_RELEASE(mAllocator);
}
@ -85,6 +88,10 @@ nsBuffer::PushWriteSegment()
nsAutoMonitor mon(this); // protect mSegments
if (mBufferSize >= mMaxSize) {
if (mObserver) {
nsresult rv = mObserver->OnFull();
if (NS_FAILED(rv)) return rv;
}
return NS_ERROR_FAILURE;
}
@ -135,6 +142,10 @@ nsBuffer::PopReadSegment()
mReadSegment = nsnull;
mReadSegmentEnd = nsnull;
mReadCursor = nsnull;
if (mObserver) {
rv = mObserver->OnEmpty();
if (NS_FAILED(rv)) return rv;
}
}
else {
mReadSegment = mSegments.next;
@ -159,11 +170,11 @@ nsBuffer::ReadSegments(nsWriteSegmentFun writer, void* closure, PRUint32 count,
while (count > 0) {
rv = GetReadSegment(0, &readBuffer, &readBufferLen);
if (rv == NS_BASE_STREAM_EOF) // all we're going to get
return *readCount > 0 ? NS_OK : NS_BASE_STREAM_EOF;
return *readCount == 0 ? rv : NS_OK;
if (NS_FAILED(rv)) return rv;
if (readBufferLen == 0)
return mEOF && *readCount == 0 ? NS_BASE_STREAM_EOF : NS_OK;
return mEOF && (*readCount == 0) ? NS_BASE_STREAM_EOF : NS_OK;
readBufferLen = PR_MIN(readBufferLen, count);
while (readBufferLen > 0) {
@ -172,7 +183,7 @@ nsBuffer::ReadSegments(nsWriteSegmentFun writer, void* closure, PRUint32 count,
if (NS_FAILED(rv)) {
// if we failed to write just report what we were
// able to read so far
return NS_OK;
return (*readCount == 0) ? rv : NS_OK;
}
NS_ASSERTION(writeCount <= readBufferLen, "writer returned bad writeCount");
readBuffer += writeCount;
@ -192,7 +203,7 @@ nsBuffer::ReadSegments(nsWriteSegmentFun writer, void* closure, PRUint32 count,
return NS_OK;
}
NS_METHOD
static NS_METHOD
nsWriteToRawBuffer(void* closure,
const char* fromRawSegment,
PRUint32 offset,
@ -208,39 +219,7 @@ nsWriteToRawBuffer(void* closure,
NS_IMETHODIMP
nsBuffer::Read(char* toBuf, PRUint32 bufLen, PRUint32 *readCount)
{
#if 1
return ReadSegments(nsWriteToRawBuffer, toBuf, bufLen, readCount);
#else
nsresult rv;
PRUint32 readBufferLen;
char* readBuffer;
*readCount = 0;
while (bufLen > 0) {
rv = GetReadSegment(0, &readBuffer, &readBufferLen);
if (rv == NS_BASE_STREAM_EOF) // all we're going to get
return *readCount > 0 ? NS_OK : NS_BASE_STREAM_EOF;
if (NS_FAILED(rv)) return rv;
if (readBufferLen == 0)
return mEOF && *readCount == 0 ? NS_BASE_STREAM_EOF : NS_OK;
PRUint32 count = PR_MIN(bufLen, readBufferLen);
nsCRT::memcpy(toBuf, readBuffer, count);
*readCount += count;
toBuf += count;
bufLen -= count;
if (mReadCursor + count == mReadSegmentEnd) {
rv = PopReadSegment();
if (NS_FAILED(rv)) return rv;
}
else {
mReadCursor += count;
}
}
return NS_OK;
#endif
}
NS_IMETHODIMP
@ -319,6 +298,59 @@ nsBuffer::GetReadSegment(PRUint32 segmentLogicalOffset,
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsBuffer::GetReadableAmount(PRUint32 *result)
{
// first set the read segment and cursor if not already set
if (mReadSegment == nsnull) {
if (PR_CLIST_IS_EMPTY(&mSegments)) {
*result = 0;
return NS_OK;
}
else {
mReadSegment = mSegments.next;
mReadSegmentEnd = (char*)mReadSegment + mGrowBySize;
mReadCursor = (char*)mReadSegment + sizeof(PRCList);
*result = mGrowBySize;
}
}
// now search for the segment starting from segmentLogicalOffset and return it
PRCList* curSeg = mReadSegment;
char* curSegStart = mReadCursor;
char* curSegEnd = mReadSegmentEnd;
PRInt32 amt;
while (PR_TRUE) {
// snapshot the write cursor into a local variable -- this allows
// a writer to freely change it while we're reading while avoiding
// using a lock
char* snapshotWriteCursor = mWriteCursor; // atomic
// next check if the write cursor is in our segment
if (curSegStart <= snapshotWriteCursor &&
snapshotWriteCursor < curSegEnd) {
// same segment -- read up to the snapshotWriteCursor
curSegEnd = snapshotWriteCursor;
amt = curSegEnd - curSegStart;
*result += amt;
return NS_OK;
}
else {
amt = curSegEnd - curSegStart;
*result += amt;
curSeg = PR_NEXT_LINK(curSeg);
if (curSeg == mReadSegment) {
// been all the way around
return NS_OK;
}
curSegEnd = (char*)curSeg + mGrowBySize;
curSegStart = (char*)curSeg + sizeof(PRCList);
}
}
return NS_ERROR_FAILURE;
}
////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
@ -339,7 +371,7 @@ nsBuffer::WriteSegments(nsReadSegmentFun reader, void* closure, PRUint32 count,
// if we failed to allocate a new segment, we're probably out
// of memory, but we don't care -- just report what we were
// able to write so far
return (*writeCount == 0) ? NS_BASE_STREAM_FULL : NS_OK;
return (*writeCount == 0) ? NS_BASE_STREAM_FULL : NS_OK;
}
writeBufLen = PR_MIN(writeBufLen, count);
@ -350,11 +382,11 @@ nsBuffer::WriteSegments(nsReadSegmentFun reader, void* closure, PRUint32 count,
// If the input stream ends, set EOF on the buffer so that
// nsBuffer::Read later notices it.
SetEOF();
return NS_OK;
return (*writeCount == 0) ? rv : NS_OK;
}
else if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
// If no more data is available then return...
return rv;
// If no more data is available then return...
return rv;
}
else if (NS_FAILED(rv)) {
// if we failed to read just report what we were
@ -380,7 +412,7 @@ nsBuffer::WriteSegments(nsReadSegmentFun reader, void* closure, PRUint32 count,
return NS_OK;
}
NS_METHOD
static NS_METHOD
nsReadFromRawBuffer(void* closure,
char* toRawSegment,
PRUint32 offset,
@ -396,45 +428,10 @@ nsReadFromRawBuffer(void* closure,
NS_IMETHODIMP
nsBuffer::Write(const char* fromBuf, PRUint32 bufLen, PRUint32 *writeCount)
{
#if 1
return WriteSegments(nsReadFromRawBuffer, (void*)fromBuf, bufLen, writeCount);
#else
nsresult rv;
if (mEOF)
return NS_BASE_STREAM_EOF;
*writeCount = 0;
while (bufLen > 0) {
PRUint32 writeBufLen;
char* writeBuf;
rv = GetWriteSegment(&writeBuf, &writeBufLen);
if (NS_FAILED(rv)) {
// if we failed to allocate a new segment, we're probably out
// of memory, but we don't care -- just report what we were
// able to write so far
return NS_OK;
}
PRUint32 count = PR_MIN(writeBufLen, bufLen);
nsCRT::memcpy(writeBuf, fromBuf, count);
fromBuf += count;
bufLen -= count;
*writeCount += count;
// set the write cursor after the data is valid
if (mWriteCursor + count == mWriteSegmentEnd) {
mWriteSegment = nsnull; // allocate a new segment next time around
mWriteSegmentEnd = nsnull;
mWriteCursor = nsnull;
}
else
mWriteCursor += count;
}
return NS_OK;
#endif
}
NS_METHOD
static NS_METHOD
nsReadFromInputStream(void* closure,
char* toRawSegment,
PRUint32 offset,
@ -448,52 +445,7 @@ nsReadFromInputStream(void* closure,
NS_IMETHODIMP
nsBuffer::WriteFrom(nsIInputStream* fromStream, PRUint32 count, PRUint32 *writeCount)
{
#if 1
return WriteSegments(nsReadFromInputStream, fromStream, count, writeCount);
#else
nsresult rv;
if (mEOF)
return NS_BASE_STREAM_EOF;
*writeCount = 0;
while (count > 0) {
PRUint32 writeBufLen;
char* writeBuf;
rv = GetWriteSegment(&writeBuf, &writeBufLen);
if (NS_FAILED(rv)) {
// if we failed to allocate a new segment, we're probably out
// of memory, but we don't care -- just report what we were
// able to write so far
return NS_OK;
}
PRUint32 readCount;
rv = fromStream->Read(writeBuf, PR_MIN(writeBufLen, count), &readCount);
if (rv == NS_BASE_STREAM_EOF) {
// If the input stream ends, set EOF on the buffer so that
// nsBuffer::Read later notices it.
SetEOF();
return NS_OK;
}
else if (NS_FAILED(rv)) {
// if we failed to read just report what we were
// able to write so far
return NS_OK;
}
*writeCount += readCount;
count -= readCount;
// set the write cursor after the data is valid
if (mWriteCursor + readCount == mWriteSegmentEnd) {
mWriteSegment = nsnull; // allocate a new segment next time around
mWriteSegmentEnd = nsnull;
mWriteCursor = nsnull;
}
else
mWriteCursor += readCount;
}
return NS_OK;
#endif
}
NS_IMETHODIMP
@ -507,9 +459,6 @@ nsBuffer::GetWriteSegment(char* *resultSegment,
nsresult rv;
if (mWriteSegment == nsnull) {
if (mBufferSize >= mMaxSize)
return NS_ERROR_FAILURE;
rv = PushWriteSegment();
if (NS_FAILED(rv)) return rv;
@ -521,6 +470,17 @@ nsBuffer::GetWriteSegment(char* *resultSegment,
return NS_OK;
}
NS_IMETHODIMP
nsBuffer::GetWritableAmount(PRUint32 *amount)
{
nsresult rv;
PRUint32 readableAmount;
rv = GetReadableAmount(&readableAmount);
if (NS_FAILED(rv)) return rv;
*amount = mMaxSize - readableAmount;
return NS_OK;
}
NS_IMETHODIMP
nsBuffer::SetEOF()
{
@ -616,7 +576,8 @@ static NS_DEFINE_CID(kAllocatorCID, NS_ALLOCATOR_CID);
NS_COM nsresult
NS_NewBuffer(nsIBuffer* *result,
PRUint32 growBySize, PRUint32 maxSize)
PRUint32 growBySize, PRUint32 maxSize,
nsIBufferObserver* observer)
{
nsresult rv;
NS_WITH_SERVICE(nsIAllocator, alloc, kAllocatorCID, &rv);
@ -626,7 +587,7 @@ NS_NewBuffer(nsIBuffer* *result,
rv = nsBuffer::Create(NULL, nsIBuffer::GetIID(), (void**)&buf);
if (NS_FAILED(rv)) return rv;
rv = buf->Init(growBySize, maxSize, alloc);
rv = buf->Init(growBySize, maxSize, observer, alloc);
if (NS_FAILED(rv)) {
NS_RELEASE(buf);
return rv;
@ -640,7 +601,8 @@ static NS_DEFINE_CID(kPageManagerCID, NS_PAGEMANAGER_CID);
NS_COM nsresult
NS_NewPageBuffer(nsIBuffer* *result,
PRUint32 growBySize, PRUint32 maxSize)
PRUint32 growBySize, PRUint32 maxSize,
nsIBufferObserver* observer)
{
nsresult rv;
NS_WITH_SERVICE(nsIAllocator, alloc, kPageManagerCID, &rv);
@ -650,7 +612,7 @@ NS_NewPageBuffer(nsIBuffer* *result,
rv = nsBuffer::Create(NULL, nsIBuffer::GetIID(), (void**)&buf);
if (NS_FAILED(rv)) return rv;
rv = buf->Init(growBySize, maxSize, alloc);
rv = buf->Init(growBySize, maxSize, observer, alloc);
if (NS_FAILED(rv)) {
NS_RELEASE(buf);
return rv;

View File

@ -33,19 +33,21 @@ public:
// nsIBuffer methods:
NS_IMETHOD Init(PRUint32 growBySize, PRUint32 maxSize,
nsIAllocator* allocator);
nsIBufferObserver* observer, nsIAllocator* allocator);
NS_IMETHOD Read(char* toBuf, PRUint32 bufLen, PRUint32 *readCount);
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void* closure, PRUint32 count,
PRUint32 *readCount);
NS_IMETHOD GetReadSegment(PRUint32 segmentLogicalOffset,
const char* *resultSegment,
PRUint32 *resultSegmentLen);
NS_IMETHOD GetReadableAmount(PRUint32 *amount);
NS_IMETHOD Write(const char* fromBuf, PRUint32 bufLen, PRUint32 *writeCount);
NS_IMETHOD WriteFrom(nsIInputStream* fromStream, PRUint32 count, PRUint32 *writeCount);
NS_IMETHOD WriteSegments(nsReadSegmentFun reader, void* closure, PRUint32 count,
PRUint32 *writeCount);
NS_IMETHOD GetWriteSegment(char* *resultSegment,
PRUint32 *resultSegmentLen);
NS_IMETHOD GetWritableAmount(PRUint32 *amount);
NS_IMETHOD SetEOF();
NS_IMETHOD AtEOF(PRBool *result);
NS_IMETHOD Search(const char* forString, PRBool ignoreCase,
@ -62,6 +64,7 @@ protected:
PRUint32 mGrowBySize;
PRUint32 mMaxSize;
nsIAllocator* mAllocator;
nsIBufferObserver* mObserver;
PRCList mSegments;
PRUint32 mBufferSize;

View File

@ -26,6 +26,7 @@ class nsIInputStream;
class nsIAllocator;
class nsIBufferInputStream;
class nsIBufferOutputStream;
class nsIBufferObserver;
#define NS_IBUFFER_IID \
{ /* 1eebb300-fb8b-11d2-9324-00104ba0fd40 */ \
@ -76,7 +77,7 @@ public:
* minus SEGMENT_OVERHEAD bytes.
*/
NS_IMETHOD Init(PRUint32 growBySize, PRUint32 maxSize,
nsIAllocator* allocator) = 0;
nsIBufferObserver* observer, nsIAllocator* allocator) = 0;
/**
* Reads from the read cursor into a char buffer up to a specified length.
@ -103,6 +104,11 @@ public:
const char* *resultSegment,
PRUint32 *resultSegmentLen) = 0;
/**
* Returns the amount of data currently in the buffer available for reading.
*/
NS_IMETHOD GetReadableAmount(PRUint32 *amount) = 0;
/**
* Writes from a char buffer up to a specified length.
* @param writeCount - The amount that could be written. If the buffer becomes full,
@ -133,6 +139,11 @@ public:
NS_IMETHOD GetWriteSegment(char* *resultSegment,
PRUint32 *resultSegmentLen) = 0;
/**
* Returns the amount of space currently in the buffer available for writing.
*/
NS_IMETHOD GetWritableAmount(PRUint32 *amount) = 0;
/**
* Sets an EOF marker (typcially done by the writer) so that a reader can be informed
* when all the data in the buffer is consumed. After the EOF marker has been
@ -160,13 +171,47 @@ public:
PRBool *found, PRUint32 *offsetSearchedTo) = 0;
};
////////////////////////////////////////////////////////////////////////////////
#define NS_IBUFFEROBSERVER_IID \
{ /* 0c18bef0-22a8-11d3-9349-00104ba0fd40 */ \
0x0c18bef0, \
0x22a8, \
0x11d3, \
{0x93, 0x49, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
}
/**
* A buffer observer is used to detect when the buffer becomes completely full
* or completely empty.
*/
class nsIBufferObserver : public nsISupports {
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IBUFFEROBSERVER_IID);
NS_IMETHOD OnFull() = 0;
NS_IMETHOD OnEmpty() = 0;
};
////////////////////////////////////////////////////////////////////////////////
/**
* Creates a new buffer.
* @param observer - may be null
*/
extern NS_COM nsresult
NS_NewBuffer(nsIBuffer* *result,
PRUint32 growBySize, PRUint32 maxSize);
PRUint32 growBySize, PRUint32 maxSize,
nsIBufferObserver* observer);
/**
* Creates a new buffer, allocating segments from virtual memory pages.
*/
extern NS_COM nsresult
NS_NewPageBuffer(nsIBuffer* *result,
PRUint32 growBySize, PRUint32 maxSize);
PRUint32 growBySize, PRUint32 maxSize,
nsIBufferObserver* observer);
extern NS_COM nsresult
NS_NewBufferInputStream(nsIBufferInputStream* *result,
@ -177,8 +222,11 @@ NS_NewBufferOutputStream(nsIBufferOutputStream* *result,
nsIBuffer* buffer, PRBool blocking = PR_FALSE);
extern NS_COM nsresult
NS_NewPipe2(nsIBufferInputStream* *inStrResult,
NS_NewPipe(nsIBufferInputStream* *inStrResult,
nsIBufferOutputStream* *outStrResult,
PRUint32 growBySize, PRUint32 maxSize);
PRUint32 growBySize, PRUint32 maxSize,
PRBool blocking, nsIBufferObserver* observer);
////////////////////////////////////////////////////////////////////////////////
#endif // nsIBuffer_h___

View File

@ -168,16 +168,18 @@ nsBufferInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount)
while (aCount > 0) {
PRUint32 amt;
rv = mBuffer->Read(aBuf, aCount, &amt);
if (rv == NS_BASE_STREAM_EOF)
return *aReadCount > 0 ? NS_OK : rv;
if (NS_FAILED(rv)) return rv;
if (rv == NS_BASE_STREAM_EOF) {
rv = (*aReadCount == 0) ? rv : NS_OK;
break;
}
if (NS_FAILED(rv)) break;
if (amt == 0) {
rv = Fill();
if (NS_FAILED(rv)) return rv;
if (!mBlocking) {
// Only return WOULD_BLOCK if no data was read...
return *aReadCount > 0 ? NS_OK : rv;
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
rv = (*aReadCount == 0) ? rv : NS_OK;
break;
}
if (NS_FAILED(rv)) break;
}
else {
*aReadCount += amt;
@ -185,6 +187,11 @@ nsBufferInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount)
aCount -= amt;
}
}
if (rv == NS_BASE_STREAM_EOF) {
// all we're ever going to get -- so wake up anyone in Flush
nsAutoMonitor mon(mBuffer);
mon.Notify(); // wake up writer
}
return rv;
}
@ -200,21 +207,62 @@ nsBufferInputStream::GetBuffer(nsIBuffer* *result)
}
NS_IMETHODIMP
nsBufferInputStream::Fill(const char* buf, PRUint32 count, PRUint32 *result)
nsBufferInputStream::Fill(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount)
{
if (mBuffer == nsnull)
return NS_BASE_STREAM_CLOSED;
return mBuffer->Write(buf, count, result);
nsresult rv = NS_OK;
*aWriteCount = 0;
while (aCount > 0) {
PRUint32 amt;
rv = mBuffer->Write(aBuf, aCount, &amt);
if (rv == NS_BASE_STREAM_EOF)
return *aWriteCount > 0 ? NS_OK : rv;
if (NS_FAILED(rv)) return rv;
if (amt == 0) {
rv = Fill();
if (rv == NS_BASE_STREAM_WOULD_BLOCK)
return *aWriteCount > 0 ? NS_OK : rv;
if (NS_FAILED(rv)) return rv;
}
else {
aBuf += amt;
aCount -= amt;
*aWriteCount += amt;
}
}
return rv;
}
NS_IMETHODIMP
nsBufferInputStream::FillFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *result)
nsBufferInputStream::FillFrom(nsIInputStream *fromStream, PRUint32 aCount, PRUint32 *aWriteCount)
{
if (mBuffer == nsnull)
return NS_BASE_STREAM_CLOSED;
return mBuffer->WriteFrom(inStr, count, result);
nsresult rv = NS_OK;
*aWriteCount = 0;
while (aCount > 0) {
PRUint32 amt;
rv = mBuffer->WriteFrom(fromStream, aCount, &amt);
if (rv == NS_BASE_STREAM_EOF)
return *aWriteCount > 0 ? NS_OK : rv;
if (NS_FAILED(rv)) return rv;
if (amt == 0) {
rv = Fill();
if (rv == NS_BASE_STREAM_WOULD_BLOCK)
return *aWriteCount > 0 ? NS_OK : rv;
if (NS_FAILED(rv)) return rv;
}
else {
aCount -= amt;
*aWriteCount += amt;
}
}
return rv;
}
nsresult
@ -348,12 +396,18 @@ nsBufferOutputStream::Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteC
while (aCount > 0) {
PRUint32 amt;
rv = mBuffer->Write(aBuf, aCount, &amt);
if (rv == NS_BASE_STREAM_EOF)
return *aWriteCount > 0 ? NS_OK : rv;
if (NS_FAILED(rv)) return rv;
if (rv == NS_BASE_STREAM_EOF) {
rv = (*aWriteCount == 0) ? rv : NS_OK;
break;
}
if (NS_FAILED(rv)) break;
if (amt == 0) {
rv = Flush();
if (NS_FAILED(rv)) return rv;
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
rv = (*aWriteCount == 0) ? rv : NS_OK;
break;
}
if (NS_FAILED(rv)) break;
}
else {
aBuf += amt;
@ -361,6 +415,11 @@ nsBufferOutputStream::Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteC
*aWriteCount += amt;
}
}
if (rv == NS_BASE_STREAM_EOF) {
// all we're ever going to get -- so wake up anyone in Flush
nsAutoMonitor mon(mBuffer);
mon.Notify(); // wake up writer
}
return rv;
}
@ -377,18 +436,29 @@ nsBufferOutputStream::WriteFrom(nsIInputStream* fromStream, PRUint32 aCount,
while (aCount > 0) {
PRUint32 amt;
rv = mBuffer->WriteFrom(fromStream, aCount, &amt);
if (rv == NS_BASE_STREAM_EOF)
return *aWriteCount > 0 ? NS_OK : rv;
if (NS_FAILED(rv)) return rv;
if (rv == NS_BASE_STREAM_EOF) {
rv = (*aWriteCount == 0) ? rv : NS_OK;
break;
}
if (NS_FAILED(rv)) break;
if (amt == 0) {
rv = Flush();
if (NS_FAILED(rv)) return rv;
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
rv = (*aWriteCount == 0) ? rv : NS_OK;
break;
}
if (NS_FAILED(rv)) break;
}
else {
aCount -= amt;
*aWriteCount += amt;
}
}
if (rv == NS_BASE_STREAM_EOF) {
// all we're ever going to get -- so wake up anyone in Flush
nsAutoMonitor mon(mBuffer);
mon.Notify(); // wake up writer
}
return rv;
}
@ -406,10 +476,10 @@ nsBufferOutputStream::Flush(void)
PRUint32 amt;
char* buf;
rv = mBuffer->GetWriteSegment(&buf, &amt);
if (rv == NS_BASE_STREAM_EOF) return rv;
// don't exit on EOF here -- we need to block until the data is consumed
if (NS_SUCCEEDED(rv) && amt > 0) return NS_OK;
// else notify the reader and wait
// else notify the reader and wait
rv = mon.Notify();
if (NS_FAILED(rv)) return rv; // interrupted
rv = mon.Wait();
@ -446,22 +516,23 @@ NS_NewBufferOutputStream(nsIBufferOutputStream* *result,
////////////////////////////////////////////////////////////////////////////////
NS_COM nsresult
NS_NewPipe2(nsIBufferInputStream* *inStrResult,
NS_NewPipe(nsIBufferInputStream* *inStrResult,
nsIBufferOutputStream* *outStrResult,
PRUint32 growBySize, PRUint32 maxSize)
PRUint32 growBySize, PRUint32 maxSize,
PRBool blocking, nsIBufferObserver* observer)
{
nsresult rv;
nsIBufferInputStream* inStr = nsnull;
nsIBufferOutputStream* outStr = nsnull;
nsIBuffer* buf = nsnull;
rv = NS_NewPageBuffer(&buf, growBySize, maxSize);
rv = NS_NewPageBuffer(&buf, growBySize, maxSize, observer);
if (NS_FAILED(rv)) goto error;
rv = NS_NewBufferInputStream(&inStr, buf, PR_TRUE);
rv = NS_NewBufferInputStream(&inStr, buf, blocking);
if (NS_FAILED(rv)) goto error;
rv = NS_NewBufferOutputStream(&outStr, buf, PR_TRUE);
rv = NS_NewBufferOutputStream(&outStr, buf, blocking);
if (NS_FAILED(rv)) goto error;
NS_RELEASE(buf);

View File

@ -18,17 +18,45 @@
#include "nsThread.h"
#include "prmem.h"
//#include <stdio.h>
#include "prlog.h"
PRUintn nsThread::kIThreadSelfIndex = 0;
static nsIThread *gMainThread = 0;
#if defined(PR_LOGGING)
//
// Log module for nsIThread logging...
//
// To enable logging (see prlog.h for full details):
//
// set NSPR_LOG_MODULES=nsIThread:5
// set NSPR_LOG_FILE=nspr.log
//
// this enables PR_LOG_DEBUG level information and places all output in
// the file nspr.log
//
// gSocketLog is defined in nsSocketTransport.cpp
//
PRLogModuleInfo* nsIThreadLog = nsnull;
#endif /* PR_LOGGING */
////////////////////////////////////////////////////////////////////////////////
nsThread::nsThread()
: mThread(nsnull), mRunnable(nsnull), mDead(PR_FALSE)
{
NS_INIT_REFCNT();
#if defined(PR_LOGGING)
//
// Initialize the global PRLogModule for nsIThread logging
// if necessary...
//
if (nsIThreadLog == nsnull) {
nsIThreadLog = PR_NewLogModule("nsIThread");
}
#endif /* PR_LOGGING */
}
nsresult
@ -46,7 +74,8 @@ nsThread::Init(nsIRunnable* runnable,
NS_ADDREF_THIS(); // released in nsThread::Join
mThread = PR_CreateThread(PR_USER_THREAD, Main, this,
priority, scope, state, stackSize);
// printf("%x %x (%d) create\n", this, mThread, mRefCnt);
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThread %p created\n", this));
if (mThread == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
@ -54,7 +83,8 @@ nsThread::Init(nsIRunnable* runnable,
nsThread::~nsThread()
{
// printf("%x %x (%d) destroy\n", this, mThread, mRefCnt);
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThread %p destroyed\n", this));
NS_IF_RELEASE(mRunnable);
}
@ -67,13 +97,15 @@ nsThread::Main(void* arg)
rv = self->RegisterThreadSelf();
NS_ASSERTION(rv == NS_OK, "failed to set thread self");
// printf("%x %x (%d) start run\n", self, self->mThread, self->mRefCnt);
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThread %p start run %p\n", self, self->mRunnable));
rv = self->mRunnable->Run();
NS_ASSERTION(NS_SUCCEEDED(rv), "runnable failed");
PRThreadState state;
rv = self->GetState(&state);
// printf("%x %x (%d) end run\n", self, self->mThread, self->mRefCnt);
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThread %p end run %p\n", self, self->mRunnable));
}
void
@ -82,7 +114,8 @@ nsThread::Exit(void* arg)
nsThread* self = (nsThread*)arg;
nsresult rv = NS_OK;
self->mDead = PR_TRUE;
// printf("%x %x (%d) exit\n", self, self->mThread, self->mRefCnt - 1);
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThread %p exited\n", self));
NS_RELEASE(self);
}
@ -94,11 +127,13 @@ nsThread::Join()
// don't check for mDead here because nspr calls Exit (cleaning up
// thread-local storage) before they let us join with the thread
// printf("%x %x (%d) start join\n", this, mThread, mRefCnt);
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThread %p start join\n", this));
PRStatus status = PR_JoinThread(mThread);
// XXX can't use NS_RELEASE here because the macro wants to set
// this to null (bad c++)
// printf("%x %x (%d) end join\n", this, mThread, mRefCnt);
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThread %p end join\n", this));
if (status == PR_SUCCESS) {
this->Release(); // most likely the final release of this thread
return NS_OK;
@ -368,7 +403,12 @@ nsThreadPool::GetRequest()
rv = NS_ERROR_FAILURE;
break;
}
// printf("thread %x waiting\n", PR_CurrentThread());
#if defined(PR_LOGGING)
nsIThread* th;
nsIThread::GetCurrent(&th);
#endif
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThreadPool thread %p waiting\n", th));
PRStatus status = PR_Wait(mRequestMonitor, PR_INTERVAL_NO_TIMEOUT);
if (status != PR_SUCCESS || mShuttingDown) {
rv = NS_ERROR_FAILURE;
@ -495,17 +535,23 @@ nsThreadPoolRunnable::Run()
PR_CNotify(mPool);
PR_CExitMonitor(mPool);
#if defined(PR_LOGGING)
nsIThread* th;
nsIThread::GetCurrent(&th);
#endif
while ((request = mPool->GetRequest()) != nsnull) {
// printf("running %x, thread %x\n", this, PR_CurrentThread());
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThreadPool thread %p running %p\n", th, this));
rv = request->Run();
NS_ASSERTION(NS_SUCCEEDED(rv), "runnable failed");
// let the thread pool know we're finished a run
// let the thread pool know we've finished a run
PR_CEnterMonitor(mPool);
PR_CNotify(mPool);
PR_CExitMonitor(mPool);
}
// printf("quitting %x, thread %x\n", this, PR_CurrentThread());
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThreadPool thread %p quitting %x\n", th, this));
return rv;
}