字段(Fields)总结
在骨架侧,服务实现负责更新并通知字段值变化、处理传入的 Get () 和 Set () 调用。骨架为每个提供的字段提供一个字段包装类成员,在服务提供方 / 骨架侧,特定于服务的字段包装类在骨架命名空间下的fields命名空间内定义。
以UpdateRate类为例:
class UpdateRate
{
public:using FieldType = uint32_t;ara::core::Result<void> Update(const FieldType& data);ara::core::Result<void> RegisterGetHandler(std::function<ara::core::Future<FieldType>()> getHandler);ara::core::Result<void> RegisterSetHandler(std::function<ara::core::Future<FieldType>(const FieldType& data)> setHandler);
};
一、Update () 方法
服务实现者可通过Update()方法更新字段当前值。若字段配置了 “变化通知”,在Update()调用过程中会触发对订阅者的通知。
二、注册 getter(RegisterGetHandler () 方法)
- 在生成的骨架代码中,仅当 IDL 为字段配置了 “字段 getter” 可用性时该方法才存在。注册 “GetHandler” 是可选的,通常服务实现者无需提供,因为绑定实现可通过
Update()设置的最新值响应Get()调用。 - 服务实现者提供 “GetHandler” 的可能原因是计算字段新 / 当前值代价高昂 / 耗时,可将计算过程推迟到 getter 调用时进行。但如果字段同时配置了 “on-change-notification”,这种设置可能导致新订阅者获得过时值且通信管理实现不会自动同步值。
- 如果 “获取处理程序” 仅返回已由
Update()更新的当前值,效率较低,通信管理需调用用户空间并对返回值进行序列化,而不注册 “获取处理程序” 可优化这一过程。
三、注册设置器(RegisterSetHandler () 方法)
- 如果服务实现存在且字段启用设置器,必须调用
RegisterSetHandler()API。强制注册 “SetHandler” 是因为服务器实现需要检查客户端设置的新 / 更新字段值的有效性。 - “SetHandler” 的签名为
std::function<ara::core::Future<FieldType>(const FieldType& data)>,处理程序将新值作为输入参数并返回一个值,通信管理实现会隐式接管返回的有效值,如同服务实现者用有效值调用了Update()一样,所以在 “SetHandler” 内部进行显式的Update()调用是多余的。
四、确保 “SetHandler” 的存在
开发人员在骨架实现上调用OfferService()时,如果尚未为每个启用设置器的字段注册 “SetHandler”,通信管理实现应返回ComErrc::kSetHandlerNotSet错误。
五、确保有效字段值的存在
ara::com需确保服务实现在服务对潜在消费者可见之前提供一个值。若开发人员在骨架实现上调用OfferService()时,尚未在满足特定条件的字段上调用Update(),通信管理实现应返回ComErrc::kFieldValueIsNotValid错误。
六、从 GetHandler/SetHandler 访问当前字段值
由于底层字段值仅为中间件所知,当前字段值无法从位于应用程序级别的 “GetHandler/SetHandler” 实现中访问。若 “GetHandler/SetHandler” 需要读取当前字段值,骨架实现必须提供一个可从应用程序级别访问的字段值副本。
