核心类型定义了多个功能集合使用的通用类和功能,作为它们公共接口的一部分。定义核心类型的一个原理是包含在接口定义中经常使用的通用复杂数据类型。
18.1 错误处理
概述
对任何软件开发来说错误处理都是一个重要的话题。对于关键安全软件,它更重要,因为软件生命要依靠它。但是,当前的安全关键软件开发标准对构建工具链施加了很大的限制,特别是在c++异常方面。对于ASIL应用程序,使用c++异常通常是不可能的,因为ASIL认证的c++编译器缺乏对异常的支持。
Adaptive 平台引入了一个概念使错误处理没有C++异常,并且定义了大量的C++数据类型来辅助。
从应用程序开发者的角度,实现这个概念的核心类型是ara::core::ErrorCode和ara::core::Result.
错误码
ara::code::ErrorCode的一个实例表示软件内一个特定的错误条件。它类似于std::error_code,但是在很多方面都不相同。
一个错误码一直包含一个枚举类型(将类型擦除为整型)和一个对错误域的引用。枚举值描述一个特定的错误类型,错误域的音乐定义了错误应用的上下文。其它可选的成员是一个用户定义的信息字符串和一个厂家定义的额补充错误描述值。
在Adaptive 平台内部,每个功能集合定义了一个或多个错误域。比如,功能集合“Core Type”定义了错误域“Posix”,这个错误域包含了POSIX 1已经定义的错误码。它们相当于c++ 11标准中的std::errc。
结果
类ara::core::Result是一个打包类型,它包含了一个值或一个错误。因为模板特性,值和错误可以是任何一种类型。但是,错误类型默认为ara::core::ErrorCode,并希望在整个Adaptive平台保持。
因为错误类型有个默认值,所以ara::core::Result大部分的生命仅仅需要给值一个类型。比如 ara::core::Result<int> 包含一个int 或 ara::core::ErrorCode。
包含的值或错误可以通过成员函数Result::Value 或 Result::Error来访问。确保仅当结果实例分别包含一个值或一个错误时才调用这些访问函数是调用者的责任。比如Result::HasValue可以查询一个值或一个错误。没有成员函数抛出异常,因此可以在不支持C++异常的环境中使用。
除了上面描述的无异常工作流之外,类ara::core::Result允许通过调用ara::core::Result::ValueOrThrow将包含ara::core::ErrorCode转换成C++异常。此调用按原样返回任何包含的值,但是通过抛出相应的异常类型来处理包含的错误,该异常类型自动派生自包含的ara::core::ErrorCode的内容。
将来和承诺
与ara::core::Result用作同步函数调用的广义返回类型类似,ara::core::Future用作异步函数调用的广义返回类型。
ara::core::Future与std:: Future非常相似,但是已经扩展到与ara::core::Result互操作。
和ara::core::Result类似,ara::core::Future是包含一个值或一个错误的类。该内容可以通过两种方式提取:
1. 通过调用ara::core::Future::get,如果存在就返回一个包含的值。如果没有,就抛出异常
2. 通过调用ara::core::Future::GetResult, 从Future中返回一个包含一个值或一个错误的对象ara::core::Result。
这两条调用会block直到这个值或错误通过异步调用方法可用。
18.2 高级数据类型
除了前面部分提到的AUTOSAR设计的类型,Adaptive平台也包含大量的通用数据类型。
部分这些类型已经包含在C++11标准中;但是,大部分相同行为的类型在ara::core命名空间重新定义。原因是std::types的内存分配行为对汽车来说不适用。因此,ara::core定义了他们自己的内存分配行为。
这种数据类型的例子是vector, map, 和string。
其它定义在ara::core中的类型已经被定义或建议给新的C++标准。Adaptive平台把他们包含进了ara::core命名空间,因为他们对于支持某些清单的构建是必须的,或因为它们被认为在API中非常有用。这种数据类型的例子是string_view, span, optional和variant。
18.3 原始数据类型
存在另外一个文档AUTOSAR_SWS_AdaptivePlatformTypes,它定义了可以用在服务接口描述中的原始类型。这个文档将来会考虑和顶到核心类型文档中。
18.4 全局初始化和关闭功能
下面的函数对Adaptive应用程序来说,初始化和反初始化对应的数据结构和AUTOSAR运行事件的线程是非常有用的:
* ara::core::Initialize
* ara::core::Deinitialize
ara::core::Initialize初始化应用程序的数据结构和AUTOSAR Adaptive运行时的线程。在此调用之前,不可能与ARA进行交互。这个调用必须在main()函数中。比如在保证静态内存初始化完成的地方。根据个人功能集合规范,调用应用程序需要提供额外的配置数据(比如日志要求的Application ID)或额外的初始化调用(比如在ara::com中启动FindService),然后才能对相应的功能集群进行其他API调用。这些调用必须在调用Initialize()之后。在静态初始化完成之前调用ARA API可能导致未定义的行为。在静态初始化完成之后但是在Initialize()之前调用会被功能集合实现拒绝并报告错误。如果没有定义报告的错误,会导致未定义的行为。
ara::core::Deinitialize破坏应用程序所有的数据结构和AUTOSAR Adaptive运行时的线程。调用必须在main()函数中,比如在保证静态初始化已经完成并且静态初始化数据析构还没有开始的地方。对ARA API的嗲用在ara::core::Deinitialize()之后但是在静态初始化数据析构之前会被拒绝并报告错误。如果没有定义错误,会导致未定义的行为。在静态初始化数据析构之后调用ARA API会导致未定义的行为。