// Copyright 2021 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_FDF_CPP_DISPATCHER_H_
#define LIB_FDF_CPP_DISPATCHER_H_

#include <lib/async/dispatcher.h>
#include <lib/fdf/cpp/unowned.h>
#include <lib/fdf/dispatcher.h>
#include <lib/fit/function.h>
#include <lib/stdcompat/string_view.h>
#include <lib/zx/result.h>
#include <zircon/assert.h>

#include <string>

namespace fdf_env {
// Forward declaration to support friend declaration.
class DispatcherBuilder;
}  // namespace fdf_env

namespace fdf_internal {
// Forward declaration to support friend declaration.
class TestDispatcherBuilder;
}  // namespace fdf_internal

namespace fdf {

// C++ wrapper for a dispatcher, with RAII semantics. Automatically shuts down
// the dispatcher when it goes out of scope.
//
// # Thread safety
//
// This class is thread-unsafe.
//
// # Example
//
//   void Driver::OnDispatcherShutdown(fdf_dispatcher_t* dispatcher) {
//     // Handle dispatcher shutdown.
//     // It is now safe to destroy |dispatcher|.
//   }
//
//   void Driver::Start() {
//     // TODO(https://fxbug.dev/42166901): update this once scheduler_role is supported.
//     const std::string_view scheduler_role = "";
//     const std::string_view name = "MyDriver";
//
//     auto shutdown_handler = [&]() {
//       OnDispatcherShutdown();
//     };
//     auto dispatcher =
//         fdf::SynchronizedDispatcher::Create(0, name, shutdown_handler, scheduler_role);
//
//     fdf::ChannelRead channel_read;
//     ...
//     zx_status_t status = channel_read->Begin(dispatcher.get());
//
//     // The dispatcher will call the channel_read handler when ready.
//   }
class Dispatcher {
 public:
  using HandleType = fdf_dispatcher_t*;

  // Called when the asynchronous shutdown for |dispatcher| has completed.
  using ShutdownHandler = fit::callback<void(fdf_dispatcher_t* dispatcher)>;

  // Returns the current thread's dispatcher.
  // This will return NULL if not called from a dispatcher managed thread.
  static Unowned<Dispatcher> GetCurrent() {
    return Unowned<Dispatcher>(fdf_dispatcher_get_current_dispatcher());
  }

  // Returns an unowned dispatcher provided an async dispatcher. If |async_dispatcher| was not
  // retrieved via |fdf_dispatcher_get_async_dispatcher|, the call will result in a crash.
  static Unowned<Dispatcher> Downcast(async_dispatcher_t* async_dispatcher) {
    return Unowned<Dispatcher>(fdf_dispatcher_downcast_async_dispatcher(async_dispatcher));
  }

  explicit Dispatcher(fdf_dispatcher_t* dispatcher = nullptr) : dispatcher_(dispatcher) {}

  // Dispatcher cannot be copied.
  Dispatcher(const Dispatcher& to_copy) = delete;
  Dispatcher& operator=(const Dispatcher& other) = delete;

  // Dispatcher can be moved. Once moved, invoking a method on an instance will
  // yield undefined behavior.
  Dispatcher(Dispatcher&& other) noexcept : Dispatcher(other.release()) {}
  Dispatcher& operator=(Dispatcher&& other) noexcept {
    reset(other.release());
    return *this;
  }

  // Begins shutting down the dispatcher. Shutting down is an asynchronous operation.
  //
  // Once |Dispatcher::ShutdownAsync| is called, the dispatcher will no longer
  // accept queueing new |async_dispatcher_t| operations or |ChannelRead| callbacks.
  //
  // The dispatcher will asynchronously wait for all pending |async_dispatcher_t|
  // and |ChannelRead| callbacks to complete. Then it will serially cancel all
  // remaining callbacks with |ZX_ERR_CANCELED| and call the shutdown handler set
  // in |SynchronizedDispatcher::Create| or |UnsynchronizedDispatcher::Create|.
  //
  // If the dispatcher is already shutting down or has completed shutdown, this will do nothing.
  void ShutdownAsync() {
    if (dispatcher_) {
      fdf_dispatcher_shutdown_async(dispatcher_);
    }
  }

