事件标志

XWOS的事件标志

概述

当系统需要处理很多事件,如果每个事件都绑定一个特定的条件量, 每个条件量又由一个线程进行等待处理,会导致系统需要大量内存来创建条件量和线程。

事件标志使用位图来管理一组事件,位图中的每个位代表一个事件, 当一个或多个事件状态发生变化时,事件对应的位也会发生变化,并唤醒正在等待的线程。 线程唤醒后,就可从事件位图中获取事件的状态。

  • 线程可以等待位图中的事件位被置 1 ,也可以等待事件位被清 0
  • 线程可以等待位图中的事件位同时被置 1 (事件与事件之间是逻辑 的关系),也可以等待其中任意一个位被置 1 (事件与事件之间是逻辑 的关系)。
  • 线程可以等待位图中的事件位同时被清 0 (事件与事件之间是逻辑 的关系),也可以等待其中任意一个位被清 0 (事件与事件之间是逻辑 的关系)。
  • 线程可以选择是否 消费 事件。 消费 事件是指,当事件到来,线程被唤醒时,可以选择是否 清除 事件。
  • 线程可以等待事件标志位发生 翻转翻转 是指事件标志位由 1 变为 0 ,或由 0 变为 1

事件标志对象与对象描述符描述符

事件标志对象是 XWOS对象 struct xwos_object 的派生类 。 类似的,事件标志对象也用 事件标志对象描述符 xwos_flg_d 来解决有效性和身份合法性的问题。

事件标志对象描述符由 事件标志对象的指针标签 组成:

typedef struct {
        struct xwos_flg * flg; /**< 事件标志对象的指针 */
        xwsq_t tik; /**< 标签 */
} xwos_flg_d;

通过对象描述符引用对象时,首先检测 obj->magic 的值,是否为 0x58574F53U ,由此可确定指针 obj 指向一个有效的 XWOS的对象 。 然后对比标签 obj->tiktik 是否相等,由此可以确定对象的 身份 。 因为对象的 tik 是全局唯一的,当对象被释放后,它的 tik 会被析构函数析构为 0 。 当内存地址被重新构建为新的对象,那么它的 tik 一定与对象描述符的 tik 不一致。

事件标志的初始化、销毁与动态创建、删除

静态初始化、销毁

  • 静态初始化: xwos_flg_init()
    • 静态 是指用户预先定义线程结构体对象,这些对象在编译期由编译器分配内存。
  • 销毁静态初始化的事件标志 xwos_flg_fini()

动态创建、删除

  • 动态创建: xwos_flg_create()
    • 动态 是指程序在运行时,通过内存分配函数申请内存,并在申请的内存上构造对象。
  • 删除动态创建的事件标志 xwos_flg_delete()

产生事件

XWOS提供6个CAPI产生触发事件:

  • xwos_flg_s1m() :同时设置多个事件标志位,可在 任意 上下文使用
  • xwos_flg_s1i() :设置单个事件标志位,可在 任意 上下文使用
  • xwos_flg_c0m() :同时清除多个事件标志位,可在 任意 上下文使用
  • xwos_flg_c0i() :清除单个事件标志位,可在 任意 上下文使用
  • xwos_flg_x1m() :同时翻转多个事件标志位,可在 任意 上下文使用
  • xwos_flg_x1i() :翻转单个事件标志位,可在 任意 上下文使用

这些CAPI除了会修改事件标志位图的状态,还会通过 广播 唤醒所有正在等待的线程。 然后,线程通过比对位图状态,确定事件是否已经满足触发条件。 若满足触发条件,就退出等待;若未满足触发条件,重新进入阻塞等待状态。

获取事件的状态

等待事件

触发条件

当调用等待事件的CAPI时,需要指定触发条件(参数: trigger )。触发条件分为 电平触发边沿触发

电平触发

电平触发 源于数字电路,是一种类比概念,是指事件位的特定的状态( 10 )所产生的触发信号,下面的触发条件均为电平触发:

边沿触发

边沿触发 源于数字电路,是一种类比概念,是指事件状态发生改变( 1001 )时产生的唤醒信号,下面的触发条件为边沿触发:

边沿触发时,必须要有一个初始状态,就像数字电路一样:

  • 当位的初始值为 0 (低电平),然后跳变到 1 (高电平)的瞬间被称为上升沿。此时触发的事件被称为上升沿触发。
  • 当位的初始值为 1 (高电平),然后跳变到 0 (低电平)的瞬间被称为下降沿。此时触发的事件被称为下降沿触发。

清除事件

  • 当采用 电平触发 时,需要在读取事件位图后 清除 事件标志位,否则事件会一直处于触发状态。 可以在调用CAPI时,指定参数 actionXWOS_FLG_ACTION_CONSUMPTION清除 的含义是:
    • 当线程等待的是位图中的事件位被置 1清除 是指将这些位清 0
    • 当线程等待的是位图中的事件位被清 0清除 是指将这些位置 1
  • 当采用 边沿触发 时,不需要 清除 事件的触发条件。

绑定与解绑信号选择器

可以通过 xwos_flg_bind() 将事件标志绑定到 信号选择器 上。 当等待的事件发生时,事件标志会向 信号选择器 发送一个 选择信号 。此时 信号选择器 会唤醒正在等待的线程。

绑定后的事件标志可以通过 xwos_flg_unbind() 解绑。

事件标志对象的生命周期管理

事件标志对象的基类是 XWOS对象 struct xwos_object 。 事件标志对象也有两组生命周期管理的CAPI:

  • 使用 对象指针 访问生命周期管理的CAPI:需要确保调用CAPI时,对象一定是有效的,且不存在 释放-又被申请 为另一个对象的情况。

    • xwos_flg_grab() :增加引用计数。
    • xwos_flg_put() :减少引用计数,当引用计数减少为 0 时,调用垃圾回收函数释放对象。
  • 使用 对象描述符 访问生命周期管理的CAPI:用户无法确保对象一定有效或无法确保对象不会变成另一个对象时使用。

    • xwos_flg_acquire() :通过对象描述符确定对象有效且合法,再增加引用计数。
    • xwos_flg_release() :通过对象描述符确定对象有效且合法,再减少引用计数。 当引用计数减少为 0 时,调用垃圾回收函数释放对象。

API参考