/*
 * AXFTimerTaskInternal.cpp
 */

#include <stdio.h>

#include "AXConfig.hpp"
#include "AXFTimeDomainInternal.hpp"
#include "AXFTimerTaskInternal.hpp"

AXFTimerTaskInternal::AXFTimerTaskInternal(AXFMutex* listMutexPtr, AXFTask* taskPtr, AXFPtrList* simuListPtr)
    : m_baseInited(false),
      m_taskCreated(false),
      m_taskPtr(taskPtr),
      m_taskName(""),
      m_log(m_taskName),
      m_listMutexInited(false),
      m_listMutexPtr(listMutexPtr),
      m_unitIdCnt(1),
      m_simuListPtr(simuListPtr) {
  if (m_taskPtr == NULL) {
    // 通常は m_task を使用する
    m_taskPtr = &m_task;

    // (テスト時に外部から taskPtr を指定すると、そちらを使用する)
  }
  if (m_listMutexPtr == NULL) {
    // 通常は m_listMutex を使用する
    m_listMutexPtr = &m_listMutex;

    // (テスト時に外部から listMutexPtr を指定すると、そちらを使用する)
  }
  if (m_simuListPtr == NULL) {
    // 通常は m_simuList を使用する
    m_simuListPtr = &m_simuList;

    // (テスト時に外部から simuListPtr を指定すると、そちらを使用する)
  }
}

AXFTimerTaskInternal::~AXFTimerTaskInternal() {
  if (m_listMutexInited) {
    delAll();
  }
  if (m_taskCreated) {
    int ret;
    if ((ret = wakeup(TIMERTASK_WAKEUP_QUIT)) != TIMER_TASK_SUCCESS) {

      //@UTIGN mock destructor
      // 先にwakeup()メソッド用のmockのデストラクタが呼び出されるので
      // wakeup() を mockに置き換えれない

      m_log.write(AXFLOG_ERR, "fail wakeup at destructor");
    }
    if (m_taskPtr->join() != AXFTask::TASK_SUCCESS) {
      m_log.write(AXFLOG_ERR, "fail join at destructor");
    }
  }
}

int AXFTimerTaskInternal::initAndCreate(const std::string& name, AXFTask::taskPriority priority, size_t stackSize) {
  int ret;

  if (!m_baseInited) {
    if ((ret = init()) != TIMER_TASK_SUCCESS) {
      return ret; 
    }
    m_baseInited = true;
  }

  if (!m_listMutexInited) {
    // リスト排他処理用のMutexクラスを初期化
    if (m_listMutexPtr->init() != AXFMutex::MUTEX_SUCCESS) {
      return TIMER_TASK_ERROR_INITCREATE_MUTEXINIT;
    }
    m_listMutexInited = true;
  }

  if (m_simuListPtr->init() != AXFPtrList::PTR_LIST_SUCCESS) {
    return TIMER_TASK_ERROR_INITCREATE_SIMULIST_INIT;
  }

  if (m_taskCreated) {
    return TIMER_TASK_ERROR_INITCREATE_ALREADY;
  }

  m_taskName = AXFObjectName(name, AXConfig.getStageNameObject().getStageName());

  // タスク生成
  if (m_taskPtr->create(name, priority, stackSize, do_worker, this) != AXCTask::TASK_SUCCESS) {
    return TIMER_TASK_ERROR_INITCREATE_TASKCREATE;
  }  

  m_taskCreated = true;
  return TIMER_TASK_SUCCESS;
}

