// Copyright 2020 The Marl Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// marl::DAG<> provides an ahead of time, declarative, directed acyclic
// task graph.

#ifndef marl_dag_h
#define marl_dag_h

#include "containers.h"
#include "export.h"
#include "memory.h"
#include "scheduler.h"
#include "waitgroup.h"

namespace marl {
namespace detail {
using DAGCounter = std::atomic<uint32_t>;
template <typename T>
struct DAGRunContext {
  T data;
  Allocator::unique_ptr<DAGCounter> counters;

  template <typename F>
  MARL_NO_EXPORT inline void invoke(F&& f) {
    f(data);
  }
};
template <>
struct DAGRunContext<void> {
  Allocator::unique_ptr<DAGCounter> counters;

  template <typename F>
  MARL_NO_EXPORT inline void invoke(F&& f) {
    f();
  }
};
template <typename T>
struct DAGWork {
  using type = std::function<void(T)>;
};
template <>
struct DAGWork<void> {
  using type = std::function<void()>;
};
}  // namespace detail

///////////////////////////////////////////////////////////////////////////////
// Forward declarations
///////////////////////////////////////////////////////////////////////////////
template <typename T>
class DAG;

template <typename T>
class DAGBuilder;

template <typename T>
class DAGNodeBuilder;

///////////////////////////////////////////////////////////////////////////////
// DAGBase<T>
///////////////////////////////////////////////////////////////////////////////

// DAGBase is derived by DAG<T> and DAG<void>. It has no public API.
template <typename T>
class DAGBase {
 protected:
  friend DAGBuilder<T>;
  friend DAGNodeBuilder<T>;

  using RunContext = detail::DAGRunContext<T>;
  using Counter = detail::DAGCounter;
  using NodeIndex = size_t;
  using Work = typename detail::DAGWork<T>::type;
  static const constexpr size_t NumReservedNodes = 32;
  static const constexpr size_t NumReservedNumOuts = 4;
  static const constexpr size_t InvalidCounterIndex = ~static_cast<size_t>(0);
  static const constexpr NodeIndex RootIndex = 0;
  static const constexpr NodeIndex InvalidNodeIndex =
      ~static_cast<NodeIndex>(0);

  // DAG work node.
  struct Node {
    MARL_NO_EXPORT inline Node() = default;
    MARL_NO_EXPORT inline Node(Work&& work);

    // The work to perform for this node in the graph.
    Work work;

    // counterIndex if valid, is the index of the counter in the RunContext for
    // this node. The counter is decremented for each completed dependency task
    // (ins), and once it reaches 0, this node will be invoked.
    size_t counterIndex = InvalidCounterIndex;

    // Indices for all downstream nodes.
    containers::vector<NodeIndex, NumReservedNumOuts> outs;
  };

  // initCounters() allocates and initializes the ctx->coutners from
  // initialCounters.
  MARL_NO_EXPORT inline void initCounters(RunContext* ctx,
                                          Allocator* allocator);

  // notify() is called each time a dependency task (ins) has completed for the
  // node with the given index.
  // If all dependency tasks have completed (or this is the root node) then
  // notify() returns true and the caller should then call invoke().
  MARL_NO_EXPORT inline bool notify(RunContext*, NodeIndex);

  // invoke() calls the work function for the node with the given index, then
  // calls notify() and possibly invoke() for all the dependee nodes.
  MARL_NO_EXPORT inline void invoke(RunContext*, NodeIndex, WaitGroup*);

  // nodes is the full list of the nodes in the graph.
  // nodes[0] is always the root node, which has no dependencies (ins).
  containers::vector<Node, NumReservedNodes> nodes;

