// Copyright 2019 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_ASYNC_CPP_IRQ_H_
#define LIB_ASYNC_CPP_IRQ_H_

#include <lib/async/irq.h>
#include <lib/fit/function.h>

#include <utility>

namespace async {

// Holds context for an irq and its handler, with RAII semantics.
// Automatically unbinds the irq when it goes out of scope.
//
// This class must only be used with single-threaded asynchronous dispatchers
// and must only be accessed on the dispatch thread since it lacks internal
// synchronization of its state.
//
// Concrete implementations: |async::Irq|, |async::IrqMethod|.
// Please do not create subclasses of IrqBase outside of this library.
class IrqBase {
 protected:
  explicit IrqBase(zx_handle_t object, zx_signals_t trigger, uint32_t options,
                   async_irq_handler_t* handler);
  ~IrqBase();

  IrqBase(const IrqBase&) = delete;
  IrqBase(IrqBase&&) = delete;
  IrqBase& operator=(const IrqBase&) = delete;
  IrqBase& operator=(IrqBase&&) = delete;

 public:
  // Gets or sets the interrupt object.
  zx_handle_t object() const { return irq_.object; }
  void set_object(zx_handle_t object) { irq_.object = object; }

  // Begins asynchronously waiting for the object to receive one or more of
  // the trigger signals.  Invokes the handler when the irq is triggered.
  //
  // Returns |ZX_OK| if the irq was successfully begun.
  // Returns |ZX_ERR_BAD_STATE| if the dispatcher is shutting down.
  // Returns |ZX_ERR_NOT_SUPPORTED| if not supported by the dispatcher.
  zx_status_t Begin(async_dispatcher_t* dispatcher);

  // Cancels the irq.
  //
  // If successful, the irq's handler will not run.
  //
  // Returns |ZX_OK| if the irq was pending and it has been successfully
  // canceled; its handler will not run again and can be released immediately.
  // Returns |ZX_ERR_NOT_FOUND| if there was no pending irq either because it
  // already completed, or had not been started.
  // Returns |ZX_ERR_NOT_SUPPORTED| if not supported by the dispatcher.
  zx_status_t Cancel();

 protected:
  template <typename T>
  static T* Dispatch(async_irq* irq, zx_status_t status) {
    static_assert(offsetof(IrqBase, irq_) == 0, "");
    auto self = reinterpret_cast<IrqBase*>(irq);
    if (status == ZX_ERR_CANCELED) {
      // If the irq has been canceled by the dispatcher shutting down,
      // this should be cleared so the irq destructor does not try unbinding.
      self->dispatcher_ = nullptr;
    }
    return static_cast<T*>(self);
  }

 private:
  async_irq_t irq_;
  async_dispatcher_t* dispatcher_ = nullptr;
};

// An asynchronous IRQ whose handler is bound to a |async::irq::Handler| function.
//
// Prefer using |async::IrqMethod| instead for binding to a fixed class member
// function since it is more efficient to dispatch.
class Irq final : public IrqBase {
 public:
  // Handles completion of asynchronous irq operations.
  //
  // The |status| is |ZX_OK| if the irq was satisfied and |signal| is non-null.
  // The |status| is |ZX_ERR_CANCELED| if the dispatcher was shut down before
  // the task's handler ran or the task was canceled.
  using Handler = fit::function<void(async_dispatcher_t* dispatcher, async::Irq* irq,
                                     zx_status_t status, const zx_packet_interrupt_t* interrupt)>;

  // Creates a irq with options == 0.
  explicit Irq(zx_handle_t object = ZX_HANDLE_INVALID, zx_signals_t trigger = ZX_SIGNAL_NONE,
               Handler handler = nullptr)
      : Irq(object, trigger, 0, std::move(handler)) {}

  // Creates a irq with the provided |options|.
  explicit Irq(zx_handle_t object, zx_signals_t trigger, uint32_t options,
               Handler handler = nullptr);

  ~Irq();

  void set_handler(Handler handler) { handler_ = std::move(handler); }
  bool has_handler() const { return !!handler_; }

 private:
  static void CallHandler(async_dispatcher_t* dispatcher, async_irq_t* irq, zx_status_t status,
                          const zx_packet_interrupt_t* signal);

  Handler handler_;
};

// An asynchronous irq whose handler is bound to a fixed class member function.
//
// Usage:
//
// class Foo {
//     void Handle(async_dispatcher_t* dispatcher, async::IrqBase* irq, zx_status_t status,
//                 const zx_packet_interrupt_t* interrupt) { ... }
//     async::IrqMethod<Foo, &Foo::Handle> irq_{this};
// };
template <class Class,
          void (Class::*method)(async_dispatcher_t* dispatcher, async::IrqBase* irq,
                                zx_status_t status, const zx_packet_interrupt_t* interrupt)>
class IrqMethod final : public IrqBase {
 public:
  // Creates a irqMethod with options == 0.
  explicit IrqMethod(Class* instance, zx_handle_t object = ZX_HANDLE_INVALID,
                     zx_signals_t trigger = ZX_SIGNAL_NONE)
      : IrqMethod(instance, object, trigger, 0) {}

  // Creates a IrqMethod with the provided |options|.
  explicit IrqMethod(Class* instance, zx_handle_t object, zx_signals_t trigger, uint32_t options)
      : IrqBase(object, trigger, options, &IrqMethod::CallHandler), instance_(instance) {}

  ~IrqMethod() = default;

 private:
  static void CallHandler(async_dispatcher_t* dispatcher, async_irq_t* irq, zx_status_t status,
                          const zx_packet_interrupt_t* interrupt) {
    auto self = Dispatch<IrqMethod>(irq, status);
    (self->instance_->*method)(dispatcher, self, status, interrupt);
  }

  Class* const instance_;
};

}  // namespace async

#endif  // LIB_ASYNC_CPP_IRQ_H_
