mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 848954 - Part 7 - Get rid of the stack allocated message queue. r=roc
In the next patches, when the AudioDriver will be implemented, the audio backend thread (that we don't control), will return from the stack frame where the nsTArray that allows the MSG thread to exchange message queues in a efficient manner with the main thread. We put it in the MediaStreamGraph to avoid adding an allocation/deallocation per iteration on the MSG thread. In addition, the graph will be able to run on different threads during its lifetime, so we can't guarantee a stable stack frame to allocate things on anymore. The array are renamed with meaningful names, explaining the double-buffering pattern: the back queue is filled by the main thread, and is swapped with the front queue that is processed by the MSG thread. Arrays accesses are synchronized using the driver's monitor.
This commit is contained in:
parent
02b493fd95
commit
06aec8f087
@ -28,14 +28,14 @@ struct AutoProfilerUnregisterThread
|
||||
};
|
||||
|
||||
GraphDriver::GraphDriver(MediaStreamGraphImpl* aGraphImpl)
|
||||
: mIterationStart(INITIAL_CURRENT_TIME),
|
||||
mIterationEnd(INITIAL_CURRENT_TIME),
|
||||
mStateComputedTime(INITIAL_CURRENT_TIME),
|
||||
mGraphImpl(aGraphImpl),
|
||||
mWaitState(WAITSTATE_RUNNING),
|
||||
mNeedAnotherIteration(false),
|
||||
mMonitor("MediaStreamGraphMonitor")
|
||||
{ }
|
||||
: mIterationStart(INITIAL_CURRENT_TIME),
|
||||
mIterationEnd(INITIAL_CURRENT_TIME),
|
||||
mStateComputedTime(INITIAL_CURRENT_TIME),
|
||||
mGraphImpl(aGraphImpl),
|
||||
mWaitState(WAITSTATE_RUNNING),
|
||||
mNeedAnotherIteration(false),
|
||||
mMonitor("MediaStreamGraphMonitor")
|
||||
{ }
|
||||
|
||||
DriverHolder::DriverHolder(MediaStreamGraphImpl* aGraphImpl)
|
||||
: mGraphImpl(aGraphImpl),
|
||||
@ -75,6 +75,10 @@ public:
|
||||
{
|
||||
char aLocal;
|
||||
profiler_register_thread("MediaStreamGraph", &aLocal);
|
||||
{
|
||||
MonitorAutoLock mon(mDriver->GetThreadMonitor());
|
||||
mDriver->mGraphImpl->SwapMessageQueues();
|
||||
}
|
||||
mDriver->RunThread();
|
||||
return NS_OK;
|
||||
}
|
||||
@ -122,13 +126,6 @@ void
|
||||
ThreadedDriver::RunThread()
|
||||
{
|
||||
AutoProfilerUnregisterThread autoUnregister;
|
||||
nsTArray<MessageBlock> messageQueue;
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
messageQueue.SwapElements(mGraphImpl->MessageQueue());
|
||||
}
|
||||
NS_ASSERTION(!messageQueue.IsEmpty(),
|
||||
"Shouldn't have started a graph with empty message queue!");
|
||||
|
||||
bool stillProcessing = true;
|
||||
while (stillProcessing) {
|
||||
@ -142,8 +139,7 @@ ThreadedDriver::RunThread()
|
||||
stillProcessing = mGraphImpl->OneIteration(prevCurrentTime,
|
||||
nextCurrentTime,
|
||||
StateComputedTime(),
|
||||
nextStateComputedTime,
|
||||
messageQueue);
|
||||
nextStateComputedTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,8 @@ protected:
|
||||
GraphTime mLastSwitchOffset;
|
||||
};
|
||||
|
||||
class MediaStreamGraphInitThreadRunnable;
|
||||
|
||||
/**
|
||||
* This class is a driver that manages its own thread.
|
||||
*/
|
||||
@ -216,6 +218,7 @@ public:
|
||||
virtual void Stop() MOZ_OVERRIDE;
|
||||
virtual void Dispatch(nsIRunnable* aEvent) MOZ_OVERRIDE;
|
||||
void RunThread();
|
||||
friend MediaStreamGraphInitThreadRunnable;
|
||||
private:
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
};
|
||||
|
@ -1260,21 +1260,20 @@ MediaStreamGraphImpl::ResumeAllAudioOutputs()
|
||||
}
|
||||
|
||||
void
|
||||
MediaStreamGraphImpl::UpdateGraph(nsTArray<MessageBlock>& aMessageQueue,
|
||||
GraphTime aEndBlockingDecision)
|
||||
MediaStreamGraphImpl::UpdateGraph(GraphTime aEndBlockingDecision)
|
||||
{
|
||||
// Calculate independent action times for each batch of messages (each
|
||||
// batch corresponding to an event loop task). This isolates the performance
|
||||
// of different scripts to some extent.
|
||||
for (uint32_t i = 0; i < aMessageQueue.Length(); ++i) {
|
||||
mProcessingGraphUpdateIndex = aMessageQueue[i].mGraphUpdateIndex;
|
||||
nsTArray<nsAutoPtr<ControlMessage> >& messages = aMessageQueue[i].mMessages;
|
||||
for (uint32_t i = 0; i < mFrontMessageQueue.Length(); ++i) {
|
||||
mProcessingGraphUpdateIndex = mFrontMessageQueue[i].mGraphUpdateIndex;
|
||||
nsTArray<nsAutoPtr<ControlMessage> >& messages = mFrontMessageQueue[i].mMessages;
|
||||
|
||||
for (uint32_t j = 0; j < messages.Length(); ++j) {
|
||||
messages[j]->Run();
|
||||
}
|
||||
}
|
||||
aMessageQueue.Clear();
|
||||
mFrontMessageQueue.Clear();
|
||||
|
||||
if (mStreamOrderDirty) {
|
||||
UpdateStreamOrder();
|
||||
@ -1383,12 +1382,11 @@ MediaStreamGraphImpl::Process(GraphTime aFrom, GraphTime aTo)
|
||||
|
||||
bool
|
||||
MediaStreamGraphImpl::OneIteration(GraphTime aFrom, GraphTime aTo,
|
||||
GraphTime aStateFrom, GraphTime aStateEnd,
|
||||
nsTArray<MessageBlock>& aMessageQueue)
|
||||
GraphTime aStateFrom, GraphTime aStateEnd)
|
||||
{
|
||||
UpdateCurrentTimeForStreams(aFrom, aTo);
|
||||
|
||||
UpdateGraph(aMessageQueue, aStateEnd);
|
||||
UpdateGraph(aStateEnd);
|
||||
|
||||
Process(aStateFrom, aStateEnd);
|
||||
|
||||
@ -1398,7 +1396,7 @@ MediaStreamGraphImpl::OneIteration(GraphTime aFrom, GraphTime aTo,
|
||||
MonitorAutoLock lock(CurrentDriver()->GetThreadMonitor());
|
||||
bool finalUpdate = mForceShutDown ||
|
||||
(IterationEnd() >= mEndTime && AllFinishedStreamsNotified()) ||
|
||||
(IsEmpty() && mMessageQueue.IsEmpty());
|
||||
(IsEmpty() && mBackMessageQueue.IsEmpty());
|
||||
PrepareUpdatesToMainThreadState(finalUpdate);
|
||||
if (finalUpdate) {
|
||||
// Enter shutdown mode. The stable-state handler will detect this
|
||||
@ -1413,7 +1411,7 @@ MediaStreamGraphImpl::OneIteration(GraphTime aFrom, GraphTime aTo,
|
||||
|
||||
CurrentDriver()->WaitForNextIteration();
|
||||
|
||||
aMessageQueue.SwapElements(mMessageQueue);
|
||||
SwapMessageQueues();
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1609,7 +1607,7 @@ MediaStreamGraphImpl::RunInStableState()
|
||||
}
|
||||
} else {
|
||||
if (mLifecycleState <= LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) {
|
||||
MessageBlock* block = mMessageQueue.AppendElement();
|
||||
MessageBlock* block = mBackMessageQueue.AppendElement();
|
||||
block->mMessages.SwapElements(mCurrentTaskMessageQueue);
|
||||
block->mGraphUpdateIndex = mNextGraphUpdateIndex;
|
||||
++mNextGraphUpdateIndex;
|
||||
@ -1634,11 +1632,11 @@ MediaStreamGraphImpl::RunInStableState()
|
||||
if ((mForceShutDown || !mRealtime) &&
|
||||
mLifecycleState == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) {
|
||||
// Defer calls to RunDuringShutdown() to happen while mMonitor is not held.
|
||||
for (uint32_t i = 0; i < mMessageQueue.Length(); ++i) {
|
||||
MessageBlock& mb = mMessageQueue[i];
|
||||
for (uint32_t i = 0; i < mBackMessageQueue.Length(); ++i) {
|
||||
MessageBlock& mb = mBackMessageQueue[i];
|
||||
controlMessagesToRunDuringShutdown.MoveElementsFrom(mb.mMessages);
|
||||
}
|
||||
mMessageQueue.Clear();
|
||||
mBackMessageQueue.Clear();
|
||||
MOZ_ASSERT(mCurrentTaskMessageQueue.IsEmpty());
|
||||
// Stop MediaStreamGraph threads. Do not clear gGraph since
|
||||
// we have outstanding DOM objects that may need it.
|
||||
|
@ -181,15 +181,16 @@ public:
|
||||
* This does the actual iteration: Message processing, MediaStream ordering,
|
||||
* blocking computation and processing.
|
||||
*/
|
||||
nsTArray<MessageBlock>& MessageQueue() {
|
||||
CurrentDriver()->GetThreadMonitor().AssertCurrentThreadOwns();
|
||||
return mMessageQueue;
|
||||
}
|
||||
void DoIteration(nsTArray<MessageBlock>& aMessageQueue);
|
||||
void DoIteration();
|
||||
|
||||
bool OneIteration(GraphTime aFrom, GraphTime aTo,
|
||||
GraphTime aStateFrom, GraphTime aStateEnd,
|
||||
nsTArray<MessageBlock>& aMessageQueue);
|
||||
GraphTime aStateFrom, GraphTime aStateEnd);
|
||||
|
||||
// Get
|
||||
nsTArray<MessageBlock>& MessageQueue() {
|
||||
CurrentDriver()->GetThreadMonitor().AssertCurrentThreadOwns();
|
||||
return mFrontMessageQueue;
|
||||
}
|
||||
|
||||
/* This is the end of the current iteration, that is, the current time of the
|
||||
* graph. */
|
||||
@ -226,8 +227,12 @@ public:
|
||||
* Process graph message for this iteration, update stream processing order,
|
||||
* and recompute stream blocking until aEndBlockingDecisions.
|
||||
*/
|
||||
void UpdateGraph(nsTArray<MessageBlock>& aMessageQueue,
|
||||
GraphTime aEndBlockingDecisions);
|
||||
void UpdateGraph(GraphTime aEndBlockingDecisions);
|
||||
|
||||
void SwapMessageQueues() {
|
||||
CurrentDriver()->GetThreadMonitor().AssertCurrentThreadOwns();
|
||||
mFrontMessageQueue.SwapElements(mBackMessageQueue);
|
||||
}
|
||||
/**
|
||||
* Do all the processing and play the audio and video, ffrom aFrom to aTo.
|
||||
*/
|
||||
@ -487,7 +492,10 @@ public:
|
||||
* A list of batches of messages to process. Each batch is processed
|
||||
* as an atomic unit.
|
||||
*/
|
||||
nsTArray<MessageBlock> mMessageQueue;
|
||||
/* Message queue processed by the MSG thread during an iteration. */
|
||||
nsTArray<MessageBlock> mFrontMessageQueue;
|
||||
/* Message queue in which the main thread appends messages. */
|
||||
nsTArray<MessageBlock> mBackMessageQueue;
|
||||
/**
|
||||
* This enum specifies where this graph is in its lifecycle. This is used
|
||||
* to control shutdown.
|
||||
|
Loading…
Reference in New Issue
Block a user