  // initialCounters is a list of initial counter values to be copied to
  // RunContext::counters on DAG<>::run().
  // initialCounters is indexed by Node::counterIndex, and only contains counts
  // for nodes that have at least 2 dependencies (ins) - because of this the
  // number of entries in initialCounters may be fewer than nodes.
  containers::vector<uint32_t, NumReservedNodes> initialCounters;
};

template <typename T>
DAGBase<T>::Node::Node(Work&& work) : work(std::move(work)) {}

template <typename T>
void DAGBase<T>::initCounters(RunContext* ctx, Allocator* allocator) {
  auto numCounters = initialCounters.size();
  ctx->counters = allocator->make_unique_n<Counter>(numCounters);
  for (size_t i = 0; i < numCounters; i++) {
    ctx->counters.get()[i] = {initialCounters[i]};
  }
}

template <typename T>
bool DAGBase<T>::notify(RunContext* ctx, NodeIndex nodeIdx) {
  Node* node = &nodes[nodeIdx];

  // If we have multiple dependencies, decrement the counter and check whether
  // we've reached 0.
  if (node->counterIndex == InvalidCounterIndex) {
    return true;
  }
  auto counters = ctx->counters.get();
  auto counter = --counters[node->counterIndex];
  return counter == 0;
}

template <typename T>
void DAGBase<T>::invoke(RunContext* ctx, NodeIndex nodeIdx, WaitGroup* wg) {
  Node* node = &nodes[nodeIdx];

  // Run this node's work.
  if (node->work) {
    ctx->invoke(node->work);
  }

  // Then call notify() on all dependees (outs), and invoke() those that
  // returned true.
  // We buffer the node to invoke (toInvoke) so we can schedule() all but the
  // last node to invoke(), and directly call the last invoke() on this thread.
  // This is done to avoid the overheads of scheduling when a direct call would
  // suffice.
  NodeIndex toInvoke = InvalidNodeIndex;
  for (NodeIndex idx : node->outs) {
    if (notify(ctx, idx)) {
      if (toInvoke != InvalidNodeIndex) {
        wg->add(1);
        // Schedule while promoting the WaitGroup capture from a pointer
        // reference to a value. This ensures that the WaitGroup isn't dropped
        // while in use.
        schedule(
            [=](WaitGroup wg) {
              invoke(ctx, toInvoke, &wg);
              wg.done();
            },
            *wg);
      }
      toInvoke = idx;
    }
  }
  if (toInvoke != InvalidNodeIndex) {
    invoke(ctx, toInvoke, wg);
  }
}

///////////////////////////////////////////////////////////////////////////////
// DAGNodeBuilder<T>
///////////////////////////////////////////////////////////////////////////////

// DAGNodeBuilder is the builder interface for a DAG node.
template <typename T>
class DAGNodeBuilder {
  using NodeIndex = typename DAGBase<T>::NodeIndex;

 public:
  // then() builds and returns a new DAG node that will be invoked after this
  // node has completed.
  //
  // F is a function that will be called when the new DAG node is invoked, with
  // the signature:
  //   void(T)   when T is not void
  // or
  //   void()    when T is void
  template <typename F>
  MARL_NO_EXPORT inline DAGNodeBuilder then(F&&);

 private:
  friend DAGBuilder<T>;
  MARL_NO_EXPORT inline DAGNodeBuilder(DAGBuilder<T>*, NodeIndex);
  DAGBuilder<T>* builder;
  NodeIndex index;
};

template <typename T>
DAGNodeBuilder<T>::DAGNodeBuilder(DAGBuilder<T>* builder, NodeIndex index)
    : builder(builder), index(index) {}

template <typename T>
template <typename F>
DAGNodeBuilder<T> DAGNodeBuilder<T>::then(F&& work) {
  auto node = builder->node(std::move(work));
  builder->addDependency(*this, node);
  return node;
}

///////////////////////////////////////////////////////////////////////////////
// DAGBuilder<T>
///////////////////////////////////////////////////////////////////////////////
template <typename T>
class DAGBuilder {
 public:
  // DAGBuilder constructor
  MARL_NO_EXPORT inline DAGBuilder(Allocator* allocator = Allocator::Default);

  // root() returns the root DAG node.
  MARL_NO_EXPORT inline DAGNodeBuilder<T> root();

  // node() builds and returns a new DAG node with no initial dependencies.
  // The returned node must be attached to the graph in order to invoke F or any
  // of the dependees of this returned node.
  //
  // F is a function that will be called when the new DAG node is invoked, with
  // the signature:
  //   void(T)   when T is not void
  // or
  //   void()    when T is void
  template <typename F>
  MARL_NO_EXPORT inline DAGNodeBuilder<T> node(F&& work);

  // node() builds and returns a new DAG node that depends on all the tasks in
  // after to be completed before invoking F.
  //
  // F is a function that will be called when the new DAG node is invoked, with
  // the signature:
  //   void(T)   when T is not void
  // or
  //   void()    when T is void
  template <typename F>
  MARL_NO_EXPORT inline DAGNodeBuilder<T> node(
      F&& work,
      std::initializer_list<DAGNodeBuilder<T>> after);

  // addDependency() adds parent as dependency on child. All dependencies of
  // child must have completed before child is invoked.
  MARL_NO_EXPORT inline void addDependency(DAGNodeBuilder<T> parent,
                                           DAGNodeBuilder<T> child);