int AXFTimerTaskInternal::add(AXFTimerUnitInternal* timer) {

  // イベント通知先Actorについて、TimeDomain処理が必要か記録
  // リスト中にある timer のイベント通知先Actorは、既に処理済なので除外
  bool timeDomainSimu = timer->isTimeDomainActive() && !isExistToActor(timer->getToActor());

  // リストに timer を追加する
  // 既に追加されていたら found に true が設定される

  bool found = false;
  void* args[] = { timer };

  int ret;
  if ((ret = listWork(&AXFTimerTaskInternal::listWorkAdd, &found, args)) < 0) {
    return ret;
  }

  if (found) {
    // 既に追加されていた場合もエラーにしない
    return TIMER_TASK_SUCCESS;
  }

  // リストの更新を タイマ満了を待つタスクに通知
  if ((ret = wakeup(TIMERTASK_WAKEUP_UPDATE_LIST)) != TIMER_TASK_SUCCESS) {
    return ret;
  }

  if (timeDomainSimu) {
    // TimeDomain処理
    simu(timer->getToActor());
  }

  return TIMER_TASK_SUCCESS;
}

int AXFTimerTaskInternal::del(AXFTimerUnitInternal* timer) {

  // リストから timer を削除する
  // リスト中のタイマを削除したら found に true が設定される

  bool found = false;
  void* args[] = { timer };

  int ret;
  if ((ret = listWork(&AXFTimerTaskInternal::listWorkDel, &found, args)) != TIMER_TASK_SUCCESS) {
    return ret;
  }
  if (!found) {
    // 見つからなかった場合もエラーにしない
    return TIMER_TASK_SUCCESS;
  }

  if ((ret = wakeup(TIMERTASK_WAKEUP_UPDATE_LIST)) != TIMER_TASK_SUCCESS) {
    return ret;
  }
  return TIMER_TASK_SUCCESS;
}

int AXFTimerTaskInternal::del(AXFObjectName& name, bool andDeleteObject) {

  // リストから名前が name に一致するものを全て削除する
  // リスト中のタイマを削除したら found に true が設定される

  bool found = false;
  void* args[] = { &name, &andDeleteObject };

  int ret;
  if ((ret = listWork(&AXFTimerTaskInternal::listWorkDelByName, &found, args)) != TIMER_TASK_SUCCESS) {
    return ret;
  }
  if (!found) {
    // 見つからなかった場合もエラーにしない
    return TIMER_TASK_SUCCESS;
  }

  // リストの更新を タイマ満了を待つタスクに通知
  if ((ret = wakeup(TIMERTASK_WAKEUP_UPDATE_LIST)) != TIMER_TASK_SUCCESS) {
    return ret;
  }
  return TIMER_TASK_SUCCESS;
}

void AXFTimerTaskInternal::delAll(bool andDeleteObject) {

  // リストのタイマを全て削除する
  // リスト中のタイマを削除したら found に true が設定される

  bool found = false;
  void* args[] = { &andDeleteObject };

  int ret;
  if ((ret = listWork(&AXFTimerTaskInternal::listWorkDelAll, &found, args)) != TIMER_TASK_SUCCESS) {
    m_log.write(AXFLOG_ERR, "fail listWork at delAll");
  }
  if (found) {
    // リストの更新を タイマ満了を待つタスクに通知
    if ((ret = wakeup(TIMERTASK_WAKEUP_UPDATE_LIST)) != TIMER_TASK_SUCCESS) {
      m_log.write(AXFLOG_ERR, "fail wakeup at delAll");
    }
  }
}

int AXFTimerTaskInternal::cancel(AXFTimerUnitInternal* timer) {

  // リストに登録されている timer のタイマ設定をキャンセルする
  // リスト中のタイマをキャンセルしたら found に true が設定される

  bool found = false;
  void* args[] = { timer };

  int ret;
  if ((ret = listWork(&AXFTimerTaskInternal::listWorkCancel, &found, args)) != TIMER_TASK_SUCCESS) {
    return ret;
  }
  if (!found) {
    // 見つからなかった場合
    return TIMER_TASK_ERROR_CANCEL_NOTFOUND;
  }
  return TIMER_TASK_SUCCESS;
}

