Ejemplo n.º 1
0
// Called on the worker thread.
nsresult
BackgroundFileSaver::ProcessAttention()
{
  nsresult rv;

  // This function is called whenever the attention of the worker thread has
  // been requested.  This may happen in these cases:
  // * We are about to start the copy for the first time.  In this case, we are
  //   called from an event posted on the worker thread from the control thread
  //   by GetWorkerThreadAttention, and mAsyncCopyContext is null.
  // * We have interrupted the copy for some reason.  In this case, we are
  //   called by AsyncCopyCallback, and mAsyncCopyContext is null.
  // * We are currently executing ProcessStateChange, and attention is requested
  //   by the control thread, for example because SetTarget or Finish have been
  //   called.  In this case, we are called from from an event posted through
  //   GetWorkerThreadAttention.  While mAsyncCopyContext was always null when
  //   the event was posted, at this point mAsyncCopyContext may not be null
  //   anymore, because ProcessStateChange may have started the copy before the
  //   event that called this function was processed on the worker thread.
  // If mAsyncCopyContext is not null, we interrupt the copy and re-enter
  // through AsyncCopyCallback.  This allows us to check if, for instance, we
  // should rename the target file.  We will then restart the copy if needed.
  if (mAsyncCopyContext) {
    NS_CancelAsyncCopy(mAsyncCopyContext, NS_ERROR_ABORT);
    return NS_OK;
  }
  // Use the current shared state to determine the next operation to execute.
  rv = ProcessStateChange();
  if (NS_FAILED(rv)) {
    // If something failed while processing, terminate the operation now.
    {
      MutexAutoLock lock(mLock);

      if (NS_SUCCEEDED(mStatus)) {
        mStatus = rv;
      }
    }
    // Ensure we notify completion now that the operation failed.
    CheckCompletion();
  }

  return NS_OK;
}
Ejemplo n.º 2
0
// Called on the control thread.
nsresult
BackgroundFileSaver::GetWorkerThreadAttention(bool aShouldInterruptCopy)
{
  nsresult rv;

  MutexAutoLock lock(mLock);

  // We only require attention one time.  If this function is called two times
  // before the worker thread wakes up, and the first has aShouldInterruptCopy
  // false and the second true, we won't forcibly interrupt the copy from the
  // control thread.  However, that never happens, because calling Finish with a
  // success code is the only case that may result in aShouldInterruptCopy being
  // false.  In that case, we won't call this function again, because consumers
  // should not invoke other methods on the control thread after calling Finish.
  // And in any case, Finish already closes one end of the pipe, causing the
  // copy to finish properly on its own.
  if (mWorkerThreadAttentionRequested) {
    return NS_OK;
  }

  if (!mAsyncCopyContext) {
    // Copy is not in progress, post an event to handle the change manually.
    nsCOMPtr<nsIRunnable> event =
      NS_NewRunnableMethod(this, &BackgroundFileSaver::ProcessAttention);
    NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);

    rv = mWorkerThread->Dispatch(event, NS_DISPATCH_NORMAL);
    NS_ENSURE_SUCCESS(rv, rv);
  } else if (aShouldInterruptCopy) {
    // Interrupt the copy.  The copy will be resumed, if needed, by the
    // ProcessAttention function, invoked by the AsyncCopyCallback function.
    NS_CancelAsyncCopy(mAsyncCopyContext, NS_ERROR_ABORT);
  }

  // Indicate that attention has been requested successfully, there is no need
  // to post another event until the worker thread processes the current one.
  mWorkerThreadAttentionRequested = true;

  return NS_OK;
}