XWOS对象
Categories:
少于1分钟
概述
XWOS的内核对象全部继承于 struct xwos_object
。
struct xwos_object {
xwsq_t tik;
xwsq_t magic;
atomic_xwsq_t refcnt;
xwobj_gc_f gcfunc;
};
tik
:对象的标签,是由系统分配的独一无二的整数。此标签即为对象的 身份证ID ;magic
:常数0x58574F53U
,用于确定内存地址是否为 XWOS的对象 ;refcnt
:XWOS的对象使用引用计数法管理生命周期,当对象的引用计数减为0
,会调用gcfunc()
进行垃圾回收;gcfunc
:垃圾回收函数。
按照面向对象的思想, struct xwos_object
应当作为子类对象结构体的第一个成员。 struct xwos_object *
就可强制类型转换为子类对象的指针。
对象描述符
当使用对象指针访问对象时,有可能会出现一种情况: 对象已经被释放,甚至被释放后的内存又被用来构建新的对象。但是对象指针的持有者并不知道这种情况。由此引发各种指针问题。 为了解决这类问题,XWOS引入 对象描述符 。对象描述符 由 对象的指针 和 标签 组成:
typedef struct {
struct xwos_object * obj;
xwsq_t tik;
} xwobj_d;
通过对象描述符引用对象时,首先检测 obj->magic
的值,是否为 0x58574F53U
,由此可确定指针 obj
指向一个有效的 XWOS的对象 。
然后对比标签 obj->tik
和 tik
是否相等,由此可以确定对象的 身份 。
因为对象的 tik
是全局唯一的,当对象被释放后,它的 tik
会被析构函数析构为 0
。
当内存地址被重新构建为新的对象,那么它的 tik
一定与对象描述符的 tik
不一致。
相应的,当 struct xwos_object
被子类继承后,子类也应该有对应的 对象描述符 。
例如,线程对象的 线程对象描述符 、互斥锁对象的 互斥锁对象描述符 等。
对象的生命周期
XWOS的对象使用引用计数法管理生命周期,XWOS对象的生命周期分为三个阶段:
- 构造阶段 :对象通过
xwos_object_construct()
构造后进入 构造阶段 , 此时对象的引用计数为 0 。如果存在派生与继承,需要按照从 基类到子类 的顺序依次调用构造函数。 - 应用阶段 :处于构造阶段的对象,通过
xwos_object_activate()
激活后进入 应用阶段 。 如果存在派生与继承,需要按照从 基类到子类 的顺序依次调用激活函数。 此阶段对象的引用计数 >= 1 ,对象可以开始被使用。 - 释放阶段 :当对象引用计数从 >= 1 减少为 0 ,对象进入 释放阶段 ,此阶段会调用对象的
gcfunc()
释放对象。 用户需要提供gcfunc()
的定义,gcfunc()
内还需要调用对象的析构函数xwos_object_destruct()
如果存在派生与继承,需要按照从 子类到基类 的顺序依次调用析构函数。 至此对象生命周期结束。
对象的生命周期管理
XWOS提供两组对象的生命周期管理的CAPI:
-
使用 对象指针 访问生命周期管理的CAPI:需要确保调用CAPI时,对象一定是有效的,且不存在 释放-又被申请 为另一个对象的情况。
xwos_object_grab()
:增加引用计数。xwos_object_put()
:减少引用计数,当引用计数减少为 0 时,调用垃圾回收函数释放对象。xwos_object_rawput()
:减少引用计数,引用计数为 0 时不调用垃圾回收函数。
-
使用 对象描述符 访问生命周期管理的CAPI:用户无法确保对象一定有效或无法确保对象不会变成另一个对象时使用。
xwos_object_acquire()
:通过对象描述符确定对象有效且合法,再增加引用计数。xwos_object_release()
:通过对象描述符确定对象有效且合法,再减少引用计数。 当引用计数减少为 0 时,调用垃圾回收函数释放对象。
局限性
频繁地管理对象的生命周期会影响CPU的运行效率,因为引用计数的操作是原子操作,原子操作会影响CPU的性能, CPU性能越强,影响越巨大。因此,除了必要的情况,XWOS内核各种对象的CAPI被设计为直接使用 对象的指针 作为参数,并且不会自动管理对象的生命周期。 对象的有效性,身份的合法性,生命周期需要由用户手动管理。
通常,在简单的MCU RTOS应用,这些对象都是只创建不释放的,也没有必要关心生命周期。 事实上,对象的生命周期的CAPI主要是给高级语言设计的,例如 Lua 虚拟机用来实现对象生命周期的自动管理。