int AXFTimerTaskInternal::cancel(int id, AXFTimerUnitInternal** ret_timer) {

  // リストに登録されているタイマIDが id のタイマ設定をキャンセルする
  // リスト中のタイマをキャンセルしたら found に true が設定される

  bool found = false;
  void* args[] = { &id, ret_timer };

  int ret;
  if ((ret = listWork(&AXFTimerTaskInternal::listWorkCancelById, &found, args)) != TIMER_TASK_SUCCESS) {
    return ret;
  }
  if (!found) {
    // 見つからなかった場合
    return TIMER_TASK_ERROR_CANCEL_NOTFOUND;
  }
  return TIMER_TASK_SUCCESS;
}

int AXFTimerTaskInternal::cancel(AXFObjectName& name) {

  // リスト中の名前が name に一致するタイマの設定をキャンセルする
  // リスト中のタイマをキャンセルしたら found に true が設定される

  void* args[] = { &name };

  int ret;
  if ((ret = listWork(&AXFTimerTaskInternal::listWorkCancelByName, NULL, args)) != TIMER_TASK_SUCCESS) {
    return ret;
  }
  return TIMER_TASK_SUCCESS;
}

int AXFTimerTaskInternal::get(int id, CoreTimeSpec* ret_spec) {

  // リストに登録されている timer のタイマ設定を取得する
  // リスト中のタイマ設定を取得したら found に true が設定される

  bool found = false;
  void* args[] = { &id, ret_spec };

  int ret;
  if ((ret = listWork(&AXFTimerTaskInternal::listWorkGet, &found, args)) != TIMER_TASK_SUCCESS) {
    return ret;
  }
  if (!found) {
    // 見つからなかった場合
    // 単発タイマで満了して破棄された可能性がある
    return TIMER_TASK_ERROR_GET_NOTFOUND;
  }
  return TIMER_TASK_SUCCESS;
}

bool AXFTimerTaskInternal::isTimeDomainActive() {
#ifdef	UNUSE_CHRONO	// baba TimeDomainは現状非対応
	return false;
#else	/* UNUSE_CHRONO */
  return AXFStage::m_timeDomain && AXFStage::m_timeDomain->isActive();
#endif	/* UNUSE_CHRONO */
}

#ifndef	UNUSE_CHRONO	// baba TimeDomainは現状非対応
void AXFTimerTaskInternal::timeDomainSwitched() {
  int ret;

  m_simuListPtr->delAll();

  if (isTimeDomainActive()) {
    // timeDomain開始時

    m_simuStartChrono.getSystemTime();

    // 保持してる一覧の toActor を重複なく toActorList にまとめて
    AXFPtrList toActorList;
    if ((ret = getListToActor(toActorList)) != TIMER_TASK_SUCCESS) {
      m_log.write(AXFLOG_ERR, "fail getListToActor at timeDomainSwitched");
      return;
    }
	
    // toActorList に simu event を送信
    AXFPtrList::iterator it = toActorList.begin();
    while (it != toActorList.end()) {
      AXFActor* toActor = (AXFActor*)*it++;
      sendSimuEvent(toActor, m_log);
    }
  }

  if ((ret = wakeup(TIMERTASK_WAKEUP_UPDATE_TIME)) != TIMER_TASK_SUCCESS) {
    m_log.write(AXFLOG_ERR, "fail wakeup update time at timeDomainSwitched");
  }
}
#endif	/* UNUSE_CHRONO */

void AXFTimerTaskInternal::simu(AXFActor* actor) {
  m_simuListPtr->add(actor);

  int ret;
  if ((ret = wakeup(TIMERTASK_WAKEUP_UPDATE_TIME)) != TIMER_TASK_SUCCESS) {
    m_log.write(AXFLOG_ERR, "fail wakeup update time at simu");
  }
}

bool AXFTimerTaskInternal::isExistToActor(AXFActor* toActor) {
  bool found = false;
  void* args[] = { toActor };

  int ret;
  if ((ret = listWork(&AXFTimerTaskInternal::listWorkIsExistToActor, &found, args)) != TIMER_TASK_SUCCESS) {
    m_log.write(AXFLOG_ERR, "fail isExistToActor");
    return false;
  }

  return found;
}

