/*
 * AXFIrqSignal.cpp
 */

#include "AXFIrqSignal.hpp"
#include "AXFObjectName.hpp"
#include "AXFConditionVariableInternal.hpp"
#include "AXFTask.hpp"
#include "AXFMailboxInternal.hpp"
#include "AXFStage.hpp"
#include "AXFTimerInternal.hpp"

AXFIrqSignal::AXFIrqSignal(AXFObjectName& name, AXFEvent_t evnetId,
                           AXFConditionVariableInternal* cond, AXFTask* task)
    : m_name(name),
      m_eventId(evnetId),
      m_cond(cond),
      m_thread(task),
      m_mailbox(NULL),
      m_isInited(false),
      m_isActive(false) {

  if (cond == NULL) {
    m_cond = new (std::nothrow) AXFConditionVariableInternal();
  }
  if (task == NULL) {
    m_thread = new (std::nothrow) AXFTask();
  }
}

AXFIrqSignal::~AXFIrqSignal() {
  m_isActive = false;
  if (m_cond != NULL) {
    m_cond->signal();
  }
  if (m_thread != NULL) {
    m_thread->join();
  }
  delete m_thread;
  m_thread = NULL;
  delete m_cond;
  m_cond = NULL;
}

bool AXFIrqSignal::create() {
  std::ostringstream eventIdStr;

  //@UTIGN new
  if (m_cond == NULL) {
    goto err;
  }
  if (AXFConditionVariableInternal::COND_SUCCESS != m_cond->init()) {
    goto err_cond;
  }

  //@UTIGN new
  if (NULL == m_thread) {
    goto err_cond_act;
  }
  m_isActive = true;
  eventIdStr << m_eventId;
  if (AXFTask::TASK_SUCCESS
      != m_thread->create(m_name.getActorName() + eventIdStr.str(),
                          AXFTask::AXF_PRIORITY_HIGH_DEFAULT, 1024,
                          &AXFIrqSignal::do_worker, this)) {
    goto err_task;
  }

  AXFStageActorInfo* actorInfo;
  if (0 > AXFStage::getInstance()->getActorInfo(m_name, &actorInfo)) {
    goto err_task_act;
  }
  m_mailbox = actorInfo->mailRef;

  m_isInited = true;
  return true;

  /* task開始以降失敗時 */
  err_task_act: m_isActive = false;
  m_cond->signal();
  m_thread->join();

  /* task開始失敗時 */
  err_task: m_isActive = false;
  delete m_thread;
  m_thread = NULL;

  err_cond_act: ;

  err_cond: delete m_cond;
  m_cond = NULL;

  err: return false;
}

bool AXFIrqSignal::signal() {
  if (false == m_isInited) {
    return false;
  }

  if (AXFConditionVariableInternal::COND_SUCCESS != m_cond->signal()) {
    return false;
  }
  return true;
}

void* AXFIrqSignal::do_worker_sub() {
  AXFTimerInternal::maskTimerSignal();

  while (m_isActive) {
    if (AXFConditionVariableInternal::COND_SUCCESS != m_cond->wait()) {
      return NULL;
    }

    if (false == m_isActive) {
      break;
    }

    if (0 > m_mailbox->send(m_eventId, NULL, 0)) {
      continue;
    }
  }

  if (m_thread != NULL) {
    m_thread->exitSelf();
  }
  //@UTIGN exitSelf
  return NULL;
}
