Wednesday, April 19, 2006

Union Declaration in IDL and its C++ mapping

CORBA IDL Series Continued (Part 5)

Unions are like the C++ unions, value of which could be any of the types as represented in the union. In other words, it is an ordered list of identifiers and the value of the union itself is the value of the identifier chosen by the descriminator. If not all values of the discriminator are represented, then a notion of default exists.

Constructwise, a union has
  1. Descriminator - which defines the type of the case label
  2. case statements - which constist of a case label and case value; case label being a constant value of the descriminator and case value is the union value when the case label is selected
  3. Default value when no descriminator is selected or selection is out of range of the discriminator values.

Declaration in IDL

<union_type> ::= “union” <identifier> “switch”
“(” <switch_type_spec> “)” “{” <switch_body> “}”

<switch_type_spec> ::=
<integer_type>
<char_type>
<boolean_type>
<enum_type>

<switch_body> ::= (<case_label>+ <element_spec> “;”)+

<case_label> ::= “case” <const_exp> “:”
“default” “:”

<element_spec> ::= <type_spec> <declarator>

Mapping in C++

Unions map to C++ classes with the following member functions
  1. accessors: which provide a read only value
  2. mutators: which change the value; parameters are passed by value for small types and passed by constant reference to larger data types members; perform equivalent of deep copy and return nothing
  3. referents: read-write methods; Available for only struct, union, sequence and any member.
  4. union descriminator accessor and modifier - is always _d()
  5. Default accessor: If union does not have any default case, then _default() is automatically generated
Like structure mappings, this mapping totally manages its member memory. Copy constructor, assignment operators and destructor totally take care of this.

Salient notes about this mapping

Union instances should not be used with initialization. No default initialization should be assumed. By default, VisiBroker sets ths state to a legal default value.

When a union object is created, it needs to be initialized by calling one of the modifiers methods. This causes the descriminator to be set to the descriminator value corresponding to that particular type.

Trying to set descriminator value outside the current value set is illegal behaviour. In VisiBroker BAD_OPERATION exception is thrown.

When a different member modifier is called, the previous member is cleaned up.

union Foo switch (long) {
case 1: string str;
case 2:
case 3: long l;
default: char c;
};

C++ code
Foo f; // union not initialized
f._d(2); // illegal; throws BAD_OPERATION
f.str("Sandesh"); // initialized string member
f.l(20); string member is cleaned up
f._d(2); // legal
f._d(3); // legal
f.c('A'); // default value chosen
f._d(4); // okay as 4 is out of range of the discriminator and hence default value

Recursion

Recursion rules are similar to that of the structures. This is done through either anonymous sequences, or sequences of incomplete types by using forward declaration. If forward declarations are used, the incomplete constructs can only be used inside a union which is defining the incomlpete type. For more information see the BLOG - "Structure Declaration in IDL and its C++ mapping"

Memory Management of unions

Memory management rules are very similar to that of structures. Similar to structures, if a union has fixed length members it is a Fixed Length union, otherwise it is a variable length union. For more information see the BLOG - "Structure Declaration in IDL and its C++ mapping"