  // The dispatcher must be completely shutdown before the dispatcher can be closed.
  // i.e. the shutdown handler set in |SynchronizedDispatcher::Create|
  // or |UnsynchronizedDispatcher::Create| has been called.
  // It is safe to call this from that shutdown handler.
  ~Dispatcher() { close(); }

  fdf_dispatcher_t* get() const { return dispatcher_; }

  void reset(fdf_dispatcher_t* dispatcher = nullptr) {
    close();
    dispatcher_ = dispatcher;
  }

  void close() {
    if (dispatcher_) {
      fdf_dispatcher_destroy(dispatcher_);
      dispatcher_ = nullptr;
    }
  }

  fdf_dispatcher_t* release() {
    fdf_dispatcher_t* ret = dispatcher_;
    dispatcher_ = nullptr;
    return ret;
  }

  // Gets the dispatcher's asynchronous dispatch interface.
  async_dispatcher_t* async_dispatcher() const {
    return dispatcher_ ? fdf_dispatcher_get_async_dispatcher(dispatcher_) : nullptr;
  }

  // Returns the options set for this dispatcher.
  std::optional<uint32_t> options() const {
    return dispatcher_ ? std::optional(fdf_dispatcher_get_options(dispatcher_)) : std::nullopt;
  }

  Unowned<Dispatcher> borrow() const { return Unowned<Dispatcher>(dispatcher_); }

  // Removes the allow_sync option that was set on the dispatcher during creation.
  // Calling this will remove the ability of the dispatcher to make any more synchronous calls.
  //
  // # Thread requirements
  //
  // This must be called from the |dispatcher|'s own context.
  //
  // # Errors
  //
  // ZX_ERR_BAD_STATE: Not called from the same context as the given dispatcher or the dispatcher
  // is not in a running state.
  //
  // ZX_ERR_ALREADY_EXISTS: The dispatcher did not contain the allow_sync option. This can happen
  // if this is called more than once, or if it was not created with that option.
  zx::result<> SealAllowSync() {
    return zx::make_result(
        fdf_dispatcher_seal(dispatcher_, FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS));
  }

 protected:
  // Friend declaration is needed because the |DispatcherShutdownContext| is private.
  friend class fdf_env::DispatcherBuilder;
  friend class fdf_internal::TestDispatcherBuilder;

  class DispatcherShutdownContext final {
   public:
    explicit DispatcherShutdownContext(ShutdownHandler handler)
        : observer_{CallHandler}, handler_(std::move(handler)) {}

    fdf_dispatcher_shutdown_observer_t* observer() { return &observer_; }

   private:
    static void CallHandler(fdf_dispatcher_t* dispatcher,
                            fdf_dispatcher_shutdown_observer_t* observer) {
      static_assert(offsetof(DispatcherShutdownContext, observer_) == 0);
      auto self = reinterpret_cast<DispatcherShutdownContext*>(observer);
      self->handler_(dispatcher);
      // Delete the pointer allocated in |SynchronizedDispatcher::Create| or
      // |UnsynchronizedDispatcher::Create|.
      delete self;
    }

    fdf_dispatcher_shutdown_observer_t observer_;
    ShutdownHandler handler_;
  };

  fdf_dispatcher_t* dispatcher_;
};

// Dispatcher that disallows parallel calls into callbacks.
class SynchronizedDispatcher final : public Dispatcher {
 public:
  // Options that may be passed to |fdf::SynchronizedDispatcher::Create|.
  // When using the |SynchronizedDispatcher| class, the dispatcher options must set
  // FDF_DISPATCHER_OPTION_SYNCHRONIZED.
  struct Options {
    // The options to set for the dispatcher. In additional to FDF_DISPATCHER_OPTION_SYNCHRONIZED,
    // the following options are supported:
    //   * `FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS` - blocking calls may be made on this dispatcher.
    uint32_t value = FDF_DISPATCHER_OPTION_SYNCHRONIZED;
    // Specifies a synchronized dispatcher that allows blocking calls to be made.
    static const Options kAllowSyncCalls;
  };

