运行时模型
本节介绍 AutoCode 运行时模型。
概述
AutoCode 运行时由事件驱动执行,组件之间通过事件连接,一组连接的事件组成一个会话。每个会话有一个启动事件,一般由 VSOA 事件或系统事件启动会话,所有事件都执行完成,会话结束。 会话开始时,系统为会话创建会话对象(ac_t *acs),会话对象保存了会话上下文状态。会话结束时系统自动销毁会话对象及上下文资源。
异步会话
如果一个会话中存在 VSOA-CALL 输出端口,则会话为异步会话,异步会话分为同步过程与异步过程。同步过程会话中执行所有同步事件接口,异步过程等待 VSOA-CALL 调用返回并执行 REPLY 接口及异步事件接口。
在异步调用组件(AsyncCallMCom)中,finish
事件在会话的异步过程执行。
注意:异步过程与同步过程有可能并发执行,VSOA-CALL 调用可能在同步过程结束前返回。 在异步会话中,只有当所有 VSOA-CALL 调用返回会话才会结束。 会话启动事件是 VSOA-CALL 时,会话上下文将记录 VSOA-CALL 的响应状态:
- 当会话过程中执行了 REPLY 操作,VSOA-CALL 的响应结束;
- 当会话过程再次执行 REPLY 操作,REPLY 将会失败;
- 会话结束时将检查 VSOA-CALL 的 REPLY 状态,如果 REPLY 未完成,系统将自动执行 REPLY 操作,并返回 128 状态码。
会话执行顺序
通用组件(Component)每个事件输出端口可以连接多个事件,每个连接事件是一个分支,会话按照分支排序执行,执行完一个分支,再调用下一个分支。会话按照事件连接关系深度优先调用事件。
通用组件事件 Connect level
属性定义了输出端口分支的执行顺序。
多通道组件由第一个事件开始执行,一般情况多通道组件所有事件都在同一个会话中,每个事件是一个分支,按照事件在组件中的顺序从上到下执行。
会话可重入性
一组会话事件默认情况下是可重入的,即上次会话还未结束,可发起新的会话。
每个会话的启动事件有 Reentrant
属性,将 Reentrant
属性配置为 false
可设置会话不可重入,当会话开始时将检查上次会话是否结束,如果上次会话未结束则中止当前会话。
会话数据处理
以下 API 可以在会话对象上设置缓存数据:
/* Ac Cache data in k: v format, this method thread safe */
bool ac_data_set(ac_t *acs, const char *key, void *value, ac_data_free_fun_t free);
/* Ac Cache data with length in k: v format, this method thread safe */
bool ac_data_set_with_length(ac_t *acs, const char *key, void *value, size_t value_len, ac_data_free_fun_t free);
acs
: 会话对象。key
: 字符串类型,数据标识。value
: 数据缓存。value_len
: 数据缓存大小。 默认值: 0 表示未知大小。free
: 如果数据是动态分配的,需要提供一个释放方法。Returns
: 成功返回true
, 失败返回false
。
以下 API 可以在会话对象上获取缓存数据:
/* Find a previously added data of the specified key, this method thread safe */
void *ac_data_get(ac_t *acs, const char *key);
/* Find a previously added data of the specified key, this method thread safe */
void *ac_data_get_with_length(ac_t *acs, const char *key, size_t *value_len);
acs
: 会话对象。key
: 字符串类型,数据标识。value_len
: 获取数据缓存大小。 默认值: 0 表示未知大小。Returns
: 返回数据缓存, 失败返回NULL
。
返回值为空表明 key
指向的数据不存在。
以下 API 可以在会话对象上绑定数据:
/* Ac set custom data */
void ac_custom_set(ac_t *acs, void *custom);
/* Ac get custom data */
void *ac_custom_get(ac_t *acs);
设置缓存数据示例:
u_elems_t *cache = (u_elems_t *)malloc(sizeof(u_elems_t));
u_elems_init(cache);
ac_data_set(acs, "cache", (void *)cache, (ac_data_free_fun_t)free);
获取缓存数据示例:
u_elems_t * cache = (u_elems_t *)ac_data_get(acs, "cache");
jreply->var1 = cache->elema + cache->elemb;
在异步会话中,使用数据缓存 API 可以在不同接口中共享数据。
会话控制
会话中断
会话过程中如果出现异常时可以中断分支或整个会话过程。
AutoCode 每个事件编程接口都返回一个状态码,状态码可以控制会话执行过程:
AC_RET_OK
: 会话正常,将继续执行后继事件。AC_RET_BREAK
: 中断当前接口所在分支的前向事件,继续执行下一个事件。AC_RET_ABORT
: 中断会话,停止执行会话所有后继事件。
下图所示,会话在 com3.event1
返回 AC_RET_BREAK
, 则 com2.event1
后继事件不再执行,继续执行 com2.event2
。
下图所示,会话在 com3.event1
返回 AC_RET_ABORT
, 则会话结束。
会话控制
AutoCode 生成的系统代码中,如果检测到异常,一般返回 AC_RET_BREAK
状态码。用户在接口中可以修改返回状态码,从而控制会话执行过程。
会话跟踪
当会话异常时,系统将记录会话中断点,通过日志可以跟踪会话执行情况。
异步会话中断
同步过程中断
在异步会话中,同步过程执行完毕(正常或异常);如果输出端口成功发起 VSOA-CALL
,则会话将继续异步过程,等待调用返回; 如果所有输出端口 VSOA-CALL
调用失败,则会话会话结束。下图展示异步会话同步过程中断情况:
会话同步过程调用 com4.event1
接口执行成功,然后调用 com4.event2
接口;com4.event2
接口调用 VSOA-CALL
失败,返回中断标识。 当 com4.event1
REPLY 事件在 com4.event2
接口之前执行,会话是正常状态 com4.event1
REPLY 接口将正常执行。 当 com4.event2
接口在 com4.event1
REPLY 事件之前执行,会话被设置为中断状态, com4.event1
REPLY 接口将不再执行。
异步过程中断
异步过程每个分支如果检查到会话是中断状态则当前分支中断,不会继续调用用户接口;如果异步过程当前分支接口返回中断,则设置会话状态为中断状态;所有等待中的异步分支执行完会话结束。下图展示异步会话异步过程中断情况:
同步过程 com4.event1
接口和 com4.event2
接口执行成功,会话等待 com4.event1
、 com4.event2
REPLY 事件。com4.event1
REPLY 接口执行时返回中断标识。 当 com4.event1
REPLY 事件发生在 com4.event2
REPLY 事件之前,会话被设置为中断状态,com4.event2
REPLY 接口将不再执行。 当 com4.event2
REPLY 事件发生在 com4.event1
REPLY 事件之前,会话是正常状态,com4.event2
REPLY 接口将正常执行。