#ifndef	UNUSE_CHRONO	// baba TimeDomainは現状非対応
int AXFTimerTaskInternal::getListToActor(AXFPtrList& ret_list) {
  int ret;
  if ((ret = ret_list.init()) != AXFPtrList::PTR_LIST_SUCCESS) {
    //@UTIGN always success
    // getListToActor は private method で、呼び出し元は timeDomainSwitched() method からのみ
    // 引数で渡される ret_list は、timeDomainSwitched() method 内のローカル変数で
    // 初期化 ret_list.init() は必ず成功する

    return TIMER_TASK_ERROR_GETLISTTOACTOR_LIST_INIT;
  }

  void* args[] = { &ret_list };
  if ((ret = listWork(&AXFTimerTaskInternal::listWorkGetListToActor, NULL, args)) != TIMER_TASK_SUCCESS) {
    return ret;
  }

  return TIMER_TASK_SUCCESS;
}
#endif	/* UNUSE_CHRONO */


// リスト関連の処理汎用のメソッド
// 引数で内部処理用のメソッドとパラメータを指定する

int AXFTimerTaskInternal::listWork(ListMethod method, bool* found, void** args) {

  // リストをロック
  if (m_listMutexPtr->lock() != AXFMutex::MUTEX_SUCCESS) {
    return TIMER_TASK_ERROR_LISTWORK_LOCK;
  }    

  // 引数で指定された method を実行
  int ret;
  if ((ret = (this->*method)(found, args)) != TIMER_TASK_SUCCESS) {
    // 非0の値 (非SUCCESS) はエラーとして扱う

    // リストをアンロック
    if (m_listMutexPtr->unlock() != AXFMutex::MUTEX_SUCCESS) {
      m_log.write(AXFLOG_ERR, "fail unlock at listWork");
    }

    // methodのエラーを返す
    return ret;
  }

  // リストをアンロック
  if (m_listMutexPtr->unlock() != AXFMutex::MUTEX_SUCCESS) {
    return TIMER_TASK_ERROR_LISTWORK_UNLOCK;
  }

  return TIMER_TASK_SUCCESS;
}


// リストへの追加の内部処理
// listWork() 引数指定で渡されるメソッド

int AXFTimerTaskInternal::listWorkAdd(bool* found, void** args) {

  AXFTimerUnitInternal* timer = (AXFTimerUnitInternal*)args[0];
  
  ListIt it;
  int id;

  do {
    // IDは正の値のみ発行する
    if (m_unitIdCnt <= 0) {
      //@UTIGN too many times
      // 呼び出し回数 2G回必要
      m_unitIdCnt = 1;
    }
    id = m_unitIdCnt++;

    it = m_list.begin();
    while (it != m_list.end()) {
      if (*it == timer) {
	*found = true; // 見つけた
	return TIMER_TASK_SUCCESS;
      } else if ((*it)->getId() == id) {
	// IDが既に使用中の場合
	// 次の候補IDで再処理する
	break;
      } else {
	it++;
      }
    }

  } while (it != m_list.end());

  // 見つからなかったので追加する
  // IDの重複もなし
  m_list.push_back(timer);
  timer->setId(id);

  return TIMER_TASK_SUCCESS;
}


// リストからの削除の内部処理
// listWork() 引数指定で渡されるメソッド

int AXFTimerTaskInternal::listWorkDel(bool* found, void** args) {

  AXFTimerUnitInternal* timer = (AXFTimerUnitInternal*)args[0];

  ListIt it = m_list.begin();
  while (it != m_list.end()) {
    if (*it == timer) {
      *found = true; // 見つけた
      m_list.erase(it);
      break;
    } else {
      it++;
    }
  }
  return TIMER_TASK_SUCCESS;
}


// リストからの削除(名前指定)の内部処理
// listWork() 引数指定で渡されるメソッド

