Program Listing for File executable_task.hpp

Return to documentation for file (cosm/ta/executable_task.hpp)

#pragma once

/*******************************************************************************
 * Includes
 ******************************************************************************/
#include <string>
#include <vector>

#include "rcppsw/er/client.hpp"

#include "cosm/ta/abort_probability.hpp"
#include "cosm/ta/logical_task.hpp"
#include "cosm/ta/metrics/execution_metrics.hpp"
#include "cosm/ta/time_estimate.hpp"

/*******************************************************************************
 * Namespaces/Decls
 ******************************************************************************/
namespace rcppsw::math::config {
struct ema_config;
} // namespace rcppsw::math::config

namespace cosm::ta {

namespace config {
struct src_sigmoid_sel_config;
} /* namespace config */

/*******************************************************************************
 * Class Definitions
 ******************************************************************************/
class executable_task : public logical_task,
                        public metrics::execution_metrics,
                        public rer::client<executable_task> {
 public:
  static constexpr const size_t kMAX_INTERFACES = 2;
  static inline const std::string kAbortSrcExec = "exec";
  static inline const std::string kAbortSrcInterface = "interface";

  executable_task(const std::string& name,
                  const config::src_sigmoid_sel_config* abort,
                  const rmath::config::ema_config* estimation);

  ~executable_task(void) override = default;

  /* execution metrics */
  rtypes::timestep task_last_exec_time(void) const override {
    return m_last_exec_time;
  }
  rtypes::timestep task_last_interface_time(size_t i) const override {
    ER_ASSERT(i <= kMAX_INTERFACES,
              "Bad interface ID %zu for task %s",
              i,
              name().c_str());
    return m_last_interface_times[i];
  }
  bool task_aborted(void) const override final { return m_task_aborted; }
  const time_estimate& task_exec_estimate(void) const override final {
    return m_exec_estimate;
  }
  const time_estimate& task_interface_estimate(size_t i) const override final {
    ER_ASSERT(i <= kMAX_INTERFACES,
              "Bad interface ID %zu for task %s",
              i,
              name().c_str());
    return m_interface_estimates[i];
  }
  bool task_at_interface(void) const override { return -1 != active_interface(); }

  void interface_time_update(void) {
    if (-1 != active_interface()) {
      m_interface_times[active_interface()] = interface_time_calc(
          active_interface(), m_interface_start_times[active_interface()]);
    }
  }

  int active_interface(void) const RCPPSW_PURE;

  int task_last_active_interface(void) const override final {
    return m_last_active_interface;
  }

  void interface_time_reset(void) {
    if (-1 != active_interface()) {
      m_interface_times[active_interface()] = rtypes::timestep(0);
    }
  }

  void abort_prob_update(void) {
    if (kAbortSrcExec == mc_abort_src) {
      m_abort_prob.calc(m_exec_time, m_exec_estimate);
      return;
    } else if (kAbortSrcInterface == mc_abort_src) {
      if (-1 != active_interface()) {
        m_abort_prob.calc(m_interface_times[active_interface()],
                          m_interface_estimates[active_interface()]);
        return;
      }
    } else {
      ER_FATAL_SENTINEL("Bad abort source '%s'", mc_abort_src.c_str());
    }
  }

  rtypes::timestep exec_time_update(void) {
    return m_exec_time = current_time() - m_exec_start_time;
  }

  void exec_time_reset(void) {
    m_last_exec_time = m_exec_time;
    m_exec_start_time = current_time();
  }

  void interface_estimate_update(size_t i, const rtypes::timestep& last_measure) {
    m_interface_estimates[i](last_measure.v());
  }

  void exec_estimate_update(const rtypes::timestep& last_measure) {
    m_exec_estimate(last_measure.v());
  }

  void exec_estimate_init(const rtypes::timestep& init_measure) {
    m_exec_estimate.eval(init_measure.v());
  }

  virtual void task_execute(void) = 0;

  virtual double abort_prob_calc(void) = 0;

  virtual void active_interface_update(int i) = 0;

  rtypes::timestep interface_time(size_t i) const {
    ER_ASSERT(i <= kMAX_INTERFACES,
              "Bad interface ID %zu for task %s",
              i,
              name().c_str());
    return m_interface_times[i];
  }

  double abort_prob(void) const { return m_abort_prob.v(); }

  rtypes::timestep exec_time(void) const { return m_exec_time; }

  bool is_atomic(void) const { return m_is_atomic; }

  void set_atomic(bool b) { m_is_atomic = b; }

  bool is_partitionable(void) const { return m_is_partitionable; }

  void set_partitionable(bool b) { m_is_partitionable = b; }

  void task_aborted(bool task_aborted) { m_task_aborted = task_aborted; }

  void task_exec_count_inc(void) { ++m_exec_count; }

  size_t task_exec_count(void) const { return m_exec_count; }

 protected:
  virtual rtypes::timestep
  interface_time_calc(size_t i, const rtypes::timestep& start_time) = 0;

  virtual rtypes::timestep current_time(void) const = 0;

  void interface_time_mark_finish(size_t i) {
    ER_ASSERT(i <= kMAX_INTERFACES,
              "Bad interface ID %zu for task %s",
              i,
              name().c_str());
    m_last_interface_times[i] = m_interface_times[i];
  }

  void interface_time_mark_start(size_t i) {
    ER_ASSERT(i <= kMAX_INTERFACES,
              "Bad interface ID %zu for task %s",
              i,
              name().c_str());
    m_interface_start_times[i] = current_time();
  }

  bool interface_in_prog(size_t i) const { return m_interface_in_prog[i]; }

  void interface_enter(size_t i) {
    ER_ASSERT(i <= kMAX_INTERFACES,
              "Bad interface ID %zu for task %s",
              i,
              name().c_str());
    m_interface_in_prog[i] = true;
    last_active_interface_reset();
  }

  void interface_exit(size_t i) {
    ER_ASSERT(i <= kMAX_INTERFACES,
              "Bad interface ID %zu for task %s",
              i,
              name().c_str());
    m_interface_in_prog[i] = false;
    m_last_active_interface = i;
  }

 private:
  void last_active_interface_reset(void) { m_last_active_interface = -1; }

  /* clang-format off */
  const std::string             mc_abort_src;

  bool                          m_is_atomic{false};
  bool                          m_is_partitionable{false};
  std::vector<bool>             m_interface_in_prog;
  int                           m_last_active_interface{-1};
  size_t                        m_exec_count{0};

  std::vector<rtypes::timestep> m_interface_times;
  std::vector<rtypes::timestep> m_last_interface_times;
  std::vector<rtypes::timestep> m_interface_start_times;
  std::vector<time_estimate>    m_interface_estimates;

  rtypes::timestep              m_exec_time{0};
  rtypes::timestep              m_last_exec_time{0};
  rtypes::timestep              m_exec_start_time{0};
  time_estimate                 m_exec_estimate;

  bool                          m_task_aborted{false};
  abort_probability             m_abort_prob;
  /* clang-format on */
};

} /* namespace cosm::ta */