@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();
}
}