int AXFTimerTaskInternal::listWorkDelByName(bool* found, void** args) {

  AXFObjectName& name = *(AXFObjectName*)args[0];
  bool andDeleteObject = *(bool*)args[1];

  ListIt it = m_list.begin();
  while (it != m_list.end()) {
    AXFTimerUnitInternal* timer = *it;
    if (timer->getName().isMatch(name)) {
      *found = true; // 見つけた
      it = m_list.erase(it);
      if (andDeleteObject) {
	delete timer;
      }
    } else {
      it++;
    }
  }
  return TIMER_TASK_SUCCESS;
}


// リストからの削除(全指定)の内部処理
// listWork() 引数指定で渡されるメソッド

int AXFTimerTaskInternal::listWorkDelAll(bool* found, void** args) {

  bool andDeleteObject = *(bool*)args[0];

  ListIt it = m_list.begin();
  while (it != m_list.end()) {
    AXFTimerUnitInternal* timer = *it;
    *found = true; // 削除した
    it = m_list.erase(it);
    if (andDeleteObject) {
      delete timer;
    }
  }    
  return TIMER_TASK_SUCCESS;
}


// リスト中のタイマのキャンセルの内部処理
// listWork() 引数指定で渡されるメソッド

int AXFTimerTaskInternal::listWorkCancel(bool* found, void** args) {

  AXFTimerUnitInternal* timer = (AXFTimerUnitInternal*)args[0];

  ListIt it = m_list.begin();
  while (it != m_list.end()) {
    if (*it == timer) {
      *found = true; // 見つけた
      int ret;
      if ((ret = timer->cancel()) != AXFTimerUnitInternal::TIMER_UNIT_SUCCESS) {
	return TIMER_TASK_ERROR_LISTWORKCANCEL_CANCEL;
      }
      break;
    } else {
      it++;
    }
  }
  return TIMER_TASK_SUCCESS;
}


// リスト中のタイマのキャンセル(ID指定)の内部処理
// listWork() 引数指定で渡されるメソッド

int AXFTimerTaskInternal::listWorkCancelById(bool* found, void** args) {

  int id = *(int*)args[0];
  AXFTimerUnitInternal** ret_timer = (AXFTimerUnitInternal**)args[1];

  AXFTimerUnitInternal* timer = NULL;
  ListIt it = m_list.begin();
  while (it != m_list.end()) {
    timer = *it;
    if (timer->getId() == id) {
      *found = true; // 見つけた
      int ret;
      if ((ret = timer->cancel()) != AXFTimerUnitInternal::TIMER_UNIT_SUCCESS) {
	return TIMER_TASK_ERROR_LISTWORKCANCEL_CANCEL;
      }
      break;
    } else {
      it++;
    }
  }
  if (ret_timer) {
    *ret_timer = timer;
  }
  return TIMER_TASK_SUCCESS;
}


// リスト中のタイマのキャンセル(名前指定)の内部処理
// listWork() 引数指定で渡されるメソッド

int AXFTimerTaskInternal::listWorkCancelByName(bool* found, void** args) {

  AXFObjectName& name = *(AXFObjectName*)args[0];

  ListIt it = m_list.begin();
  while (it != m_list.end()) {
    AXFTimerUnitInternal* timer = *it++;
    if (!timer->getName().isMatch(name)) {
      continue;
    }
    int ret;
    if ((ret = timer->cancel()) != AXFTimerUnitInternal::TIMER_UNIT_SUCCESS) {
      return TIMER_TASK_ERROR_LISTWORKCANCELBYNAME_CANCEL;
    }
  }
  return TIMER_TASK_SUCCESS;
}


// リスト中のタイマの設定取得の内部処理
// listWork() 引数指定で渡されるメソッド

int AXFTimerTaskInternal::listWorkGet(bool* found, void** args) {

  int id = *(int*)args[0];
  CoreTimeSpec* ret_spec = (CoreTimeSpec*)args[1];

  AXFTimerUnitInternal* timer = NULL;
  ListIt it = m_list.begin();
  while (it != m_list.end()) {
    timer = *it;
    if (timer->getId() == id) {
      *found = true; // 見つけた
      int ret;
      if ((ret = timer->get(ret_spec)) != AXFTimerUnitInternal::TIMER_UNIT_SUCCESS) {
	return TIMER_TASK_ERROR_LISTWORKGET_GET;
      }
      break;
    } else {
      it++;
    }
  }
  return TIMER_TASK_SUCCESS;
}


