147. Shaping C-like unions into memory segments
Let’s consider the C-like union from the following figure (the members of a C union share the same memory location (the member’s largest data type dictates the size of the memory location), so only one of the members has a value at any moment in time):

Figure 7.14 – A C-like union
In Figure 7.14, we have a C-like union named product to shape two members, price (double) and sku (int), while only one can have a value at any moment in time. We can shape a memory segment to fit this model as follows (arena is an instance of Arena):
MemorySegment segment = MemorySegment.allocateNative(
ValueLayout.JAVA_DOUBLE.byteSize(),
ValueLayout.JAVA_DOUBLE.byteAlignment(), arena.scope());
Because double needs 8 bytes and int needs only 4 bytes, we choose ValueLayout.JAVA_DOUBLE to shape the size of the memory segment. This way, the segment can accommodate a double and an int at the same offset.Next, we can set the price or the sku and use it accordingly:
segment.setAtIndex(ValueLayout.JAVA_DOUBLE, 0, 500.99);
segment.setAtIndex(ValueLayout.JAVA_INT, 0, 101000);
When we set the sku (int), the value of price (double) became a garbage value and vice versa. For more details, check out the bundled code. Next, let’s see an alternative to this implementation based on UnionLayout.
Introducing UnionLayout
A UnionLayout is a group layout. In this layout, the members (other memory layouts) are laid out at the same starting offset exactly as in a C union. This means that we can shape our C-like union by laying out the price (double) and the sku (int) members as follows:
UnionLayout union = MemoryLayout.unionLayout(
ValueLayout.JAVA_DOUBLE.withName(“price”),
ValueLayout.JAVA_INT.withName(“sku”));
Next, as we already know from Problem x, we need to define the proper layout paths via PathElement and get back the VarHandle. We need a VarHandle for price and one for sku. Notice in the following code how we point them out via their names:
// VarHandle[varType=double,
// coord=[interface java.lang.foreign.MemorySegment]]
VarHandle pHandle = union.varHandle(
PathElement.groupElement(“price”));
// VarHandle[varType=double,
// coord=[interface java.lang.foreign.MemorySegment]]
VarHandle sHandle = union.varHandle(
PathElement.groupElement(“sku”));
Finally, we can use these VarHandle to set price or sku:
try (Arena arena = Arena.openConfined()) {
MemorySegment segment = arena.allocate(union);
pHandle.set(segment, 500.99);
sHandle.set(segment, 101000);
}
When we set the sku (int), the value of price (double) became a garbage value and vice versa.