< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java

Print this page
*** 28,11 ***
  
  import jdk.incubator.foreign.MemorySegment;
  import jdk.incubator.foreign.ResourceScope;
  import jdk.incubator.foreign.SegmentAllocator;
  import jdk.internal.misc.ScopedMemoryAccess;
! import jdk.internal.ref.CleanerFactory;
  
  import java.lang.ref.Cleaner;
  import java.lang.ref.Reference;
  import java.util.Objects;
  
--- 28,11 ---
  
  import jdk.incubator.foreign.MemorySegment;
  import jdk.incubator.foreign.ResourceScope;
  import jdk.incubator.foreign.SegmentAllocator;
  import jdk.internal.misc.ScopedMemoryAccess;
! import jdk.internal.vm.annotation.ForceInline;
  
  import java.lang.ref.Cleaner;
  import java.lang.ref.Reference;
  import java.util.Objects;
  

*** 47,25 ***
   * Shared scopes do not feature an owner thread - meaning their operations can be called, in a racy
   * manner, by multiple threads. To guarantee temporal safety in the presence of concurrent thread,
   * shared scopes use a more sophisticated synchronization mechanism, which guarantees that no concurrent
   * access is possible when a scope is being closed (see {@link jdk.internal.misc.ScopedMemoryAccess}).
   */
! public abstract non-sealed class ResourceScopeImpl implements ResourceScope, ScopedMemoryAccess.Scope, SegmentAllocator {
  
      final ResourceList resourceList;
  
      @Override
      public void addCloseAction(Runnable runnable) {
          Objects.requireNonNull(runnable);
          addInternal(ResourceList.ResourceCleanup.ofRunnable(runnable));
      }
  
-     @Override
-     public boolean isImplicit() {
-         return false;
-     }
- 
      /**
       * Add a cleanup action. If a failure occurred (because of a add vs. close race), call the cleanup action.
       * This semantics is useful when allocating new memory segments, since we first do a malloc/mmap and _then_
       * we register the cleanup (free/munmap) against the scope; so, if registration fails, we still have to
       * cleanup memory. From the perspective of the client, such a failure would manifest as a factory
--- 47,23 ---
   * Shared scopes do not feature an owner thread - meaning their operations can be called, in a racy
   * manner, by multiple threads. To guarantee temporal safety in the presence of concurrent thread,
   * shared scopes use a more sophisticated synchronization mechanism, which guarantees that no concurrent
   * access is possible when a scope is being closed (see {@link jdk.internal.misc.ScopedMemoryAccess}).
   */
! public abstract non-sealed class ResourceScopeImpl implements ResourceScope, SegmentAllocator, ScopedMemoryAccess.Scope {
  
      final ResourceList resourceList;
+     final Cleaner.Cleanable cleanable;
+ 
+     static final int MAX_FORKS = Integer.MAX_VALUE;
  
      @Override
      public void addCloseAction(Runnable runnable) {
          Objects.requireNonNull(runnable);
          addInternal(ResourceList.ResourceCleanup.ofRunnable(runnable));
      }
  
      /**
       * Add a cleanup action. If a failure occurred (because of a add vs. close race), call the cleanup action.
       * This semantics is useful when allocating new memory segments, since we first do a malloc/mmap and _then_
       * we register the cleanup (free/munmap) against the scope; so, if registration fails, we still have to
       * cleanup memory. From the perspective of the client, such a failure would manifest as a factory

*** 89,87 ***
          } catch (ScopedMemoryAccess.Scope.ScopedAccessError err) {
              throw new IllegalStateException("Already closed");
          }
      }
  
!     protected ResourceScopeImpl(Cleaner cleaner, ResourceList resourceList) {
          this.resourceList = resourceList;
!         if (cleaner != null) {
!             cleaner.register(this, resourceList);
-         }
-     }
- 
-     public static ResourceScopeImpl createImplicitScope() {
-         return new ImplicitScopeImpl(CleanerFactory.cleaner());
      }
  
      public static ResourceScopeImpl createConfined(Thread thread, Cleaner cleaner) {
          return new ConfinedScope(thread, cleaner);
      }
  
-     /**
-      * Creates a confined memory scope with given attachment and cleanup action. The returned scope
-      * is assumed to be confined on the current thread.
-      * @return a confined memory scope
-      */
-     public static ResourceScopeImpl createConfined(Cleaner cleaner) {
-         return new ConfinedScope(Thread.currentThread(), cleaner);
-     }
- 
-     /**
-      * Creates a shared memory scope with given attachment and cleanup action.
-      * @return a shared memory scope
-      */
      public static ResourceScopeImpl createShared(Cleaner cleaner) {
          return new SharedScope(cleaner);
      }
  
-     private final void release0(HandleImpl handle) {
-         try {
-             Objects.requireNonNull(handle);
-             if (handle.scope() != this) {
-                 throw new IllegalArgumentException("Cannot release an handle acquired from another scope");
-             }
-             handle.release();
-         } finally {
-             Reference.reachabilityFence(this);
-         }
-     }
- 
      @Override
!     public final void release(ResourceScope.Handle handle) {
!         release0((HandleImpl)handle);
-     }
- 
-     @Override
-     public final void release(ScopedMemoryAccess.Scope.Handle handle) {
-         release0((HandleImpl)handle);
      }
  
!     @Override
-     public abstract HandleImpl acquire();
- 
-     /**
-      * Internal interface used to implement resource scope handles.
-      */
-     public non-sealed interface HandleImpl extends ResourceScope.Handle, ScopedMemoryAccess.Scope.Handle {
  
!         @Override
-         ResourceScopeImpl scope();
  
!         void release();
      }
  
      /**
       * Closes this scope, executing any cleanup action (where provided).
       * @throws IllegalStateException if this scope is already closed or if this is
       * a confined scope and this method is called outside of the owner thread.
       */
      public void close() {
          try {
              justClose();
!             resourceList.cleanup();
          } finally {
              Reference.reachabilityFence(this);
          }
      }
  
--- 87,56 ---
          } catch (ScopedMemoryAccess.Scope.ScopedAccessError err) {
              throw new IllegalStateException("Already closed");
          }
      }
  
