mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 551344 part 4 - Address more review comments from sicking in the C++ parts of the HTML5 parser. r=jonas.
--HG-- extra : rebase_source : b15efefa4ba578dead7645770f5ce3fa8becefda
This commit is contained in:
parent
bec27dec6f
commit
5c3712d80a
@ -123,7 +123,10 @@ public:
|
||||
* If the read value does not belong to this character set, one should
|
||||
* replace it with the Unicode special 0xFFFD. When an actual input error is
|
||||
* encountered, like a format error, the converter stop and return error.
|
||||
* Hoever, we should keep in mind that we need to be lax in decoding.
|
||||
* However, we should keep in mind that we need to be lax in decoding. When
|
||||
* a decoding error is returned to the caller, it is the caller's
|
||||
* responsibility to advance over the bad byte and reset the decoder before
|
||||
* trying to call the decoder again.
|
||||
*
|
||||
* Converter required behavior:
|
||||
* In this order: when output space is full - return right away. When input
|
||||
@ -144,7 +147,9 @@ public:
|
||||
* NS_PARTIAL_MORE_OUTPUT if only a partial conversion
|
||||
* was done; more output space is needed to continue
|
||||
* NS_ERROR_ILLEGAL_INPUT if an illegal input sequence
|
||||
* was encountered and the behavior was set to "signal"
|
||||
* was encountered and the behavior was set to "signal";
|
||||
* the caller must skip over one byte, reset the decoder
|
||||
* and retry.
|
||||
*/
|
||||
NS_IMETHOD Convert(const char * aSrc, PRInt32 * aSrcLength,
|
||||
PRUnichar * aDest, PRInt32 * aDestLength) = 0;
|
||||
|
@ -2873,15 +2873,13 @@ pref("accelerometer.enabled", true);
|
||||
pref("html5.enable", false);
|
||||
// Toggle which thread the HTML5 parser uses for stream parsing
|
||||
pref("html5.offmainthread", true);
|
||||
// Time in milliseconds between the start of the network stream and the
|
||||
// first time the flush timer fires in the off-the-main-thread HTML5 parser.
|
||||
pref("html5.flushtimer.startdelay", 200);
|
||||
// Time in milliseconds between the return to non-speculating more and the
|
||||
// first time the flush timer fires thereafter.
|
||||
pref("html5.flushtimer.continuedelay", 150);
|
||||
// Time in milliseconds between timer firings once the timer has starting
|
||||
// firing.
|
||||
pref("html5.flushtimer.interval", 120);
|
||||
// Time in milliseconds between the time a network buffer is seen and the
|
||||
// timer firing when the timer hasn't fired previously in this parse in the
|
||||
// off-the-main-thread HTML5 parser.
|
||||
pref("html5.flushtimer.initialdelay", 200);
|
||||
// Time in milliseconds between the time a network buffer is seen and the
|
||||
// timer firing when the timer has already fired previously in this parse.
|
||||
pref("html5.flushtimer.subsequentdelay", 120);
|
||||
|
||||
// Push/Pop/Replace State prefs
|
||||
pref("browser.history.allowPushState", true);
|
||||
|
@ -304,7 +304,10 @@ class nsHtml5Parser : public nsIParser,
|
||||
void InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState, PRInt32 aLine);
|
||||
|
||||
void DropStreamParser() {
|
||||
mStreamParser = nsnull;
|
||||
if (mStreamParser) {
|
||||
mStreamParser->DropTimer();
|
||||
mStreamParser = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
void StartTokenizer(PRBool aScriptingEnabled);
|
||||
|
@ -54,22 +54,43 @@
|
||||
|
||||
static NS_DEFINE_CID(kCharsetAliasCID, NS_CHARSETALIAS_CID);
|
||||
|
||||
PRInt32 nsHtml5StreamParser::sTimerStartDelay = 200;
|
||||
PRInt32 nsHtml5StreamParser::sTimerContinueDelay = 150;
|
||||
PRInt32 nsHtml5StreamParser::sTimerInterval = 100;
|
||||
PRInt32 nsHtml5StreamParser::sTimerInitialDelay = 200;
|
||||
PRInt32 nsHtml5StreamParser::sTimerSubsequentDelay = 100;
|
||||
|
||||
// static
|
||||
void
|
||||
nsHtml5StreamParser::InitializeStatics()
|
||||
{
|
||||
nsContentUtils::AddIntPrefVarCache("html5.flushtimer.startdelay",
|
||||
&sTimerStartDelay);
|
||||
nsContentUtils::AddIntPrefVarCache("html5.flushtimer.continuedelay",
|
||||
&sTimerContinueDelay);
|
||||
nsContentUtils::AddIntPrefVarCache("html5.flushtimer.interval",
|
||||
&sTimerInterval);
|
||||
nsContentUtils::AddIntPrefVarCache("html5.flushtimer.initialdelay",
|
||||
&sTimerInitialDelay);
|
||||
nsContentUtils::AddIntPrefVarCache("html5.flushtimer.subsequentdelay",
|
||||
&sTimerSubsequentDelay);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that nsHtml5StreamParser implements cycle collecting AddRef and
|
||||
* Release. Therefore, nsHtml5StreamParser must never be refcounted from
|
||||
* the parser thread!
|
||||
*
|
||||
* To work around this limitation, runnables posted by the main thread to the
|
||||
* parser thread hold their reference to the stream parser in an
|
||||
* nsHtml5RefPtr. Upon creation, nsHtml5RefPtr addrefs the object it holds
|
||||
* just like a regular nsRefPtr. This is OK, since the creation of the
|
||||
* runnable and the nsHtml5RefPtr happens on the main thread.
|
||||
*
|
||||
* When the runnable is done on the parser thread, the destructor of
|
||||
* nsHtml5RefPtr runs there. It doesn't call Release on the held object
|
||||
* directly. Instead, it posts another runnable back to the main thread where
|
||||
* that runnable calls Release on the wrapped object.
|
||||
*
|
||||
* When posting runnables in the other direction, the runnables have to be
|
||||
* created on the main thread when nsHtml5StreamParser is instantiated and
|
||||
* held for the lifetime of the nsHtml5StreamParser. This works, because the
|
||||
* same runnabled can be dispatched multiple times and currently runnables
|
||||
* posted from the parser thread to main thread don't need to wrap any
|
||||
* runnable-specific data. (In the other direction, the runnables most notably
|
||||
* wrap the byte data of the stream.)
|
||||
*/
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHtml5StreamParser)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHtml5StreamParser)
|
||||
|
||||
@ -83,10 +104,7 @@ NS_INTERFACE_MAP_END
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsHtml5StreamParser)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHtml5StreamParser)
|
||||
if (tmp->mFlushTimer) {
|
||||
tmp->mFlushTimer->Cancel();
|
||||
tmp->mFlushTimer = nsnull;
|
||||
}
|
||||
tmp->DropTimer();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mObserver)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRequest)
|
||||
tmp->mOwner = nsnull;
|
||||
@ -169,10 +187,11 @@ nsHtml5StreamParser::nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor,
|
||||
, mFlushTimer(do_CreateInstance("@mozilla.org/timer;1"))
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
mFlushTimer->SetTarget(mThread);
|
||||
mAtomTable.Init(); // we aren't checking for OOM anyway...
|
||||
#ifdef DEBUG
|
||||
mAtomTable.SetPermittedLookupThread(mThread);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
mAtomTable.SetPermittedLookupThread(mThread);
|
||||
#endif
|
||||
mTokenizer->setInterner(&mAtomTable);
|
||||
mTokenizer->setEncodingDeclarationHandler(this);
|
||||
|
||||
@ -198,6 +217,8 @@ nsHtml5StreamParser::~nsHtml5StreamParser()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
mTokenizer->end();
|
||||
NS_ASSERTION(!mFlushTimer, "Flush timer was not dropped before dtor!");
|
||||
#ifdef DEBUG
|
||||
mRequest = nsnull;
|
||||
mObserver = nsnull;
|
||||
mUnicodeDecoder = nsnull;
|
||||
@ -208,10 +229,7 @@ nsHtml5StreamParser::~nsHtml5StreamParser()
|
||||
mTreeBuilder = nsnull;
|
||||
mTokenizer = nsnull;
|
||||
mOwner = nsnull;
|
||||
if (mFlushTimer) {
|
||||
mFlushTimer->Cancel();
|
||||
mFlushTimer = nsnull;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -540,11 +558,6 @@ nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
|
||||
*/
|
||||
mExecutor->WillBuildModel(eDTDMode_unknown);
|
||||
|
||||
mFlushTimer->InitWithFuncCallback(nsHtml5StreamParser::TimerCallback,
|
||||
static_cast<void*> (this),
|
||||
sTimerStartDelay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
mReparseForbidden = PR_FALSE;
|
||||
@ -658,6 +671,18 @@ nsHtml5StreamParser::DoDataAvailable(PRUint8* aBuffer, PRUint32 aLength)
|
||||
}
|
||||
|
||||
ParseAvailableData();
|
||||
|
||||
if (mFlushTimerArmed || mSpeculating) {
|
||||
return;
|
||||
}
|
||||
|
||||
mFlushTimer->InitWithFuncCallback(nsHtml5StreamParser::TimerCallback,
|
||||
static_cast<void*> (this),
|
||||
mFlushTimerEverFired ?
|
||||
sTimerInitialDelay :
|
||||
sTimerSubsequentDelay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
mFlushTimerArmed = PR_TRUE;
|
||||
}
|
||||
|
||||
class nsHtml5DataAvailable : public nsRunnable
|
||||
@ -748,16 +773,29 @@ nsHtml5StreamParser::internalEncodingDeclaration(nsString* aEncoding)
|
||||
}
|
||||
|
||||
mTreeBuilder->NeedsCharsetSwitchTo(preferred);
|
||||
mTreeBuilder->Flush();
|
||||
FlushTreeOpsAndDisarmTimer();
|
||||
Interrupt();
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mExecutorFlusher))) {
|
||||
NS_WARNING("failed to dispatch executor flush event");
|
||||
}
|
||||
// the tree op executor will cause the stream parser to terminate
|
||||
// if the charset switch request is accepted or it'll uninterrupt
|
||||
// if the request failed.
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5StreamParser::FlushTreeOpsAndDisarmTimer()
|
||||
{
|
||||
NS_ASSERTION(IsParserThread(), "Wrong thread!");
|
||||
if (mFlushTimerArmed) {
|
||||
// avoid calling Cancel if the flush timer isn't armed to avoid acquiring
|
||||
// a mutex
|
||||
mFlushTimer->Cancel();
|
||||
mFlushTimerArmed = PR_FALSE;
|
||||
}
|
||||
mTreeBuilder->Flush();
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mExecutorFlusher))) {
|
||||
NS_WARNING("failed to dispatch executor flush event");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5StreamParser::ParseAvailableData()
|
||||
{
|
||||
@ -794,10 +832,7 @@ nsHtml5StreamParser::ParseAvailableData()
|
||||
mAtEOF = PR_TRUE;
|
||||
mTokenizer->eof();
|
||||
mTreeBuilder->StreamEnded();
|
||||
mTreeBuilder->Flush();
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mExecutorFlusher))) {
|
||||
NS_WARNING("failed to dispatch executor flush event");
|
||||
}
|
||||
FlushTreeOpsAndDisarmTimer();
|
||||
return; // no more data and not expecting more
|
||||
default:
|
||||
NS_NOTREACHED("It should be impossible to reach this.");
|
||||
@ -826,10 +861,7 @@ nsHtml5StreamParser::ParseAvailableData()
|
||||
mTreeBuilder->newSnapshot());
|
||||
mTreeBuilder->AddSnapshotToScript(speculation->GetSnapshot(),
|
||||
speculation->GetStartLineNumber());
|
||||
mTreeBuilder->Flush();
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mExecutorFlusher))) {
|
||||
NS_WARNING("failed to dispatch executor flush event");
|
||||
}
|
||||
FlushTreeOpsAndDisarmTimer();
|
||||
mTreeBuilder->SetOpSink(speculation);
|
||||
mSpeculations.AppendElement(speculation); // adopts the pointer
|
||||
mSpeculating = PR_TRUE;
|
||||
@ -853,6 +885,7 @@ public:
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
mozilla::MutexAutoLock autoLock(mStreamParser->mTokenizerMutex);
|
||||
mStreamParser->Uninterrupt();
|
||||
mStreamParser->ParseAvailableData();
|
||||
return NS_OK;
|
||||
}
|
||||
@ -943,11 +976,7 @@ nsHtml5StreamParser::ContinueAfterScripts(nsHtml5Tokenizer* aTokenizer,
|
||||
mTreeBuilder->SetOpSink(mExecutor->GetStage());
|
||||
mExecutor->StartReadingFromStage();
|
||||
mSpeculating = PR_FALSE;
|
||||
mFlushTimer->Cancel();
|
||||
mFlushTimer->InitWithFuncCallback(nsHtml5StreamParser::TimerCallback,
|
||||
static_cast<void*> (this),
|
||||
sTimerContinueDelay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
|
||||
// Copy state over
|
||||
mLastWasCR = aLastWasCR;
|
||||
mTokenizer->loadState(aTokenizer);
|
||||
@ -968,17 +997,11 @@ nsHtml5StreamParser::ContinueAfterScripts(nsHtml5Tokenizer* aTokenizer,
|
||||
mTreeBuilder->SetOpSink(mExecutor->GetStage());
|
||||
mExecutor->StartReadingFromStage();
|
||||
mSpeculating = PR_FALSE;
|
||||
mFlushTimer->Cancel();
|
||||
mFlushTimer->InitWithFuncCallback(nsHtml5StreamParser::TimerCallback,
|
||||
static_cast<void*> (this),
|
||||
sTimerContinueDelay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
Uninterrupt();
|
||||
nsCOMPtr<nsIRunnable> event = new nsHtml5StreamParserContinuation(this);
|
||||
if (NS_FAILED(mThread->Dispatch(event, nsIThread::DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Failed to dispatch ParseAvailableData event");
|
||||
NS_WARNING("Failed to dispatch nsHtml5StreamParserContinuation");
|
||||
}
|
||||
// A stream event might run before this event runs, but that's harmless.
|
||||
#ifdef DEBUG
|
||||
@ -991,29 +1014,83 @@ void
|
||||
nsHtml5StreamParser::ContinueAfterFailedCharsetSwitch()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
mozilla::MutexAutoLock tokenizerAutoLock(mTokenizerMutex);
|
||||
Uninterrupt();
|
||||
nsCOMPtr<nsIRunnable> event = new nsHtml5StreamParserContinuation(this);
|
||||
if (NS_FAILED(mThread->Dispatch(event, nsIThread::DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Failed to dispatch nsHtml5StreamParserContinuation");
|
||||
}
|
||||
}
|
||||
|
||||
class nsHtml5TimerKungFu : public nsRunnable
|
||||
{
|
||||
private:
|
||||
nsHtml5RefPtr<nsHtml5StreamParser> mStreamParser;
|
||||
public:
|
||||
nsHtml5TimerKungFu(nsHtml5StreamParser* aStreamParser)
|
||||
: mStreamParser(aStreamParser)
|
||||
{}
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
if (mStreamParser->mFlushTimer) {
|
||||
mStreamParser->mFlushTimer->Cancel();
|
||||
mStreamParser->mFlushTimer = nsnull;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
nsHtml5StreamParser::DropTimer()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
/*
|
||||
* Simply nulling out the timer wouldn't work, because if the timer is
|
||||
* armed, it needs to be canceled first. Simply canceling it first wouldn't
|
||||
* work, because nsTimerImpl::Cancel is not safe for calling from outside
|
||||
* the thread where nsTimerImpl::Fire would run. It's not safe to
|
||||
* dispatch a runnable to cancel the timer from the destructor of this
|
||||
* class, because the timer has a weak (void*) pointer back to this instance
|
||||
* of the stream parser and having the timer fire before the runnable
|
||||
* cancels it would make the timer access a deleted object.
|
||||
*
|
||||
* This DropTimer method addresses these issues. This method must be called
|
||||
* on the main thread before the destructor of this class is reached.
|
||||
* The nsHtml5TimerKungFu object has an nsHtml5RefPtr that addrefs this
|
||||
* stream parser object to keep it alive until the runnable is done.
|
||||
* The runnable cancels the timer on the parser thread, drops the timer
|
||||
* and lets nsHtml5RefPtr send a runnable back to the main thread to
|
||||
* release the stream parser.
|
||||
*/
|
||||
if (mFlushTimer) {
|
||||
nsCOMPtr<nsIRunnable> event = new nsHtml5TimerKungFu(this);
|
||||
if (NS_FAILED(mThread->Dispatch(event, nsIThread::DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Failed to dispatch TimerKungFu event");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Using a static, because the method name Notify is taken by the chardet
|
||||
// callback.
|
||||
void
|
||||
nsHtml5StreamParser::TimerCallback(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
(static_cast<nsHtml5StreamParser*> (aClosure))->PostTimerFlush();
|
||||
(static_cast<nsHtml5StreamParser*> (aClosure))->TimerFlush();
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5StreamParser::TimerFlush()
|
||||
{
|
||||
NS_ASSERTION(IsParserThread(), "Wrong thread!");
|
||||
mTokenizerMutex.AssertCurrentThreadOwns();
|
||||
mozilla::MutexAutoLock autoLock(mTokenizerMutex);
|
||||
|
||||
if (mSpeculating) {
|
||||
NS_ASSERTION(!mSpeculating, "Flush timer fired while speculating.");
|
||||
|
||||
// The timer fired if we got here. No need to cancel it. Mark it as
|
||||
// not armed, though.
|
||||
mFlushTimerArmed = PR_FALSE;
|
||||
|
||||
mFlushTimerEverFired = PR_TRUE;
|
||||
|
||||
if (IsTerminatedOrInterrupted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1031,52 +1108,3 @@ nsHtml5StreamParser::TimerFlush()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class nsHtml5StreamParserTimerFlusher : public nsRunnable
|
||||
{
|
||||
private:
|
||||
nsHtml5RefPtr<nsHtml5StreamParser> mStreamParser;
|
||||
public:
|
||||
nsHtml5StreamParserTimerFlusher(nsHtml5StreamParser* aStreamParser)
|
||||
: mStreamParser(aStreamParser)
|
||||
{}
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
mozilla::MutexAutoLock autoLock(mStreamParser->mTokenizerMutex);
|
||||
mStreamParser->TimerFlush();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
nsHtml5StreamParser::PostTimerFlush()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
mFlushTimer->Cancel();
|
||||
|
||||
// The following line reads a mutex-protected variable without acquiring
|
||||
// the mutex. This is OK, because failure to exit early here is harmless.
|
||||
// The early exit here is merely an optimization. Note that parser thread
|
||||
// may have set mSpeculating to true where it previously was false--not
|
||||
// the other way round. mSpeculating is set to false only on the main thread.
|
||||
if (mSpeculating) {
|
||||
// No need for timer flushes when speculating
|
||||
return;
|
||||
}
|
||||
|
||||
// Schedule the next timer shot
|
||||
mFlushTimer->InitWithFuncCallback(nsHtml5StreamParser::TimerCallback,
|
||||
static_cast<void*> (this),
|
||||
sTimerInterval,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
|
||||
// TODO: (If the document isn't in the frontmost tab or If the user isn't
|
||||
// interacting with the browser) and this isn't every nth timer flush, return
|
||||
|
||||
nsCOMPtr<nsIRunnable> event = new nsHtml5StreamParserTimerFlusher(this);
|
||||
if (NS_FAILED(mThread->Dispatch(event, nsIThread::DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Failed to dispatch nsHtml5StreamParserTimerFlusher");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ class nsHtml5StreamParser : public nsIStreamListener,
|
||||
friend class nsHtml5RequestStopper;
|
||||
friend class nsHtml5DataAvailable;
|
||||
friend class nsHtml5StreamParserContinuation;
|
||||
friend class nsHtml5StreamParserTimerFlusher;
|
||||
friend class nsHtml5TimerKungFu;
|
||||
|
||||
public:
|
||||
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
||||
@ -175,8 +175,7 @@ class nsHtml5StreamParser : public nsIStreamListener,
|
||||
PRBool aLastWasCR);
|
||||
|
||||
/**
|
||||
* Uninterrupts and continues the stream parser if the charset switch
|
||||
* failed.
|
||||
* Continues the stream parser if the charset switch failed.
|
||||
*/
|
||||
void ContinueAfterFailedCharsetSwitch();
|
||||
|
||||
@ -185,6 +184,8 @@ class nsHtml5StreamParser : public nsIStreamListener,
|
||||
mTerminated = PR_TRUE;
|
||||
}
|
||||
|
||||
void DropTimer();
|
||||
|
||||
private:
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -195,19 +196,31 @@ class nsHtml5StreamParser : public nsIStreamListener,
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Marks the stream parser as interrupted. If you ever add calls to this
|
||||
* method, be sure to review Uninterrupt usage very, very carefully to
|
||||
* avoid having a previous in-flight runnable cancel your Interrupt()
|
||||
* call on the other thread too soon.
|
||||
*/
|
||||
void Interrupt() {
|
||||
mozilla::MutexAutoLock autoLock(mTerminatedMutex);
|
||||
mInterrupted = PR_TRUE;
|
||||
}
|
||||
|
||||
void Uninterrupt() {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(IsParserThread(), "Wrong thread!");
|
||||
mTokenizerMutex.AssertCurrentThreadOwns();
|
||||
// Not acquiring mTerminatedMutex because mTokenizerMutex is already
|
||||
// held at this point and is already stronger.
|
||||
mInterrupted = PR_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the tree ops from the tree builder and disarms the flush
|
||||
* timer.
|
||||
*/
|
||||
void FlushTreeOpsAndDisarmTimer();
|
||||
|
||||
void ParseAvailableData();
|
||||
|
||||
void DoStopRequest();
|
||||
@ -311,12 +324,6 @@ class nsHtml5StreamParser : public nsIStreamListener,
|
||||
*/
|
||||
static void TimerCallback(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
/**
|
||||
* Main thread entry point for (maybe) flushing the ops and posting
|
||||
* a flush runnable back on the main thread.
|
||||
*/
|
||||
void PostTimerFlush();
|
||||
|
||||
/**
|
||||
* Parser thread entry point for (maybe) flushing the ops and posting
|
||||
* a flush runnable back on the main thread.
|
||||
@ -466,24 +473,29 @@ class nsHtml5StreamParser : public nsIStreamListener,
|
||||
nsCOMPtr<nsITimer> mFlushTimer;
|
||||
|
||||
/**
|
||||
* The pref html5.flushtimer.startdelay: Time in milliseconds between
|
||||
* the start of the network stream and the first time the flush timer
|
||||
* fires.
|
||||
* Keeps track whether mFlushTimer has been armed. Unfortunately,
|
||||
* nsITimer doesn't enable querying this from the timer itself.
|
||||
*/
|
||||
static PRInt32 sTimerStartDelay;
|
||||
PRBool mFlushTimerArmed;
|
||||
|
||||
/**
|
||||
* The pref html5.flushtimer.continuedelay: Time in milliseconds between
|
||||
* the return to non-speculating more and the first time the flush timer
|
||||
* fires thereafter.
|
||||
* False initially and true after the timer has fired at least once.
|
||||
*/
|
||||
static PRInt32 sTimerContinueDelay;
|
||||
PRBool mFlushTimerEverFired;
|
||||
|
||||
/**
|
||||
* The pref html5.flushtimer.interval: Time in milliseconds between
|
||||
* timer firings once the timer has starting firing.
|
||||
* The pref html5.flushtimer.initialdelay: Time in milliseconds between
|
||||
* the time a network buffer is seen and the timer firing when the
|
||||
* timer hasn't fired previously in this parse.
|
||||
*/
|
||||
static PRInt32 sTimerInterval;
|
||||
static PRInt32 sTimerInitialDelay;
|
||||
|
||||
/**
|
||||
* The pref html5.flushtimer.subsequentdelay: Time in milliseconds between
|
||||
* the time a network buffer is seen and the timer firing when the
|
||||
* timer has already fired previously in this parse.
|
||||
*/
|
||||
static PRInt32 sTimerSubsequentDelay;
|
||||
};
|
||||
|
||||
#endif // nsHtml5StreamParser_h__
|
||||
|
Loading…
Reference in New Issue
Block a user