Unions are sometimes needed for communicating with C/C++ programs. They're also how ASIL implements [Variants]. ASIL ensures the data is valid for the fields you're trying to access with a control member. The control member is an instance of an primitive-based enum type. (Structure-based enums can't be used with unions.) The enum type must have explicit or implied values for each entry. Unlike [Bitfields], unions don't have to be nested inside another type.
All members of a union must be either a bitfield or a structure (except members of the union's members). The immediate members of the union (the bitfields and structures) are all public to all code with access to the union. These immediate members have no name or type associated with it. Think of them as anonymous structures from C++. Variants in ASIL are implemented as unions. See the section on [Variants] for more information.
Declaring the union
Unions in ASIL are the controlling member as far as syntax is concerned. It declares a type, not an instance. The syntax is union enumtype identifier [= defaultvalue]
where enumtype
is the type of the controlling member. If you leave out the default value, you should set it in the union's constructor.
You have a choice of putting the bits used for the controlling member's values at the start of the union (before it's members) or after the union's members. That's controlled by the @ line shown below. It's required. The type of the controlling member can be nested within the union type.
It's unknown if this type of union will default to by reference or by value.
union MyUnion.ControllingType MyUnion public enum ControllingType left = 0 right constructor self = ControllingType.left struct = MyEnum.left ' This syntax associates the members of this struct with MyENum.left public constructor s$ = "test" public var s$ bitfield = MyEnum.right ' The syntax for a bitfield that's a member of a union is the same as for normal bitfields except we need to associate the bitfield with a entry from MyEnum. public 8 first = 3 public 8 second = 5 public 8 third = 6 public 8 fourth = 9 ' If a reference pointer is 32-bits long, this would be the same length @ ' Place the bits for the controlling member here ~ ' One tilde causes all members of the union to be padded to the length of the longest member--and no longer. Two tildes (<code>~~</code> causes all members of the union to be padded as the compiler sees fit (that is, whatever is considered optimal). No tildes prevents padding. Must be last.
In order to use a union, you need to declare an instance. Syntactically, an instance can be treated as an instance of the controlling enum type. You can compare it as needed. You can also set it by setting the union's identifier to an instance of the enum type. The following code users the union declared above.
var MyUnion myUnionInstance = new MyUnion if myUnionInstance = left ' do something with myUnionInstance.s$ myUnionInstance = MyUnion.ControllingType.right ' Destroys s$ and creates the bitfield myUnionInstance.first = 34
Unions can be generic. The syntax is the same as with other generic types.
If you need external code to change part of the union, mark your instance of the union's type with the **volatile keyword.
Unions of this type have a built-in event. Even though you can treat the union's instance as though it were the actual controlling enum member, the ++ and -- get mapped to the event, not the controlling member. (It doesn't make sense to increment or decrement the value of the controlling member anyway.) The handler should be a command takes an instance of the controlling type (which has the old value of the controlling member) and can throw no exceptions. If you need to know the new value of the controlling member, just reference the union instance's identifier.
command myHandler var MyUnion.ControllingType oldValue ' Do something in response to the event. myUnionInstance ++ &myHandler myUnionInstance -- &myHandler
Unions can have methods and properties. However, it's methods and properties must be members of the bitfields and structures inside the union, not directly inside the union itself. (The union can however declare constructors, destructors, and creators.) Those methods or properties can only be accessed when the controlling member allows access to those fields.
All editors and compilers should warn about access of fields/methods/properties when the value of the controlling member isn't known or is wrong for the field/method/property being accessed. By the same token, if the value of the controlling member has been established, an auto-complete tool should only list members of that part of the union.
Wiki: Bitfields
Wiki: Home
Wiki: Keywords
Wiki: Structures
Wiki: Variants
Wiki: keywords-union
I don't yet know how to solve this problem: If external code changes the controlling member, the [volatile] keyword might not be enough. The problem is firing the event and calling destructors/constructors. I see some options: