/**
 * @file   AXFCommSendInternal.hpp
 * @brief  AXFCommSendInternalクラスヘッダ
 *
 * @par    Programming Language
 *         C++
 */

#ifndef AXFCOMMSEND_HPP_
#define AXFCOMMSEND_HPP_

#include "AXFCommInternal.hpp"

class AXFTask;
class AXFMailboxInternal;
class AXFObjectName;
class AXFMutex;

/**
 * @class AXFCommSendInternal
 * @brief プロセス間・CPU間通信用の送信スレッド機能を提供する
 *
 * @n     送信専用のスレッド・コンテキスト上で送信データを共有メモリへ書き込み、
 * @n     書き込み完了待ち状態時は送信要求データをキューイングする。
 */
class AXFCommSendInternal {
  char* m_sendBuf;
  char* m_rcvBuf;
  AXFMutex* m_mutex;
  AXFMailboxInternal* m_mailbox;
  AXFCommInternal* m_comm;
  AXFTask* m_thread;
  volatile bool m_isActive;

 public:
  /** @enum  axcommSendStatus
   *  @brief axcommSendStatus実行完了状態
   */
  enum axcommSendStatus {
    AXCOMMSEND_SUCCESS = 0,        ///< 正常終了
    AXCOMMSEND_ERROR,              ///< 異常終了
    AXCOMMSEND_ERROR_PARAM,        ///< 異常パラメータ
    AXCOMMSEND_ERROR_NEW,          ///< new失敗
    AXCOMMSEND_ERROR_INIT_MUTEX,  ///< AXFMutex初期化エラー
    AXCOMMSEND_ERROR_INIT_MAILBOX,  ///< AXFMailbox初期化エラー
    AXCOMMSEND_ERROR_INIT_AXCOMM,  ///< AXFComm初期化エラー
    AXCOMMSEND_ERROR_INIT_TASK,    ///< AXFTask初期化エラー
  };

  /**
   * @brief AXFCommSendInternalコンストラクタ
   */
  AXFCommSendInternal(char* sendBuf, char* rcvBuf, AXFMutex* mutex,
                      AXFMailboxInternal* mailbox, AXFCommInternal* comm,
                      AXFTask* thread);

  /**
   * @brief AXFCommSendInternalデストラクタ
   */
  virtual ~AXFCommSendInternal();

  /*
   * @brief 初期化
   * @param [in] type AXCommタイプ
   * @return AXFCommSendInternal初期化状況
   */
  axcommSendStatus init(AXComm_t type);

  /*
   * @brief 終了
   * @return AXFCommSendInternal終了状況
   */
  axcommSendStatus join();

  /**
   * @brief タスクにキャンセル要求する。
   */
  axcommSendStatus cancel();

  /**
   * @brief 送信処理を行う
   * @n
   * @n     詳細はAXFActorクラスの記述を参照
   * @n
   * @param [in] name 送信宛アクタ名
   * @param [in] eventId イベント
   * @param [in] data 送信データ
   * @param [in] size 送信データサイズ
   * @return 送信完了データサイズ(送信失敗時は 0 未満の値を返す)
   */
  int send(AXFObjectName& name, AXFEvent_t eventId, void* data, int size);

 private:
  // インスタンスのコピーは想定しない(Klockwork指摘対応:CL.FFM.ASSIGN)
  AXFCommSendInternal& operator=(const AXFCommSendInternal&) {
    return *this;
  }

  // インスタンスのコピーは想定しない(Klockwork指摘対応:CL.FFM.COPY)
  AXFCommSendInternal(const AXFCommSendInternal& obj)
      : m_sendBuf(obj.m_sendBuf),
        m_mutex(obj.m_mutex),
        m_mailbox(obj.m_mailbox),
        m_comm(obj.m_comm),
        m_thread(obj.m_thread),
        m_isActive(obj.m_isActive) {
  }

  void *do_worker_sub();

  static void *do_worker(void *obj) {
    AXFCommSendInternal *fCommSend =
        reinterpret_cast<AXFCommSendInternal *>(obj);
    return fCommSend->do_worker_sub();
  }
};

#endif /* AXFCOMMSEND_HPP_ */

