alef 0.82.0

Opinionated polyglot binding generator for Rust libraries
Documentation
@SuppressWarnings("PMD")
public class {{ class_name }} implements AutoCloseable {
    private MemorySegment handle;
    private int activeBorrows;
    private boolean handleUnavailable;
    private boolean transferPending;

    @FunctionalInterface
    private interface NativeReleaser {
        void release(MemorySegment handle) throws Throwable;
    }

    private static final class CleanupFailures {
        private final List<Throwable> failures = new java.util.ArrayList<>();

        private void release(MemorySegment handle, NativeReleaser releaser) {
            if (handle == null || handle.equals(MemorySegment.NULL)) return;
            try {
                releaser.release(handle);
            } catch (Throwable failure) {
                failures.add(failure);
            }
        }

        private void close(AutoCloseable resource) {
            if (resource == null) return;
            try {
                resource.close();
            } catch (Throwable failure) {
                failures.add(failure);
            }
        }

        private void throwIfAny(Throwable primaryFailure) {
            if (failures.isEmpty()) return;
            RuntimeException aggregate = new RuntimeException("Native resource cleanup failed");
            failures.forEach(aggregate::addSuppressed);
            if (primaryFailure != null) {
                primaryFailure.addSuppressed(aggregate);
                return;
            }
            throw aggregate;
        }
    }

    final class HandleLease implements AutoCloseable {
        private final MemorySegment borrowedHandle;
        private boolean released;

        private HandleLease(MemorySegment borrowedHandle) {
            this.borrowedHandle = borrowedHandle;
        }

        MemorySegment handle() {
            return borrowedHandle;
        }

        @Override
        public void close() {
            synchronized ({{ class_name }}.this) {
                if (released) {
                    return;
                }
                released = true;
                activeBorrows--;
                if (activeBorrows == 0) {
                    {{ class_name }}.this.notifyAll();
                }
            }
        }
    }

    final class HandleTransfer implements AutoCloseable {
        private MemorySegment transferredHandle;

        private HandleTransfer(MemorySegment transferredHandle) {
            this.transferredHandle = transferredHandle;
        }

        synchronized MemorySegment handle() {
            if (transferredHandle == null || transferredHandle.equals(MemorySegment.NULL)) {
                throw new IllegalStateException("Handle transfer is no longer active");
            }
            return transferredHandle;
        }

        synchronized MemorySegment commit() {
            if (transferredHandle == null || transferredHandle.equals(MemorySegment.NULL)) {
                throw new IllegalStateException("Handle transfer is no longer active");
            }
            MemorySegment committedHandle = transferredHandle;
            transferredHandle = MemorySegment.NULL;
            commitTransfer();
            return committedHandle;
        }

        @Override
        public synchronized void close() {
            if (transferredHandle == null || transferredHandle.equals(MemorySegment.NULL)) {
                return;
            }
            rollbackTransfer(transferredHandle);
            transferredHandle = MemorySegment.NULL;
        }
    }

    {{ class_name }}(MemorySegment handle) {
        this.handle = handle;
    }

    synchronized MemorySegment handle() {
        checkHandleAvailable();
        return this.handle;
    }

    synchronized HandleLease borrowHandle() {
        checkHandleAvailable();
        activeBorrows++;
        return new HandleLease(handle);
    }

    synchronized HandleTransfer takeHandle() {
        checkHandleAvailable();
        HandleTransfer transfer = new HandleTransfer(handle);
        handleUnavailable = true;
        awaitBorrowedCalls();
        this.handle = MemorySegment.NULL;
        transferPending = true;
        return transfer;
    }

    private synchronized void rollbackTransfer(MemorySegment transferredHandle) {
        if (!handle.equals(MemorySegment.NULL)) {
            throw new IllegalStateException("Cannot restore an active handle");
        }
        transferPending = false;
        handle = transferredHandle;
        handleUnavailable = false;
        notifyAll();
    }

    private synchronized void commitTransfer() {
        transferPending = false;
        notifyAll();
    }

    private void checkHandleAvailable() {
        if (handleUnavailable || handle == null || handle.equals(MemorySegment.NULL)) {
            throw new IllegalStateException("{{ class_name }} is closed");
        }
    }

    private void awaitBorrowedCalls() {
        boolean interrupted = false;
        while (activeBorrows != 0) {
            try {
                wait();
            } catch (InterruptedException ignored) {
                interrupted = true;
            }
        }
        if (interrupted) {
            Thread.currentThread().interrupt();
        }
    }