Slicing Allocators and Slicing Memory Segments (original) (raw)

The following example allocates a memory segment namedsegment that can hold 60 Java int values. It then uses a slicing allocator by calling SegmentAllocator.slicingAllocator(MemorySegment) to obtain ten consecutive slices from segment. The example allocates an array of five integers in each slice. After, it prints the contents of each slice.

void allocate60Int() {

    try (Arena arena = Arena.ofConfined()) {
        SequenceLayout SEQUENCE_LAYOUT =
            MemoryLayout.sequenceLayout(60L, ValueLayout.JAVA_INT);
        MemorySegment segment = arena.allocate(SEQUENCE_LAYOUT);
        SegmentAllocator allocator = SegmentAllocator.slicingAllocator(segment);
        
        MemorySegment s[] = new MemorySegment[10];
        
        for (int i = 0 ; i < 10 ; i++) {
            s[i] = allocator.allocateFrom(
                ValueLayout.JAVA_INT, 1, 2, 3, 4, 5);
        }

        for (int i = 0 ; i < 10 ; i++) {
            int[] intArray = s[i].toArray(ValueLayout.JAVA_INT);
            System.out.println(Arrays.toString(intArray));
        }
        
    } catch (Exception e) {
        e.printStackTrace();
    }
}
    

You can use segment allocators as building blocks to create arenas that support custom allocation strategies. For example, if a large number of native segments will share the same bounded lifetime, then a custom arena could use a slicing allocator to allocate the segments efficiently. This lets clients enjoy both scalable allocation (thanks to slicing) and deterministic deallocation (thanks to the arena).

The following example defines a slicing arena that behaves like a confined arena but internally uses a slicing allocator to respond to allocation requests. When the slicing arena is closed, the underlying confined arena is closed, invalidating all segments allocated in the slicing arena.

To keep this example short, it implements only a subset of the methods ofArena and SegmentAllocator (which is a superinterface of Arena).

public class SlicingArena implements Arena {
    final Arena arena = Arena.ofConfined();
    final SegmentAllocator slicingAllocator;

    SlicingArena(MemoryLayout m) {
        slicingAllocator = SegmentAllocator.slicingAllocator(arena.allocate(m));
    }
    public MemorySegment allocate(long byteSize, long byteAlignment) {
        return slicingAllocator.allocate(byteSize, byteAlignment);
    }
    public MemorySegment.Scope scope() {
        return arena.scope();
    }        
    public void close() {
        arena.close();
    }
}

With this slicing arena, you can rewrite the first example in this section more succinctly:

void allocate60IntWithSlicingArena() {

    SequenceLayout SEQUENCE_LAYOUT =
        MemoryLayout.sequenceLayout(60L, ValueLayout.JAVA_INT);
    try (Arena slicingArena = new SlicingArena(SEQUENCE_LAYOUT)) {
        MemorySegment s[] = new MemorySegment[10];
        
        for (int i = 0 ; i < 10 ; i++) {
            s[i] = slicingArena.allocateFrom(
                ValueLayout.JAVA_INT, 1, 2, 3, 4, 5);
        }
            
        for (int i = 0 ; i < 10 ; i++) {
            int[] intArray = s[i].toArray(ValueLayout.JAVA_INT);
            System.out.println(Arrays.toString(intArray));
        }
            
    } catch (Exception e) {
        e.printStackTrace();
    }
}