Class NativeResourceHandle
- All Implemented Interfaces:
AutoCloseable
This class encapsulates the closed-flag lifecycle pattern used across all Panama FFI classes. Each Panama class holds a NativeResourceHandle as a field and delegates close/ensureNotClosed to it, replacing the duplicated volatile boolean + ensureNotClosed boilerplate.
Key features:
- Thread-safe close via
AtomicBoolean.compareAndSet(boolean, boolean)(no double-free) - Optional
Cleanersafety net for native resources not explicitly closed - Idempotent
close()— safe to call multiple times
Safety net pattern: When using the Cleaner safety net, the safetyNetAction must
NOT capture a reference to the owning object. Capture only extracted local values (e.g., a
MemorySegment field). Otherwise the Cleaner prevents GC of the owning object and the safety net
never fires.
- Since:
- 1.0.0
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceFunctional interface for resource cleanup operations. -
Constructor Summary
ConstructorsConstructorDescriptionNativeResourceHandle(String resourceType, NativeResourceHandle.CleanupAction closeAction) Creates a resource handle without a Cleaner safety net.NativeResourceHandle(String resourceType, NativeResourceHandle.CleanupAction closeAction, Object safetyNetOwner, Runnable safetyNetAction) Creates a resource handle with a Cleaner safety net. -
Method Summary
Modifier and TypeMethodDescriptionvoidBegins a guarded operation by acquiring the read lock and verifying the resource is not closed.voidclose()Closes the resource.voidEnds a guarded operation by releasing the read lock.voidEnsures the resource is not closed.booleanisClosed()Checks if this resource has been closed.booleanAttempts to begin a guarded operation.
-
Constructor Details
-
NativeResourceHandle
public NativeResourceHandle(String resourceType, NativeResourceHandle.CleanupAction closeAction, Object safetyNetOwner, Runnable safetyNetAction) Creates a resource handle with a Cleaner safety net.CRITICAL: The
safetyNetActionRunnable must NOT capture a reference to the owning object. Capture only extracted primitive values or handles. If the Runnable capturesthis(the owning object), the Cleaner will prevent the object from being GC'd and the safety net will never fire.- Parameters:
resourceType- human-readable resource type for logging and error messagescloseAction- the cleanup action to run on explicit closesafetyNetOwner- the object whose GC triggers the safety net (typically the owning object)safetyNetAction- cleanup to run if the owner is GC'd without close (must not capture owner)
-
NativeResourceHandle
Creates a resource handle without a Cleaner safety net.Use this constructor for resources that don't hold native pointers directly, or where the Arena already provides cleanup guarantees.
- Parameters:
resourceType- human-readable resource type for logging and error messagescloseAction- the cleanup action to run on explicit close
-
-
Method Details
-
ensureNotClosed
public void ensureNotClosed()Ensures the resource is not closed.Warning: This method does NOT acquire the close lock. For thread-safe operation guarding, use
beginOperation()/endOperation()instead to prevent use-after-free race conditions with concurrentclose()calls.- Throws:
IllegalStateException- if the resource has been closed
-
beginOperation
public void beginOperation()Begins a guarded operation by acquiring the read lock and verifying the resource is not closed.Every call to
beginOperation()must be paired withendOperation()in afinallyblock.- Throws:
IllegalStateException- if the resource has been closed
-
endOperation
public void endOperation()Ends a guarded operation by releasing the read lock.Must be called in a
finallyblock afterbeginOperation(). -
tryBeginOperation
public boolean tryBeginOperation()Attempts to begin a guarded operation. Returnsfalseif the resource is closed, without throwing. If this returnstrue, the caller must callendOperation()in afinallyblock.- Returns:
trueif the operation can proceed (lock acquired),falseif closed
-
isClosed
public boolean isClosed()Checks if this resource has been closed.- Returns:
- true if the resource is closed, false otherwise
-
close
public void close()Closes the resource. Thread-safe and idempotent — only the first call executes the cleanup action. Subsequent calls are no-ops. Acquires the write lock to ensure no in-flight operations are using the native handle when it is freed.- Specified by:
closein interfaceAutoCloseable
-