int AXFTimerTaskInternal::listWorkIsExistToActor(bool* found, void** args) {
  AXFActor* toActor = (AXFActor*)args[0];
  AXFTimerUnitInternal* timer = NULL;
  ListIt it = m_list.begin();
  while (it != m_list.end()) {
    timer = *it;
    if (timer->getToActor() == toActor) {
      *found = true; // 見つけた
      break;
    }
    it++;
  }
  return TIMER_TASK_SUCCESS;
}

#ifndef	UNUSE_CHRONO	// baba TimeDomainは現状非対応
int AXFTimerTaskInternal::listWorkGetListToActor(bool* found, void** args) {
  AXFPtrList* ret_list = (AXFPtrList*)args[0];
  AXFTimerUnitInternal* timer = NULL;
  ListIt it = m_list.begin();
  while (it != m_list.end()) {
    timer = *it;
    int ret;
    if (timer->isTimeDomainActive()) {
      if ((ret = ret_list->add(timer->getToActor(), true)) != AXFPtrList::PTR_LIST_SUCCESS) {
	//@UTIGN always success
	// listWorkGetListToActor() の呼び出し元は getListToActor() のみ
	// getListToActor は private method で、呼び出し元は timeDomainSwitched() method からのみ
	// 引数で渡される ret_list は、timeDomainSwitched() method 内のローカル変数で
	// 初期化 ret_list->add() は必ず成功する

	return TIMER_TASK_ERROR_GETLISTTOACTOR_LIST_ADD;
      }
    }
    it++;
  }
  return TIMER_TASK_SUCCESS;
}
#endif	/* UNUSE_CHRONO */

// リスト中のタイマについて待機用の初期化
// listWork() 引数指定で渡されるメソッド

int AXFTimerTaskInternal::listWorkInitWaitTimer(bool* found, void** args) {

  ListIt it = m_list.begin();
  while (it != m_list.end()) {
    AXFTimerUnitInternal* timer = *it++;
    if (timer->isTimeDomainActive()) {
      // TimeDomain有効時
      // このときは何もしない
    } else {
      initWaitTimer(timer);
    }
  }    
  return TIMER_TASK_SUCCESS;
}


// リスト中のタイマの満了判定とイベント送信
// listWork() 引数指定で渡されるメソッド

int AXFTimerTaskInternal::listWorkWorkerSub(bool* found, void** args) {

  bool isTdoffFirst = *(bool*)args[0];

  ListIt it = m_list.begin();
  while (it != m_list.end()) {
    AXFTimerUnitInternal* timer = *it;

    // 満了判定
    if (timer->isTimeDomainActive()) {
      // TimeDomain有効時
      // このときは何もしない
    } else {
      if (!isExpired(timer)) {
	it++;
	continue;
      }
    }

    // 満了回数取得
    int n = timer->getExpNum();
    if (n <= 0) {
      it++;
      continue;
    }

    // TimeDomain無効になってから初回の場合の補正処理
    if (isTdoffFirst) {
      n = timer->getCorrExpNum(n);
    }

    // イベント送信
    int ret, i;
    for (i=0; i < n; i++) {
      if ((ret = timer->sendEvent()) != AXFTimerUnitInternal::TIMER_UNIT_SUCCESS) {
	// エラーを返す
	return TIMER_TASK_ERROR_LISTWORKWORKERSUB_SENDEVENT;
      }
    }

    if (timer->isSingle()) {
      // 単発タイマは満了しイベントを送ったら破棄する

      // タイマオブジェクトのインスタンスを破棄するのは
      // 単発タイマが満了したときのみ

      // リストロック中なので del() は使えない
      // 直接削除する
      it = m_list.erase(it);
      delete timer;
    } else {
      it++;
    }
  }
  return TIMER_TASK_SUCCESS;
}