  // Creates a dispatcher for performing asynchronous operations.
  //
  // |options| provides the dispatcher configuration. This will panic if options does not
  // set FDF_DISPATCHER_OPTION_SYNCHRONIZED.
  //
  // |name| is reported via diagnostics. It is similar to setting the name of a thread. Names longer
  // than `ZX_MAX_NAME_LEN` may be truncated.
  //
  // |scheduler_role| is a hint. It may or not impact the priority the work scheduler against the
  // dispatcher is handled at. It may or may not impact the ability for other drivers to share
  // zircon threads with the dispatcher.
  //
  // |shutdown_handler| will be called after |ShutdownAsync| has been called, and the dispatcher
  // has completed its asynchronous shutdown. The client must keep any pointers that are
  // referenced in |shutdown_handler| alive until the handler runs.
  //
  // # Thread requirements
  //
  // This must be called from a thread managed by the driver runtime.
  //
  // # Errors
  //
  // ZX_ERR_INVALID_ARGS: This was not called from a thread managed by the driver runtime.
  //
  // ZX_ERR_BAD_STATE: Dispatchers are currently not allowed to be created, such as when a driver
  // is being shutdown by its driver host.
  static zx::result<SynchronizedDispatcher> Create(Options options, cpp17::string_view name,
                                                   ShutdownHandler shutdown_handler,
                                                   cpp17::string_view scheduler_role = {}) {
    ZX_ASSERT_MSG((options.value & FDF_DISPATCHER_OPTION_SYNCHRONIZATION_MASK) ==
                      FDF_DISPATCHER_OPTION_SYNCHRONIZED,
                  "options.value=%u, needs to have FDF_DISPATCHER_OPTION_SYNCHRONIZED",
                  options.value);
    // We need to create an additional shutdown context in addition to the fdf::Dispatcher
    // object, as the fdf::SynchronizedDispatcher may be destructed before the shutdown handler
    // is called. This can happen if the raw pointer is released from the
    // fdf::SynchronizedDispatcher.
    auto dispatcher_shutdown_context =
        std::make_unique<DispatcherShutdownContext>(std::move(shutdown_handler));
    fdf_dispatcher_t* dispatcher;
    zx_status_t status =
        fdf_dispatcher_create(FDF_DISPATCHER_OPTION_SYNCHRONIZED | options.value, name.data(),
                              name.size(), scheduler_role.data(), scheduler_role.size(),
                              dispatcher_shutdown_context->observer(), &dispatcher);
    if (status != ZX_OK) {
      return zx::error(status);
    }
    dispatcher_shutdown_context.release();
    return zx::ok(SynchronizedDispatcher(dispatcher));
  }

  explicit SynchronizedDispatcher(fdf_dispatcher_t* dispatcher = nullptr) : Dispatcher(dispatcher) {
    if (dispatcher) {
      ZX_ASSERT((fdf_dispatcher_get_options(dispatcher) &
                 FDF_DISPATCHER_OPTION_SYNCHRONIZATION_MASK) == FDF_DISPATCHER_OPTION_SYNCHRONIZED);
    }
  }

  Unowned<SynchronizedDispatcher> borrow() const {
    return Unowned<SynchronizedDispatcher>(dispatcher_);
  }
};

inline constexpr SynchronizedDispatcher::Options SynchronizedDispatcher::Options::kAllowSyncCalls =
    {FDF_DISPATCHER_OPTION_SYNCHRONIZED | FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS};

// Dispatcher that allows parallel calls into callbacks.
class UnsynchronizedDispatcher final : public Dispatcher {
 public:
  // Options that may be passed to |fdf::UnsynchronizedDispatcher::Create|.
  // When using the |UnsynchronizedDispatcher| class, the dispatcher options must set
  // FDF_DISPATCHER_OPTION_UNSYNCHRONIZED.
  struct Options {
    // The options to set for the dispatcher. Currently no additional options are supported.
    uint32_t value = FDF_DISPATCHER_OPTION_UNSYNCHRONIZED;
  };

