但是,如果某个对象满足以下任意一项条件,就会视作为反应对象:
如果某个对象是反应对象,那么会在该对象的结构中根据值嵌入 RiCReactive 对象的实例来作为数据成员。例如:
typedef struct Furnace Furnace;
struct Furnace {
RiCReactive ric_reactive;
/* attributes of Furnace */
};
RiCReactive 是 IBM® Rational® Rhapsody® Developer for C 框架提供用于定义反应对象的事件处理行为的抽象数据类型。
对于每个反应对象,实施文件中会定义一个额外的 struct 来保存指向定义为状态图实施的一部分的函数的指针。这些指针会传递给对象类型的反应成员:
static const RiCReactive_Vtbl Furnace_reactiveVtbl = {
rootState_dispatchEvent,
rootState_entDef,
ROOT_STATE_SERIALIZE_STATES(rootState_serializeStates),
/* Violation of MISRA Rule 45 (Required): */
/* 'Type casting to or from pointers shall not be used.' */
/* The following cast is justified and is */
/* for Rational Rhapsody auto-generated code use only. */
(RiCObjectDestroyMethod) Furnace_Destroy,
NULL,
NULL,
NULL,
(RiCObjectCleanupMethod) Furnace_Cleanup,
(RiCObjectFreeMethod) FreeInstance
};
dispatchEvent()、entDef() 和 serializeState() 函数是在框架 (RiCHdlCls.c) 中定义的句柄关闭程序文件中实施的。您可以定义函数来执行类似操作并通过虚函数表将它们链接到您的项目(如果需要)。但是,该主题超出了本标题的范围。
反应对象的初始化和它所驱动的状态图是作为对象的初始化函数的一部分来完成的。例如,以下 HomeHeatingSystem 中的 Furnace 对象的初始化方法调用 RiCReactive_init() 来初始化反应对象,然后调用 initStatechart() 来为对象初始化状态图:
void Furnace_Init(Furnace* const me, RiCTask * p_task) {
RiCReactive_init(&me->ric_reactive, (void*)me,
p_task, &Furnace_reactiveVtbl);
/* relation initialization loop */
initStatechart(me);
}
RiCReactive_init() 和 initStatechart() 函数定义在 Rational Rhapsody 框架中。
初始化方法的第二个参数 p_task 是指向任务的指针,带有相关联的事件队列,反应对象从该队列来处理事件。如果反应对象是顺序的,那么该任务是系统线程;如果反应对象是活动的,那么该任务是对象的线程。有关更多信息,请参阅活动对象和并发性。