void AXFTimerTaskInternal::sendSimuEvent(AXFActor* toActor, AXFLog& log) {
  if (toActor->send(toActor->getNameObject(), AXFEVENT_SYS_TIMER_SIMU, NULL, 0) < 0) {
    log.write(AXFLOG_ERR, "fail send simu event");
  }
}


// タスクの実行する関数

void* AXFTimerTaskInternal::do_worker(void* arg) {
  AXFTimerTaskInternal* obj = reinterpret_cast<AXFTimerTaskInternal*>(arg);
  return obj->do_worker_sub();
}


// タスクの実行する関数が呼び出すメソッド

void* AXFTimerTaskInternal::do_worker_sub() {

  // TimeDomain無効になってから初回の場合か判定用
  bool isTdoffFirst = false;

  while (true) {

    // タイマタスク待機用の初期化処理
    initWait();

    // タイマタスク待機用の各タイマについての初期化処理
    int ret;
    if ((ret = listWork(&AXFTimerTaskInternal::listWorkInitWaitTimer, NULL, NULL)) != TIMER_TASK_SUCCESS) {
      m_log.write(AXFLOG_ERR, "fail listWorkInitWaitTimer at do_worker_sub");
      continue;
    }

    // タイマの満了を待機する
    if ((ret = wait()) < 0) {
      m_log.write(AXFLOG_ERR, "fail wait at do_worker_sub");
      continue;
    }
    if (ret == TIMERTASK_WAKEUP_QUIT) {
      // タスク終了処理へ
      break;
    }
    if (ret == TIMERTASK_WAKEUP_UPDATE_LIST) {
      continue;
    }

    // ret == TIMERTASK_WAKEUP_EXPIRE
    // or TIMERTASK_WAKEUP_UPDATE_TIME

    // TimeDomain無効になってから初回の場合か判定
    if (isTdoffFirst) {
      if (ret != TIMERTASK_WAKEUP_EXPIRE) {
	// EXPIREでない場合は無効
	isTdoffFirst = false;
      }
    }

    // 各タイマの満了判定とイベント送信
    void* args[] = { &isTdoffFirst };
    int ret_listWork = listWork(&AXFTimerTaskInternal::listWorkWorkerSub, NULL, args);

    // TimeDomain無効になってから初回の場合か判定
    // 次回の WAKEUP_EXPIRE 時に listWorkWOrkerSub() に渡す
    isTdoffFirst = !isTimeDomainActive() && ret == TIMERTASK_WAKEUP_UPDATE_TIME;

    if (ret_listWork!= TIMER_TASK_SUCCESS) {
      m_log.write(AXFLOG_ERR, "fail listWorkWorkerSub at do_worker_sub");
      continue;
    }

    // TimeDomain用の処理
    if (isTimeDomainActive() && ret == TIMERTASK_WAKEUP_UPDATE_TIME) {

      // ロック
      if (m_simuListPtr->lock() != AXFPtrList::PTR_LIST_SUCCESS) {
	m_log.write(AXFLOG_ERR, "fail lock simuList at do_worker_sub");
      }

      // TimeDomain処理
      if (!m_simuListPtr->empty()) {

	// simuList が空でなければ
	// 先頭を取り出して simu event を送信

	AXFActor* toActor = (AXFActor*)m_simuListPtr->front();
	m_simuListPtr->pop_front();

	if (isExistToActor(toActor)) {
	  sendSimuEvent(toActor, m_log);
	}
      }

      // アンロック
      if (m_simuListPtr->unlock() != AXFPtrList::PTR_LIST_SUCCESS) {
	m_log.write(AXFLOG_ERR, "fail unlock simuList at do_worker_sub");
      }
    }
  }

  m_taskPtr->exitSelf();
  //@UTIGN exitSelf
  return NULL;
}
