快速生成树之通用状态机

来源:互联网 发布:sql server 表别名 编辑:程序博客网 时间:2024/05/29 10:56

1 源码

   rstplib.1.1.02/statmch.c,statmch.h

2 功能

   提供了快速生成树中所有状态机的一个抽象,类似于面向对象编程中的基类。

3 代码简析

3.1 数据结构

/* 通用状态机 */

typedefstruct 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视此宏应用场合不同而定,可能指向端口或网桥*/

#defineSTP_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, "statemachine");  // 分配内存空间

  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) returnnumber_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

 

 

 

 

原创粉丝点击