  // Creates a dispatcher for performing asynchronous operations.
  //
  // |options| provides the dispatcher configuration. This will panic if options does not
  // set FDF_DISPATCHER_OPTION_UNSYNCHRONIZED.
  //
  // |name| is reported via diagnostics. It is similar to setting the name of a thread. Names longer
  // than `ZX_MAX_NAME_LEN` may be truncated.
  //
  // |scheduler_role| is a hint. It may or not impact the priority the work scheduler against the
  // dispatcher is handled at. It may or may not impact the ability for other drivers to share
  // zircon threads with the dispatcher.
  //
  // |shutdown_handler| will be called after |ShutdownAsync| has been called, and the dispatcher
  // has completed its asynchronous shutdown. The client must keep any pointers that are
  // referenced in |shutdown_handler| alive until the handler runs.
  //
  // # Thread requirements
  //
  // This must be called from a thread managed by the driver runtime.
  //
  // # Errors
  //
  // ZX_ERR_NOT_SUPPORTED: |options| is not a supported configuration, which is any of:
  //   * `FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS`.
  //
  // ZX_ERR_INVALID_ARGS: This was not called from a thread managed by the driver runtime.
  //
  // ZX_ERR_BAD_STATE: Dispatchers are currently not allowed to be created, such as when a driver
  // is being shutdown by its driver host.
  static zx::result<UnsynchronizedDispatcher> Create(Options options, cpp17::string_view name,
                                                     ShutdownHandler shutdown_handler,
                                                     cpp17::string_view scheduler_role = {}) {
    ZX_ASSERT_MSG((options.value & FDF_DISPATCHER_OPTION_SYNCHRONIZATION_MASK) ==
                      FDF_DISPATCHER_OPTION_UNSYNCHRONIZED,
                  "options.value=%u, needs to have FDF_DISPATCHER_OPTION_UNSYNCHRONIZED",
                  options.value);
    // We need to create an additional shutdown context in addition to the fdf::Dispatcher
    // object, as the fdf::UnsynchronizedDispatcher may be destructed before the shutdown handler
    // is called. This can happen if the raw pointer is released from the
    // fdf::UnsynchronizedDispatcher.
    auto dispatcher_shutdown_context =
        std::make_unique<DispatcherShutdownContext>(std::move(shutdown_handler));
    fdf_dispatcher_t* dispatcher;
    zx_status_t status =
        fdf_dispatcher_create(FDF_DISPATCHER_OPTION_UNSYNCHRONIZED | options.value, name.data(),
                              name.size(), scheduler_role.data(), scheduler_role.size(),
                              dispatcher_shutdown_context->observer(), &dispatcher);
    if (status != ZX_OK) {
      return zx::error(status);
    }
    dispatcher_shutdown_context.release();
    return zx::ok(UnsynchronizedDispatcher(dispatcher));
  }

  explicit UnsynchronizedDispatcher(fdf_dispatcher_t* dispatcher = nullptr)
      : Dispatcher(dispatcher) {
    if (dispatcher) {
      ZX_ASSERT(
          (fdf_dispatcher_get_options(dispatcher) & FDF_DISPATCHER_OPTION_SYNCHRONIZATION_MASK) ==
          FDF_DISPATCHER_OPTION_UNSYNCHRONIZED);
    }
  }

  Unowned<UnsynchronizedDispatcher> borrow() const {
    return Unowned<UnsynchronizedDispatcher>(dispatcher_);
  }
};

using UnownedDispatcher = Unowned<Dispatcher>;
using UnownedSynchronizedDispatcher = Unowned<SynchronizedDispatcher>;
using UnownedUnsynchronizedDispatcher = Unowned<UnsynchronizedDispatcher>;

}  // namespace fdf

#endif  // LIB_FDF_CPP_DISPATCHER_H_
