< prev index next >

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

Print this page

  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package jdk.internal.foreign;
 27 
 28 import jdk.incubator.foreign.ResourceScope;
 29 import jdk.internal.vm.annotation.ForceInline;
 30 


 31 import java.lang.ref.Cleaner;
 32 import java.lang.ref.Reference;
 33 
 34 /**
 35  * A confined scope, which features an owner thread. The liveness check features an additional
 36  * confinement check - that is, calling any operation on this scope from a thread other than the
 37  * owner thread will result in an exception. Because of this restriction, checking the liveness bit
 38  * can be performed in plain mode.
 39  */
 40 final class ConfinedScope extends ResourceScopeImpl {
 41 
 42     private boolean closed; // = false
 43     private int lockCount = 0;

 44     private final Thread owner;
 45 










 46     public ConfinedScope(Thread owner, Cleaner cleaner) {
 47         super(cleaner, new ConfinedResourceList());
 48         this.owner = owner;
 49     }
 50 
 51     @ForceInline
 52     public final void checkValidState() {
 53         if (owner != Thread.currentThread()) {
 54             throw new IllegalStateException("Attempted access outside owning thread");
 55         }
 56         if (closed) {
 57             throw new IllegalStateException("Already closed");
 58         }
 59     }
 60 
 61     @Override
 62     public boolean isAlive() {
 63         return !closed;
 64     }
 65 
 66     @Override
 67     public HandleImpl acquire() {

 68         checkValidState();



 69         lockCount++;
 70         return new ConfinedHandle();
















 71     }
 72 
 73     void justClose() {
 74         this.checkValidState();
 75         if (lockCount == 0) {
 76             closed = true;
 77         } else {
 78             throw new IllegalStateException("Scope is acquired by " + lockCount + " locks");
 79         }
 80     }
 81 
 82     @Override
 83     public Thread ownerThread() {
 84         return owner;
 85     }
 86 
 87     /**
 88      * A confined resource list; no races are possible here.
 89      */
 90     static final class ConfinedResourceList extends ResourceList {
 91         @Override
 92         void add(ResourceCleanup cleanup) {
 93             if (fst != ResourceCleanup.CLOSED_LIST) {
 94                 cleanup.next = fst;
 95                 fst = cleanup;
 96             } else {
 97                 throw new IllegalStateException("Already closed!");
 98             }
 99         }
100 
101         @Override
102         void cleanup() {
103             if (fst != ResourceCleanup.CLOSED_LIST) {
104                 ResourceCleanup prev = fst;
105                 fst = ResourceCleanup.CLOSED_LIST;
106                 cleanup(prev);
107             } else {
108                 throw new IllegalStateException("Attempt to cleanup an already closed resource list");
109             }
110         }
111     }
112 
113     /**
114      * A confined resource scope handle; no races are possible here.
115      */
116     final class ConfinedHandle implements HandleImpl {
117         boolean released = false;
118 
119         @Override
120         public ResourceScopeImpl scope() {
121             return ConfinedScope.this;
122         }
123 
124         @Override
125         public void release() {
126             checkValidState(); // thread check
127             if (!released) {
128                 released = true;
129                 lockCount--;
130             }
131         }
132     }
133 }

  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package jdk.internal.foreign;
 27 

 28 import jdk.internal.vm.annotation.ForceInline;
 29 
 30 import java.lang.invoke.MethodHandles;
 31 import java.lang.invoke.VarHandle;
 32 import java.lang.ref.Cleaner;

 33 
 34 /**
 35  * A confined scope, which features an owner thread. The liveness check features an additional
 36  * confinement check - that is, calling any operation on this scope from a thread other than the
 37  * owner thread will result in an exception. Because of this restriction, checking the liveness bit
 38  * can be performed in plain mode.
 39  */
 40 final class ConfinedScope extends ResourceScopeImpl {
 41 
 42     private boolean closed; // = false
 43     private int lockCount = 0;
 44     private int asyncReleaseCount = 0;
 45     private final Thread owner;
 46 
 47     static final VarHandle ASYNC_RELEASE_COUNT;
 48 
 49     static {
 50         try {
 51             ASYNC_RELEASE_COUNT = MethodHandles.lookup().findVarHandle(ConfinedScope.class, "asyncReleaseCount", int.class);
 52         } catch (Throwable ex) {
 53             throw new ExceptionInInitializerError(ex);
 54         }
 55     }
 56 
 57     public ConfinedScope(Thread owner, Cleaner cleaner) {
 58         super(new ConfinedResourceList(), cleaner);
 59         this.owner = owner;
 60     }
 61 
 62     @ForceInline
 63     public final void checkValidState() {
 64         if (owner != Thread.currentThread()) {
 65             throw new IllegalStateException("Attempted access outside owning thread");
 66         }
 67         if (closed) {
 68             throw new IllegalStateException("Already closed");
 69         }
 70     }
 71 
 72     @Override
 73     public boolean isAlive() {
 74         return !closed;
 75     }
 76 
 77     @Override
 78     @ForceInline
 79     public void acquire0() {
 80         checkValidState();
 81         if (lockCount == MAX_FORKS) {
 82             throw new IllegalStateException("Scope keep alive limit exceeded");
 83         }
 84         lockCount++;
 85     }
 86 
 87     @Override
 88     @ForceInline
 89     public void release0() {
 90         if (Thread.currentThread() == owner) {
 91             lockCount--;
 92         } else {
 93             // It is possible to end up here in two cases: this scope was kept alive by some other confined scope
 94             // which is implicitly released (in which case the release call comes from the cleaner thread). Or,
 95             // this scope might be kept alive by a shared scope, which means the release call can come from any
 96             // thread.
 97             int value;
 98             do {
 99                 value = (int)ASYNC_RELEASE_COUNT.getVolatile(this);
100             } while (!ASYNC_RELEASE_COUNT.compareAndSet(this, value, value + 1));
101         }
102     }
103 
104     void justClose() {
105         this.checkValidState();
106         if (lockCount == 0 || lockCount - ((int)ASYNC_RELEASE_COUNT.getVolatile(this)) == 0) {
107             closed = true;
108         } else {
109             throw new IllegalStateException("Scope is kept alive by " + lockCount + " scopes");
110         }
111     }
112 
113     @Override
114     public Thread ownerThread() {
115         return owner;
116     }
117 
118     /**
119      * A confined resource list; no races are possible here.
120      */
121     static final class ConfinedResourceList extends ResourceList {
122         @Override
123         void add(ResourceCleanup cleanup) {
124             if (fst != ResourceCleanup.CLOSED_LIST) {
125                 cleanup.next = fst;
126                 fst = cleanup;
127             } else {
128                 throw new IllegalStateException("Already closed!");
129             }
130         }
131 
132         @Override
133         void cleanup() {
134             if (fst != ResourceCleanup.CLOSED_LIST) {
135                 ResourceCleanup prev = fst;
136                 fst = ResourceCleanup.CLOSED_LIST;
137                 cleanup(prev);
138             } else {
139                 throw new IllegalStateException("Attempt to cleanup an already closed resource list");
140             }
141         }
142     }





















143 }
< prev index next >