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

#ifndef LIB_CALLBACK_SCOPED_TASK_RUNNER_H_
#define LIB_CALLBACK_SCOPED_TASK_RUNNER_H_

#include <memory>

#include <lib/async/default.h>
#include <lib/async/dispatcher.h>
#include <lib/fit/function.h>
#include <lib/fit/function_traits.h>
#include <src/lib/fxl/macros.h>
#include <lib/zx/time.h>

namespace callback {

class TaskController {
 public:
  template <class T>
  struct Tag {};

  TaskController();
  virtual ~TaskController();

  // Indicates that further calls to |RunTask| should no-op. Implementations may
  // choose to block until running or outstanding tasks have completed.
  //
  // This method must be idempotent.
  virtual void ShutDown() = 0;
  // Runs a task immediately, or no-ops if this controller has shut down.
  virtual void RunTask(fit::closure task) = 0;

 private:
  FXL_DISALLOW_COPY_ASSIGN_AND_MOVE(TaskController);
};

// A basic task controller that does not synchronize shutdown with task
// execution. Client code is responsible for ensuring that any tasks that may be
// running when the runner is destroyed do not rely on invalid state, typically
// by ensuring that |ShutDown| occurs on the dispatch thread.
class SimpleTaskController : public TaskController {
 public:
  // For ergonomics, this could be a constexpr static Tag<SimpleTaskController>
  // but C++ would then allocate a (small) nonzero size for it. If we only use
  // it inline, it can be optimized out.
  // http://www.open-std.org/jtc1/sc22/open/n2356/class.html, s9p3
  using Type = Tag<SimpleTaskController>;

 private:
  // |TaskController|
  // This implementation does not block, and should be called on the dispatch
  // thread.
  void ShutDown() override;
  // |TaskController|
  void RunTask(fit::closure task) override;

  // This could easily be a std::atomic_bool, but since this implementation is
  // not synchronized, in correct code I don't think there's a case where this
  // makes a difference.
  //
  // A common idiom is to use |fxl::WeakPtr| for this kind of guard. However,
  // that is not thread-safe as |fxl::WeakPtr| contains non-atomic flag
  // twiddling, and |fxl::WeakPtr::InvalidateWeakPtrs| allows new valid pointers
  // to be created after it is called so it cannot be used as a |ShutDown|
  // method. Despite being unsynchronized, |SimpleTaskController| lets the
  // caller |ShutDown| on the dispatch thread.
  bool alive_ = true;
};

// An object that wraps the posting logic of an |async_t|, but that is
// neither copyable nor moveable and will generally not run any task after being
// deleted, though edge case handling may differ between |Controller|
// implementations.
//
// This class is mostly thread-safe, though it must not go out of scope while
// any of its methods are being called, and handling of edge cases varies
// depending on the controller implementation. Notably, the default |Controller|
// is not synchronized, so |ShutDown| should occur on the dispatch thread (after
// which destruction may happen on any thread).
//
// Typically, this class should appear towards the end of the fields of an
// owning class so that it goes out of scope before any state that tasks may
// depend on.
//
// This class may be used without a dispatcher, but the common use case is to
// manage FIDL calls.
class ScopedTaskRunner {
 public:
  explicit ScopedTaskRunner(
      async_dispatcher_t* dispatcher = async_get_default_dispatcher());

  template <class Controller>
  ScopedTaskRunner(
      typename TaskController::Tag<Controller> controller_type,
      async_dispatcher_t* dispatcher = async_get_default_dispatcher())
      : dispatcher_(dispatcher), controller_(std::make_shared<Controller>()) {}

  ~ScopedTaskRunner();

  async_dispatcher_t* dispatcher() const { return dispatcher_; }

  // Pre-emptively ends this ScopedTaskRunner's lifecycle. All subsequent tasks
  // will no-op. This method may block, depending on the |TaskController|
  // implementation. The default implementation does not block, so care should
  // be taken by callers that any tasks executing during shutdown do not depend
  // on state guarded by this instance, typically by calling this method from
  // the dispatch thread.
  //
  // This method is idempotent and will automatically be called when this class
  // goes out of scope.
  void ShutDown();

  // Posts a task to run as soon as possible on the dispatcher after the current
  // dispatch cycle.
  void PostTask(fit::closure task);

  // Posts a task to run as soon as possible after the specified |target_time|.
  void PostTaskForTime(fit::closure task, zx::time target_time);

  // Posts a task to run as soon as possible after the specified |delay|.
  void PostDelayedTask(fit::closure task, zx::duration delay);

  // Convenience function to post a repeating periodic task. If |invoke_now| is
  // true, the task is run as soon as possible on the dispatcher after the
  // current dispatch cycle as well as periodically. Otherwise, the first
  // invocation of the task will be as soon as possible after the specified
  // |interval|.
  void PostPeriodicTask(fit::closure task, zx::duration interval,
                        bool invoke_now = true);

  // Scopes a task to the current task runner without scheduling it. This means
  // that the given function will be called when the returned function is called
  // if and only if this task runner has not been deleted or shut down.
  // Synchronization of the guard depends on the |TaskController|
  // implementation; the default implementation is unsynchronized.
  template <class Task, class... Args>
  auto MakeScoped(Task task, fit::parameter_pack<Args...>) {
    return [controller = controller_,
            task = std::move(task)](Args... args) mutable {
      // This differs from |callback::MakeScoped| in that |controller| is aware
      // of the task from start to finish, as opposed to |callback::MakeScoped|
      // which only consults |witness| when the task begins.
      return controller->RunTask([task = std::move(task), &args...]() mutable {
        task(std::forward<Args>(args)...);
      });
    };
  }

  template <class Task>
  auto MakeScoped(Task task) {
    return MakeScoped(std::move(task),
                      typename fit::function_traits<Task>::args{});
  }

 private:
  async_dispatcher_t* const dispatcher_;
  const std::shared_ptr<TaskController> controller_;

  // The only thing preventing this from being movable is the const fields. If
  // we ever need this to be movable, we can do it easily.
  FXL_DISALLOW_COPY_ASSIGN_AND_MOVE(ScopedTaskRunner);
};

}  // namespace callback

#endif  // LIB_CALLBACK_SCOPED_TASK_RUNNER_H_
