< prev index next >

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

Print this page
*** 23,15 ***
   * questions.
   */
  
  package jdk.internal.foreign;
  
- import jdk.incubator.foreign.ResourceScope;
  import jdk.internal.vm.annotation.ForceInline;
  
  import java.lang.ref.Cleaner;
- import java.lang.ref.Reference;
  
  /**
   * A confined scope, which features an owner thread. The liveness check features an additional
   * confinement check - that is, calling any operation on this scope from a thread other than the
   * owner thread will result in an exception. Because of this restriction, checking the liveness bit
--- 23,15 ---
   * questions.
   */
  
  package jdk.internal.foreign;
  
  import jdk.internal.vm.annotation.ForceInline;
  
+ import java.lang.invoke.MethodHandles;
+ import java.lang.invoke.VarHandle;
  import java.lang.ref.Cleaner;
  
  /**
   * A confined scope, which features an owner thread. The liveness check features an additional
   * confinement check - that is, calling any operation on this scope from a thread other than the
   * owner thread will result in an exception. Because of this restriction, checking the liveness bit

*** 39,14 ***
   */
  final class ConfinedScope extends ResourceScopeImpl {
  
      private boolean closed; // = false
      private int lockCount = 0;
      private final Thread owner;
  
      public ConfinedScope(Thread owner, Cleaner cleaner) {
!         super(cleaner, new ConfinedResourceList());
          this.owner = owner;
      }
  
      @ForceInline
      public final void checkValidState() {
--- 39,25 ---
   */
  final class ConfinedScope extends ResourceScopeImpl {
  
      private boolean closed; // = false
      private int lockCount = 0;
+     private int asyncReleaseCount = 0;
      private final Thread owner;
  
+     static final VarHandle ASYNC_RELEASE_COUNT;
+ 
+     static {
+         try {
+             ASYNC_RELEASE_COUNT = MethodHandles.lookup().findVarHandle(ConfinedScope.class, "asyncReleaseCount", int.class);
+         } catch (Throwable ex) {
+             throw new ExceptionInInitializerError(ex);
+         }
+     }
+ 
      public ConfinedScope(Thread owner, Cleaner cleaner) {
!         super(new ConfinedResourceList(), cleaner);
          this.owner = owner;
      }
  
      @ForceInline
      public final void checkValidState() {

*** 62,22 ***
      public boolean isAlive() {
          return !closed;
      }
  
      @Override
!     public HandleImpl acquire() {
          checkValidState();
          lockCount++;
!         return new ConfinedHandle();
      }
  
      void justClose() {
          this.checkValidState();
!         if (lockCount == 0) {
              closed = true;
          } else {
!             throw new IllegalStateException("Scope is acquired by " + lockCount + " locks");
          }
      }
  
      @Override
      public Thread ownerThread() {
--- 73,42 ---
      public boolean isAlive() {
          return !closed;
      }
  
      @Override
!     @ForceInline
+     public void acquire0() {
          checkValidState();
+         if (lockCount == MAX_FORKS) {
+             throw new IllegalStateException("Scope keep alive limit exceeded");
+         }
          lockCount++;
!     }
+ 
+     @Override
+     @ForceInline
+     public void release0() {
+         if (Thread.currentThread() == owner) {
+             lockCount--;
+         } else {
+             // It is possible to end up here in two cases: this scope was kept alive by some other confined scope
+             // which is implicitly released (in which case the release call comes from the cleaner thread). Or,
+             // this scope might be kept alive by a shared scope, which means the release call can come from any
+             // thread.
+             int value;
+             do {
+                 value = (int)ASYNC_RELEASE_COUNT.getVolatile(this);
+             } while (!ASYNC_RELEASE_COUNT.compareAndSet(this, value, value + 1));
+         }
      }
  
      void justClose() {
          this.checkValidState();
!         if (lockCount == 0 || lockCount - ((int)ASYNC_RELEASE_COUNT.getVolatile(this)) == 0) {
              closed = true;
          } else {
!             throw new IllegalStateException("Scope is kept alive by " + lockCount + " scopes");
          }
      }
  
      @Override
      public Thread ownerThread() {

*** 107,27 ***
              } else {
                  throw new IllegalStateException("Attempt to cleanup an already closed resource list");
              }
          }
      }
- 
-     /**
-      * A confined resource scope handle; no races are possible here.
-      */
-     final class ConfinedHandle implements HandleImpl {
-         boolean released = false;
- 
-         @Override
-         public ResourceScopeImpl scope() {
-             return ConfinedScope.this;
-         }
- 
-         @Override
-         public void release() {
-             checkValidState(); // thread check
-             if (!released) {
-                 released = true;
-                 lockCount--;
-             }
-         }
-     }
  }
--- 138,6 ---
< prev index next >