!     protected ResourceScopeImpl(ResourceList resourceList, Cleaner cleaner) {
          this.resourceList = resourceList;
!         cleanable = (cleaner != null) ?
!             cleaner.register(this, resourceList) : null;
      }
  
      public static ResourceScopeImpl createConfined(Thread thread, Cleaner cleaner) {
          return new ConfinedScope(thread, cleaner);
      }
  
      public static ResourceScopeImpl createShared(Cleaner cleaner) {
          return new SharedScope(cleaner);
      }
  
      @Override
!     public MemorySegment allocate(long bytesSize, long bytesAlignment) {
!         return MemorySegment.allocateNative(bytesSize, bytesAlignment, this);
      }
  
!     public abstract void release0();
  
!     public abstract void acquire0();
  
!     @Override
+     public void keepAlive(ResourceScope target) {
+         if (target == this) {
+             throw new IllegalArgumentException("Invalid target scope.");
+         }
+         ResourceScopeImpl targetImpl = (ResourceScopeImpl)target;
+         targetImpl.acquire0();
+         addCloseAction(targetImpl::release0);
      }
  
      /**
       * Closes this scope, executing any cleanup action (where provided).
       * @throws IllegalStateException if this scope is already closed or if this is
       * a confined scope and this method is called outside of the owner thread.
       */
      public void close() {
          try {
              justClose();
!             if (cleanable != null) {
+                 cleanable.clean();
+             } else {
+                 resourceList.cleanup();
+             }
          } finally {
              Reference.reachabilityFence(this);
          }
      }
  

*** 213,65 ***
      protected Object clone() throws CloneNotSupportedException {
          throw new CloneNotSupportedException();
      }
  
      /**
!      * Allocates a segment using this scope. Used by {@link SegmentAllocator#ofScope(ResourceScope)}.
!      */
!     @Override
-     public MemorySegment allocate(long bytesSize, long bytesAlignment) {
-         return MemorySegment.allocateNative(bytesSize, bytesAlignment, this);
-     }
- 
-     /**
-      * A non-closeable, shared scope. Similar to a shared scope, but its {@link #close()} method throws unconditionally.
-      * In addition, non-closeable scopes feature a much simpler scheme for generating resource scope handles, where
-      * the scope itself also acts as a resource scope handle and is returned by {@link #acquire()}.
       */
!     static class ImplicitScopeImpl extends SharedScope implements HandleImpl {
- 
-         public ImplicitScopeImpl(Cleaner cleaner) {
-             super(cleaner);
-         }
  
!         @Override
!         public HandleImpl acquire() {
-             return this;
-         }
- 
-         @Override
-         public boolean isImplicit() {
-             return true;
          }
  
          @Override
          public void close() {
              throw new UnsupportedOperationException("Scope cannot be closed");
          }
  
          @Override
!         public void release() {
              // do nothing
          }
  
          @Override
!         public ResourceScopeImpl scope() {
!             return this;
          }
-     }
  
-     /**
-      * The global, always alive, non-closeable, shared scope. This is like a {@link ImplicitScopeImpl non-closeable scope},
-      * except that the operation which adds new resources to the global scope does nothing: as the scope can never
-      * become not-alive, there is nothing to track.
-      */
-     public static final ResourceScopeImpl GLOBAL = new ImplicitScopeImpl( null) {
          @Override
          void addInternal(ResourceList.ResourceCleanup resource) {
              // do nothing
          }
!     };
  
      /**
       * A list of all cleanup actions associated with a resource scope. Cleanup actions are modelled as instances
       * of the {@link ResourceCleanup} class, and, together, form a linked list. Depending on whether a scope
       * is shared or confined, different implementations of this class will be used, see {@link ConfinedScope.ConfinedResourceList}
--- 180,44 ---
      protected Object clone() throws CloneNotSupportedException {
          throw new CloneNotSupportedException();
      }
  
      /**
!      * The global, always alive, non-closeable, shared scope. Similar to a shared scope, but its {@link #close()} method throws unconditionally.
!      * Adding new resources to the global scope, does nothing: as the scope can never become not-alive, there is nothing to track.
!      * Acquiring and or releasing a resource scope similarly does nothing.
       */
!     static class GlobalScopeImpl extends SharedScope {
  
!         public GlobalScopeImpl() {
!             super(null);
          }
  
          @Override
          public void close() {
              throw new UnsupportedOperationException("Scope cannot be closed");
          }
  
          @Override
!         @ForceInline
+         public void release0() {
              // do nothing
          }
  
          @Override
!         @ForceInline
!         public void acquire0() {
+             // do nothing
          }
  
          @Override
          void addInternal(ResourceList.ResourceCleanup resource) {
              // do nothing
          }
!     }
+ 
+     public static final ResourceScopeImpl GLOBAL = new GlobalScopeImpl();
  
      /**
       * A list of all cleanup actions associated with a resource scope. Cleanup actions are modelled as instances
       * of the {@link ResourceCleanup} class, and, together, form a linked list. Depending on whether a scope
       * is shared or confined, different implementations of this class will be used, see {@link ConfinedScope.ConfinedResourceList}
< prev index next >