遷移コードのインライン化

CG::Class::ComplexityForInlining プロパティーは、ユーザー・コード内のインライン化できる行数の上限を指定します。デフォルトは、3 です。

このタスクについて

ユーザー・コードは、ステートチャートの遷移のアクション部分です。例えば、値 3 を使用すると、3 行以下のコードから成るアクションを含むすべての遷移が呼び出し元関数に自動的にインライン化されます。

インライン化では、生成されたコード内の関数呼び出しを、関数の本体を構成する実際のコード・ステートメントで置き換えます。この方法により、 コード・サイズは若干増加しますが、コード実行の最適化が図れます。例えば、インライン化できる行数を 3 から 5 に増やすことで、コード実行時間が 10 % までも短縮しました。

例えば、HomeHeatingSystem オブジェクトのステートチャートでは、systemControl 状態には、タイムアウトに関するアウト遷移があり、以下のアクション部分が含まれます。

if(IS_IN(&me->theFurnace,Furnace_starting))
   RiCGEN(&me->theFurnace,motorReady());

このアクションでは、Furnace が開始中の状態である場合に、HomeHeatingSystem から FurnacemotorReady() イベントが送られます。

ComplexityForInlining プロパティーが 0 (デフォルト値) に設定されている場合、以下のように HomeHeatingSystem オブジェクトの systemControl 状態の takeEvent() 操作で遷移コードが生成されます。

int HomeHeatingSystem_systemControl_takeEvent(
HomeHeatingSystem* const me, short id) {
    int res = eventNotConsumed;
    if(id == Timeout_id)
    {
      if(RiCTimeout_getTimeoutId((RiCTimeout*)
         me->ric_reactive.current_event) ==
            HomeHeatingSystem_Timeout_systemControl_id)
      {
         NOTIFY_TRANSITION_STARTED(me,HomeHeatingSystem,
            "1");
         HomeHeatingSystem_systemControl_exit(me);
         {
            /*#[ transition 1 */
            if(IS_IN(&me->theFurnace,Furnace_starting))
               RiCGEN(&me->theFurnace, motorReady());
            /*#]*/
         }
         systemControl_entDef(me);
         NOTIFY_TRANSITION_TERMINATED(me,
            HomeHeatingSystem,"1");
         res = eventConsumed;
      }
   }
   return res;
}

HomeHeatingSystem オブジェクトの rootStatedispatchEvent() 操作は、以下のように takeEvent() 操作を呼び出します。

static int rootState_dispatchEvent(
   void * const void_me, short id) {
   HomeHeatingSystem * const me =
      (HomeHeatingSystem *)void_me;
      int res = eventNotConsumed;
      switch (me->rootState_active) {
         case HomeHeatingSystem_systemControl:
         {
            res =
               HomeHeatingSystem_systemControl_takeEvent(
                  me, id);
            break;
         };
      default:
         break;
   };
   return res;
}

ただし、例えば、アクション・コードが 3 行未満であるために、ComplexityForInlining3 に設定されている場合、以下のように rootStatedispatchEvent() 操作に直接にアクション・コードが生成され、takeEvent() 呼び出しを置き換えます。

static int rootState_dispatchEvent(void * const void_me,
   short  id) {
   HomeHeatingSystem * const me = (HomeHeatingSystem *)
      void_me;
   int res = eventNotConsumed;
   switch (me->rootState_active) {
      case HomeHeatingSystem_systemControl:
      {
         if(id == Timeout_id)
         {
            if(RiCTimeout_getTimeoutId(
               (RiCTimeout*) me
               ->ric_reactive.current_event) == 
               HomeHeatingSystem_Timeout_systemControl_id)
            {
            NOTIFY_TRANSITION_STARTED(me,HomeHeatingSystem,
               "1");
            RiCTask_unschedTm(me->ric_reactive.myTask,
               HomeHeatingSystem_Timeout_systemControl_id,
               &me->ric_reactive);
            NOTIFY_STATE_EXITED(me,HomeHeatingSystem,
               "ROOT.systemControl");
            {
               /*#[ transition 1 */
               if(IS_IN(&me->theFurnace, Furnace_starting))
                  RiCGEN(&me->theFurnace,motorReady());
               /*#]*/
            }
         }
         /* rest of dispatchEvent() */
}

フィードバック