// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/threading/post_task_and_reply_impl.h"

#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"

namespace base {

namespace {

class PostTaskAndReplyRelay {
 public:
  PostTaskAndReplyRelay(const Location& from_here,
                        OnceClosure task,
                        OnceClosure reply)
      : from_here_(from_here),
        task_(std::move(task)),
        reply_(std::move(reply)) {}
  PostTaskAndReplyRelay(PostTaskAndReplyRelay&&) = default;

  ~PostTaskAndReplyRelay() {
    if (reply_) {
      // This can run:
      // 1) On origin sequence, when:
      //    1a) Posting |task_| fails.
      //    1b) |reply_| is cancelled before running.
      //    1c) The DeleteSoon() below is scheduled.
      // 2) On destination sequence, when:
      //    2a) |task_| is cancelled before running.
      //    2b) Posting |reply_| fails.

      if (!reply_task_runner_->RunsTasksInCurrentSequence()) {
        // Case 2a) or 2b).
        //
        // Destroy callbacks asynchronously on |reply_task_runner| since their
        // destructors can rightfully be affine to it. As always, DeleteSoon()
        // might leak its argument if the target execution environment is
        // shutdown (e.g. MessageLoop deleted, TaskScheduler shutdown).
        //
        // Note: while it's obvious why |reply_| can be affine to
        // |reply_task_runner|, the reason that |task_| can also be affine to it
        // is that it if neither tasks ran, |task_| may still hold an object
        // which was intended to be moved to |reply_| when |task_| ran (such an
        // object's destruction can be affine to |reply_task_runner_| -- e.g.
        // https://crbug.com/829122).
        auto relay_to_delete =
            std::make_unique<PostTaskAndReplyRelay>(std::move(*this));
        reply_task_runner_->DeleteSoon(from_here_, std::move(relay_to_delete));
      }

      // Case 1a), 1b), 1c).
      //
      // Callbacks will be destroyed synchronously at the end of this scope.
    } else {
      // This can run when both callbacks have run or have been moved to another
      // PostTaskAndReplyRelay instance. If |reply_| is null, |task_| must be
      // null too.
      DCHECK(!task_);
    }
  }

  // No assignment operator because of const members.
  PostTaskAndReplyRelay& operator=(PostTaskAndReplyRelay&&) = delete;

  // Static function is used because it is not possible to bind a method call to
  // a non-pointer type.
  static void RunTaskAndPostReply(PostTaskAndReplyRelay relay) {
    DCHECK(relay.task_);
    std::move(relay.task_).Run();

    // Keep a reference to the reply TaskRunner for the PostTask() call before
    // |relay| is moved into a callback.
    scoped_refptr<SequencedTaskRunner> reply_task_runner =
        relay.reply_task_runner_;

    reply_task_runner->PostTask(
        relay.from_here_,
        BindOnce(&PostTaskAndReplyRelay::RunReply, std::move(relay)));
  }

 private:
  // Static function is used because it is not possible to bind a method call to
  // a non-pointer type.
  static void RunReply(PostTaskAndReplyRelay relay) {
    DCHECK(!relay.task_);
    DCHECK(relay.reply_);
    std::move(relay.reply_).Run();
  }

  const Location from_here_;
  OnceClosure task_;
  OnceClosure reply_;
  const scoped_refptr<SequencedTaskRunner> reply_task_runner_ =
      SequencedTaskRunnerHandle::Get();

  DISALLOW_COPY_AND_ASSIGN(PostTaskAndReplyRelay);
};

}  // namespace

namespace internal {

bool PostTaskAndReplyImpl::PostTaskAndReply(const Location& from_here,
                                            OnceClosure task,
                                            OnceClosure reply) {
  DCHECK(task) << from_here.ToString();
  DCHECK(reply) << from_here.ToString();

  return PostTask(from_here,
                  BindOnce(&PostTaskAndReplyRelay::RunTaskAndPostReply,
                           PostTaskAndReplyRelay(from_here, std::move(task),
                                                 std::move(reply))));
}

}  // namespace internal

}  // namespace base
