快速生成樹之通用狀態機

1 源碼

   rstplib.1.1.02/statmch.c,statmch.h

2 功能

   提供了快速生成樹中所有狀態機的一個抽象,類似於面向對象編程中的基類。

3 代碼簡析

3.1 數據結構

/* 通用狀態機 */

typedef struct state_mach_t {

  struct state_mach_t* next; // 下一狀態機

  Bool          changeState; // 狀態變化標誌

  unsigned int  State; // 當前狀態

  void          (* concreteEnterState) (struct state_mach_t * ); // 執行進入某狀態後的固定動作

  Bool          (* concreteCheckCondition) (struct state_mach_t * ); // 檢查狀態倒換條件並完成狀態倒換

  union {

    struct stpm_t* stpm; // 指向本狀態機所屬網橋

    struct port_t* port; // 指向本狀態機所屬端口

    void  * owner; // 指向本狀態機的創建者,可能是某端口,也可能是某網橋

  } owner;

} STATE_MACH_T;

3.2 核心宏

/* 將某具體狀態機(由WHAT填入狀態機名稱,加##不展開WHAT,參見《宏中"#"和"##"的用法)添加到this下面附帶的狀態機鏈表中,其中this視此宏應用場合不同而定,可能指向端口或網橋*/

#define STP_STATE_MACH_IN_LIST(WHAT)                         /

{                                                                                          /

    STATE_MACH_T* abstr;                                                   /

    /* 創建狀態機,關聯執行函數、檢測函數,登記狀態機屬主(this*/

    abstr = STP_state_mach_create (STP_##WHAT##_enter_state,           /

                                  STP_##WHAT##_check_conditions,                          /

                                  STP_##WHAT##_get_state_name,                          /

                                  this,                                                                            /

                                  #WHAT);                                                                    /

    abstr->next = this->machines;  /

    this->machines = abstr;       / // 通過指針修改將此狀態機加入狀態機鏈表

    this->WHAT = abstr;         / // 更新this的具體狀態機指針指向此狀態機

}

3.3 實現

/* 創建狀態機 */

STATE_MACH_T * STP_state_mach_create (void (*concreteEnterState) (STATE_MACH_T*),

                       Bool (*concreteCheckCondition) (STATE_MACH_T*),

                       char *(*concreteGetStatName) (int),

                       void *owner, char *name)

{

  STATE_MACH_T *this;

  STP_MALLOC(this, STATE_MACH_T, "state machine");  // 分配內存空間

  this->State = BEGIN;

  /* 複製狀態機名稱字符串,所需空間由malloc()分配且可以由free()釋放 strdup() */

  this->name = (char*) strdup (name); 

  this->changeState = False;

  /* 關聯狀態機對應的具體函數 */

  this->concreteEnterState = concreteEnterState;

  this->concreteCheckCondition = concreteCheckCondition;

  this->concreteGetStatName = concreteGetStatName ;

  /* 登記屬主 */

  this->owner.owner = owner;

  return this;

}

/* 刪除狀態機 */

void STP_state_mach_delete (STATE_MACH_T *this)

{

  free (this->name); // 釋放狀態機名稱字符串所佔空間

  STP_FREE(this, "state machine"); // 釋放狀態機空間

}

/* 檢查倒換條件 */

Bool STP_check_condition (STATE_MACH_T* this)

{

  Bool bret;

  bret = (*(this->concreteCheckCondition)) (this); // 調用具體檢查倒換函數

  if (bret) {

    this->changeState = True; // 狀態有變

  }

  return bret;

}

/* 狀態機更新,在生成樹更新函數中被調用 */

Bool STP_change_state (STATE_MACH_T* this)

{

  register int number_of_loops;

  for (number_of_loops = 0; ; number_of_loops++) {

    if (! this->changeState) return number_of_loops; // 狀態無變化則返回

    (*(this->concreteEnterState)) (this); // 進入當前態,執行對應動作

    this->changeState = False; // 復位狀態變化標誌

    STP_check_condition (this); // 檢查倒換條件並執行倒換,更新狀態變化標誌

  }

  return number_of_loops;

}

/* 狀態機狀態倒換 */

Bool STP_hop_2_state (STATE_MACH_T* this, unsigned int new_state)

{

  this->State = new_state;  // 更新狀態

  this->changeState = True; // 置位狀態倒換標誌

  return True;

}

4 網橋、端口、狀態機關係圖

RSTP-generic_state_machine

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章