TuyaOS
事件

涂鸦TuyaOS Event是一个轻量级的事件通知库。其特点是:

  • 支持订阅-发布模式的事件机制,使用非常简单方便,可以在任意位置、任意时间进行时间的订阅;
  • 轻量级,专注于进程内部的事件通知,代码小巧,仅400行。
  • 跨平台,基于涂鸦TuyaOS的跨平台特性,可以在任意平台上运行。
  • 有弹性,默认情况下,事件是同步调用,基于涂鸦TuyaOS的跨平台特性,可以在订阅函数里使用Work Queue实现多线程的异步机制。

接口描述

发布事件

发布一个事件通知,包含了事件的数据,告知所有订阅者进行处理。事件发布首先会去搜索是否当前事件是否已经创建。

  • 没有被创建:说明之前并没有发布过相同的事件,但是可能会存在订阅者,由于他们没有找到事件,会被暂存到free_subscribe_root。因此需要从free_subscribe_root里查找是否有该事件的订阅者,如果有则把这些订阅者从free_subscribe_root里拿出来,挂载到事件的subscribe_root,然后再进行事件的发布。
  • 已经被创建:说之前已经有发布过相同的事件,所有的订阅者都已经被正常处理,不需要再关心是否有订阅者在free_subscribe_root中,可以直接进行事件发布。
  • 事件发布,遍历事件subscribe_root,对于每个订阅者,发布事件的数据,调用订阅者的回调函数,判断并记录回调函数的返回值。
    • 如果不存在订阅者,意味着不需要发布,也不需要创建事件的资源
OPERATE_RET ty_publish_event(CONST CHAR_T* name, VOID_T *data);
OPERATE_RET ty_publish_event(CONST CHAR_T *name, VOID_T *data)
: publish event

订阅事件

关注一个事件,包含了事件的名称、关注的用途以及处理数据的回调函数。事件订阅首先会去搜索是否当前事件是否已经创建。

  • 没有被创建:说明此事件没有产生过,需要把订阅者暂存到free_subscribe_root
  • 已经被创建:说明此时间已经产生过,可以直接把订阅者挂载到事件的subscribe_root

可以订阅的事件分为3种,可以按照实际需求选择:

  • SUBSCRIBE_TYPE_NORMAL, 普通订阅,按照顺序处理
  • SUBSCRIBE_TYPE_EMERGENCY,紧急订阅,优先处理
  • SUBSCRIBE_TYPE_ONETIME,一次性订阅,处理一次即取消

订阅事件不会拿到事件的上一次状态,一个原因是如果暂存数据会消耗较大的资源,另外一个原因是没有必要。

OPERATE_RET ty_subscribe_event(CONST CHAR_T *name, CONST CHAR_T *desc, CONST EVENT_SUBSCRIBE_CB cb, SUBSCRIBE_TYPE_E type);
OPERATE_RET ty_subscribe_event(CONST CHAR_T *name, CONST CHAR_T *desc, CONST EVENT_SUBSCRIBE_CB cb, SUBSCRIBE_TYPE_E type)
: subscribe event
BYTE_T SUBSCRIBE_TYPE_E
subscriber type
Definition: base_event.h:42
INT_T(* EVENT_SUBSCRIBE_CB)(VOID_T *data)
event subscribe callback function type
Definition: base_event.h:61

取消订阅

取消关注一个事件,包含了事件的名称、关注的用途以及处理数据的回调函数。如果当前订阅者没有绑定事件,则从free_subscribe_root移除;

如果订阅者绑定了事件,且为最后一个订阅者,则需要从事件的subscribe_root移除,并销毁该事件。否则,仅从事件的subscribe_root中移除订阅者。

OPERATE_RET ty_unsubscribe_event(CONST CHAR_T *name, CONST CHAR_T *desc, EVENT_SUBSCRIBE_CB cb);
OPERATE_RET ty_unsubscribe_event(CONST CHAR_T *name, CONST CHAR_T *desc, EVENT_SUBSCRIBE_CB cb)
: unsubscribe event

示例代码

#define EVENT_SAMPLE "publish.sample"
OPERATE_RET sample_subcribe_cb(event_data_t *raw_data)
{
event_data_t *data = (event_data_t*)raw_data;
TAL_PR_DEBUG("recv event");
return OPRT_OK;
}
OPERATE_RET sample_subcribe_emergence_cb(event_data_t *raw_data)
{
event_data_t *data = (event_data_t*)raw_data;
TAL_PR_DEBUG("recv event emergence");
return OPRT_OK;
}
OPERATE_RET sample_subcribe_onetime_cb(event_data_t *raw_data)
{
event_data_t *data = (event_data_t*)raw_data;
TAL_PR_DEBUG("recv event emergence");
return OPRT_OK;
}
OPERATE_RET sample_event_test()
{
OPERATE_RET rt = OPRT_OK;
// 发布事件EVENT_SAMPLE,没有订阅者,不会创建事件
rt = ty_publish_event(EVENT_SAMPLE, NULL);
EXPECT_EQ(rt, OPRT_OK);
// 订阅事件EVENT_SAMPLE,实际不存在,会暂存
char desc[] = "subscribe.sample";
rt = ty_subscribe_event(EVENT_SAMPLE, desc, sample_subcribe_cb, EVENT_TYPE_NORMAL);
EXPECT_EQ(rt, OPRT_OK);
// 发布事件EVENT_SAMPLE,有订阅者,会处理
rt = ty_publish_event(EVENT_SAMPLE, NULL);
EXPECT_EQ(rt, OPRT_OK);
// 紧急订阅事件EVENT_SAMPLE
rt = ty_subscribe_event(EVENT_SAMPLE, desc, sample_subcribe_emergence_cb, SUBSCRIBE_TYPE_EMERGENCY);
EXPECT_EQ(rt, OPRT_OK);
// 订阅事件一次性事件,一次性事件不需要手动取消订阅,处理之后会自动销毁
rt = ty_subscribe_event(EVENT_SAMPLE, desc, sample_subcribe_onetime_cb, EVENT_TYPE_ONETIME);
EXPECT_EQ(rt, OPRT_OK);
// 发布事件EVENT_SAMPLE
rt = ty_publish_event(EVENT_SAMPLE, NULL);
EXPECT_EQ(rt, OPRT_OK);
// 取消紧急订阅,删除订阅者
rt = ty_unsubscribe_event(EVENT_SAMPLE, desc, sample_subcribe_emergence_cb);
EXPECT_EQ(rt, OPRT_OK);
// 取消订阅,当事件没有订阅者,事件节点EVENT_SAMPLE会自动销毁
rt = ty_unsubscribe_event(EVENT_SAMPLE, desc, sample_subcribe_cb);
EXPECT_EQ(rt, OPRT_OK);
return OPRT_OK;
}