  // build() constructs and returns the DAG. No other methods of this class may
  // be called after calling build().
  MARL_NO_EXPORT inline Allocator::unique_ptr<DAG<T>> build();

 private:
  static const constexpr size_t NumReservedNumIns = 4;
  using Node = typename DAG<T>::Node;

  // The DAG being built.
  Allocator::unique_ptr<DAG<T>> dag;

  // Number of dependencies (ins) for each node in dag->nodes.
  containers::vector<uint32_t, NumReservedNumIns> numIns;
};

template <typename T>
DAGBuilder<T>::DAGBuilder(Allocator* allocator /* = Allocator::Default */)
    : dag(allocator->make_unique<DAG<T>>()), numIns(allocator) {
  // Add root
  dag->nodes.emplace_back(Node{});
  numIns.emplace_back(0);
}

template <typename T>
DAGNodeBuilder<T> DAGBuilder<T>::root() {
  return DAGNodeBuilder<T>{this, DAGBase<T>::RootIndex};
}

template <typename T>
template <typename F>
DAGNodeBuilder<T> DAGBuilder<T>::node(F&& work) {
  return node(std::forward<F>(work), {});
}

template <typename T>
template <typename F>
DAGNodeBuilder<T> DAGBuilder<T>::node(
    F&& work,
    std::initializer_list<DAGNodeBuilder<T>> after) {
  MARL_ASSERT(numIns.size() == dag->nodes.size(),
              "NodeBuilder vectors out of sync");
  auto index = dag->nodes.size();
  numIns.emplace_back(0);
  dag->nodes.emplace_back(Node{std::move(work)});
  auto node = DAGNodeBuilder<T>{this, index};
  for (auto in : after) {
    addDependency(in, node);
  }
  return node;
}

template <typename T>
void DAGBuilder<T>::addDependency(DAGNodeBuilder<T> parent,
                                  DAGNodeBuilder<T> child) {
  numIns[child.index]++;
  dag->nodes[parent.index].outs.push_back(child.index);
}

template <typename T>
Allocator::unique_ptr<DAG<T>> DAGBuilder<T>::build() {
  auto numNodes = dag->nodes.size();
  MARL_ASSERT(numIns.size() == dag->nodes.size(),
              "NodeBuilder vectors out of sync");
  for (size_t i = 0; i < numNodes; i++) {
    if (numIns[i] > 1) {
      auto& node = dag->nodes[i];
      node.counterIndex = dag->initialCounters.size();
      dag->initialCounters.push_back(numIns[i]);
    }
  }
  return std::move(dag);
}

///////////////////////////////////////////////////////////////////////////////
// DAG<T>
///////////////////////////////////////////////////////////////////////////////
template <typename T = void>
class DAG : public DAGBase<T> {
 public:
  using Builder = DAGBuilder<T>;
  using NodeBuilder = DAGNodeBuilder<T>;

  // run() invokes the function of each node in the graph of the DAG, passing
  // data to each, starting with the root node. All dependencies need to have
  // completed their function before dependees will be invoked.
  MARL_NO_EXPORT inline void run(T& data,
                                 Allocator* allocator = Allocator::Default);
};

template <typename T>
void DAG<T>::run(T& arg, Allocator* allocator /* = Allocator::Default */) {
  typename DAGBase<T>::RunContext ctx{arg};
  this->initCounters(&ctx, allocator);
  WaitGroup wg;
  this->invoke(&ctx, this->RootIndex, &wg);
  wg.wait();
}

///////////////////////////////////////////////////////////////////////////////
// DAG<void>
///////////////////////////////////////////////////////////////////////////////
template <>
class DAG<void> : public DAGBase<void> {
 public:
  using Builder = DAGBuilder<void>;
  using NodeBuilder = DAGNodeBuilder<void>;

  // run() invokes the function of each node in the graph of the DAG, starting
  // with the root node. All dependencies need to have completed their function
  // before dependees will be invoked.
  MARL_NO_EXPORT inline void run(Allocator* allocator = Allocator::Default);
};

void DAG<void>::run(Allocator* allocator /* = Allocator::Default */) {
  typename DAGBase<void>::RunContext ctx{};
  this->initCounters(&ctx, allocator);
  WaitGroup wg;
  this->invoke(&ctx, this->RootIndex, &wg);
  wg.wait();
}

}  // namespace marl

#endif  // marl_dag_h
