void
DecodedAudioDataSink::Shutdown()
{
  {
    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
    if (mAudioStream) {
      mAudioStream->Cancel();
    }
  }
  nsRefPtr<DecodedAudioDataSink> self = this;
  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
    self->mStopAudioThread = true;
    if (!self->mAudioLoopScheduled) {
      self->AudioLoop();
    }
  });
  DispatchTask(r.forget());

  mThread->Shutdown();
  mThread = nullptr;
  if (mAudioStream) {
    mAudioStream->Shutdown();
    mAudioStream = nullptr;
  }

  // Should've reached the final state after shutdown.
  MOZ_ASSERT(mState == AUDIOSINK_STATE_SHUTDOWN ||
             mState == AUDIOSINK_STATE_ERROR);
  // Should have no pending state change.
  MOZ_ASSERT(mPendingState.isNothing());
}
void CSessionThread::EnqueueTask(struct packet_s & packet)
{
	CSingleLock QueueGateKeeper(&m_TasksPendingAccess, TRUE);

	DispatchTask(packet);//S//MT//m_TasksPending.AddTail(packet);//M

	//MT//TriggerDispatcherThread();//M
}
void
DecodedAudioDataSink::ScheduleNextLoop()
{
  AssertOnAudioThread();
  if (mAudioLoopScheduled) {
    return;
  }
  mAudioLoopScheduled = true;
  nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(this, &DecodedAudioDataSink::AudioLoop);
  DispatchTask(r.forget());
}
void
DecodedAudioDataSink::SetPreservesPitch(bool aPreservesPitch)
{
  AssertNotOnAudioThread();
  nsRefPtr<DecodedAudioDataSink> self = this;
  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
    if (self->mState == AUDIOSINK_STATE_PLAYING) {
      self->mAudioStream->SetPreservesPitch(aPreservesPitch);
    }
  });
  DispatchTask(r.forget());
}
void
DecodedAudioDataSink::SetPlaybackRate(double aPlaybackRate)
{
  AssertNotOnAudioThread();
  MOZ_ASSERT(aPlaybackRate != 0, "Don't set the playbackRate to 0 on AudioStream");
  nsRefPtr<DecodedAudioDataSink> self = this;
  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
    if (self->mState == AUDIOSINK_STATE_PLAYING) {
      self->mAudioStream->SetPlaybackRate(aPlaybackRate);
    }
  });
  DispatchTask(r.forget());
}
void
DecodedAudioDataSink::ScheduleNextLoopCrossThread()
{
  AssertNotOnAudioThread();
  nsRefPtr<DecodedAudioDataSink> self = this;
  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () {
    // Do nothing if there is already a pending task waiting for its turn.
    if (!self->mAudioLoopScheduled) {
      self->AudioLoop();
    }
  });
  DispatchTask(r.forget());
}
void CSessionThread::DispatcherRun()
{
	if (m_stop||!m_open) { CloseSession(); return; }

	++m_dispatcher_thread_instances;

	CSingleLock
		GateKeeper(&m_DispatcherGateKeeper, TRUE),
		ToDo(&m_TasksPendingAccess, TRUE);

	//AddEvent(EVENT_SENT, 0, _T("Processador de pedidos ativado"));

	while (!m_TasksPending.IsEmpty())
	{
		struct packet_s packet;
		packet = m_TasksPending.RemoveHead();
		ToDo.Unlock();
		DispatchTask(packet);
		ToDo.Lock();
	}

	--m_dispatcher_thread_instances;
}
void
DecodedAudioDataSink::SetPlaying(bool aPlaying)
{
  AssertNotOnAudioThread();
  nsRefPtr<DecodedAudioDataSink> self = this;
  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
    if (self->mState != AUDIOSINK_STATE_PLAYING ||
        self->mPlaying == aPlaying) {
      return;
    }
    self->mPlaying = aPlaying;
    // pause/resume AudioStream as necessary.
    if (!aPlaying && !self->mAudioStream->IsPaused()) {
      self->mAudioStream->Pause();
    } else if (aPlaying && self->mAudioStream->IsPaused()) {
      self->mAudioStream->Resume();
    }
    // Wake up the audio loop to play next sample.
    if (aPlaying && !self->mAudioLoopScheduled) {
      self->AudioLoop();
    }
  });
  DispatchTask(r.forget());
}