活动对象----active object

一.preface

近期学习QPC框架,其核心之一就是 actvie-object,活动对象的出现是为了解决并发(阻塞、数据竞争)问题,笔者这里做一篇笔记,方便日后回顾。



二.What is "active object"

QP/C框架:活动对象基础框架+活动对象应用程序,让每一个线程函数都作为一个事件循环。

每一个活动对象等待事件时是阻塞的,处理事件时不允许有任何一个等待操作(例如:OSDelay、等待信号量、等待一个资源),各个线程间的通信采用消息队列进行异步通信,读到消息就立即处理。

点击查看代码
while(1)
{
  Event e = getEvent();  //阻塞等待一个事件
  dispatch(e);           //处理事件(QEP状态机)
}

通信方式又分为两种: * 直接事件派发 ---- 一对一 * 发布订阅机制 ---- 一对多

活动对象的基础框架包括三部分:

  • 活动对象的抽象:活动对象基类(本篇讲述重点)
  • 活动对象接口:活动对象的构造函数,start函数等
  • 相关基础服务: 事件的发布订阅、直接派发,事件回收,事件服务,动态分配等。

活动对象应用程序: >* 由用户实现的事件处理函数

活动对象的组成抽象



active_obj抽象代码如下

点击查看代码
typedef struct Active Active; 

typedef void (*DispatchHandler)(Active * const me, Event const * const e);  //当前处理哪一个活动对象,当前的事件是什么

/* Active Object base class */
struct Active {
    INT8U thread;     /* private thread (the unique uC/OS-II task priority), 相当于线程句柄 */
    OS_EVENT *queue;  /* private message queue */

    DispatchHandler dispatch; /* pointer to the dispatch() function */

    /* active object data added in subclasses of Active */
};

举例---LED活动对象

LED需要一个状态变量来记录LED的状态

点击查看代码
typedef struct Blinke{
    Active super; //active obj class obj
    bool isLedOn;//private data;
}Blinky;

//模块内部使用
static Blinky Blinky_instance;

//模块外部使用 
Active *const AO_Blinky = &Blinky_inst.super;    //保证了私有数据的安全

/*event base class*/
typedef struct{
    Signal sig; /*event signal*/
    /*event parameters added in subclasses of Event*/
}Event;

void Blinky_handler(Active *const me, Event *e){
  switch(e->sig){
  case TIMEOUT_SIG:
    if( ((Blinky *)me)->isLedOn == true )    //模块内部可以通过显示类型转换获得私有数据
    {
        BSP_ledOff();
        *((Blinky *)me)->isLedOn = false; 
    }
    else
    {
        BSP_ledOn();
        *((Blinky *)me)->isLedOn = true; 
    }
    break;
  default:
    //error
  }
}




三. 事件处理函数的状态机实现

点击查看代码
void Blinky_handler(Active *const me, Event *e){
  static enum{
      INIT,
      ON,
      OFF,
  }  state = INIT;
  switch(state){
  case ON:
      switch(e->sig){
      
      }
      break;
  case OFF:
      switch(e->sig){
      
      }
      break;
  default:
    //error
  }
}
但是代码结构并不美观,所以引入层次状态机
posted @   Charles_hui  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
历史上的今天:
2024-01-01 linux设备树概要
点击右上角即可分享
微信分享提示