< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java

Print this page

  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.incubator.foreign;
 27 
 28 import jdk.internal.foreign.ResourceScopeImpl;

 29 
 30 import java.lang.invoke.MethodHandle;
 31 import java.lang.ref.Cleaner;

 32 import java.nio.channels.FileChannel;
 33 import java.nio.file.Path;
 34 import java.util.Objects;
 35 import java.util.Spliterator;
 36 
 37 /**
 38  * A resource scope manages the lifecycle of one or more resources. Resources (e.g. {@link MemorySegment}) associated
 39  * with a resource scope can only be accessed while the resource scope is <em>alive</em> (see {@link #isAlive()}),
 40  * and by the thread associated with the resource scope (if any).
 41  *
 42  * <h2>Explicit resource scopes</h2>
 43  *
 44  * Resource scopes obtained from {@link #newConfinedScope()}, {@link #newSharedScope()} support <em>deterministic deallocation</em>;
 45  * We call these resource scopes <em>explicit scopes</em>. Explicit resource scopes can be closed explicitly (see {@link ResourceScope#close()}).
 46  * When a resource scope is closed, it is no longer <em>alive</em> (see {@link #isAlive()}, and subsequent operations on
 47  * resources associated with that scope (e.g. attempting to access a {@link MemorySegment} instance) will fail with {@link IllegalStateException}.
 48  * <p>
 49  * Closing a resource scope will cause all the cleanup actions associated with that scope (see {@link #addCloseAction(Runnable)}) to be called.
 50  * Moreover, closing a resource scope might trigger the releasing of the underlying memory resources associated with said scope; for instance:
 51  * <ul>
 52  *     <li>closing the scope associated with a native memory segment results in <em>freeing</em> the native memory associated with it
 53  *     (see {@link MemorySegment#allocateNative(long, ResourceScope)}, or {@link SegmentAllocator#arenaAllocator(ResourceScope)})</li>
 54  *     <li>closing the scope associated with a mapped memory segment results in the backing memory-mapped file to be unmapped
 55  *     (see {@link MemorySegment#mapFile(Path, long, long, FileChannel.MapMode, ResourceScope)})</li>
 56  *     <li>closing the scope associated with an upcall stub results in releasing the stub
 57  *     (see {@link CLinker#upcallStub(MethodHandle, FunctionDescriptor, ResourceScope)}</li>


 58  * </ul>
 59  * <p>
 60  * Sometimes, explicit scopes can be associated with a {@link Cleaner} instance (see {@link #newConfinedScope(Cleaner)} and
 61  * {@link #newSharedScope(Cleaner)}). We call these resource scopes <em>managed</em> resource scopes. A managed resource scope
 62  * is closed automatically once the scope instance becomes <a href="../../../java/lang/ref/package.html#reachability">unreachable</a>.
 63  * <p>
 64  * Managed scopes can be useful to allow for predictable, deterministic resource deallocation, while still prevent accidental native memory leaks.
 65  * In case a managed resource scope is closed explicitly, no further action will be taken when the scope becomes unreachable;
 66  * that is, cleanup actions (see {@link #addCloseAction(Runnable)}) associated with a resource scope, whether managed or not,
 67  * are called <em>exactly once</em>.
 68  *
 69  * <h2>Implicit resource scopes</h2>









 70  *
 71  * Resource scopes obtained from {@link #newImplicitScope()} cannot be closed explicitly. We call these resource scopes
 72  * <em>implicit scopes</em>. Calling {@link #close()} on an implicit resource scope always results in an exception.
 73  * Resources associated with implicit scopes are released once the scope instance becomes
 74  * <a href="../../../java/lang/ref/package.html#reachability">unreachable</a>.
 75  * <p>
 76  * An important implicit resource scope is the so called {@linkplain #globalScope() global scope}; the global scope is
 77  * an implicit scope that is guaranteed to never become <a href="../../../java/lang/ref/package.html#reachability">unreachable</a>.
 78  * As a results, the global scope will never attempt to release resources associated with it. Such resources must, where








 79  * needed, be managed independently by clients.
 80  *
 81  * <h2><a id = "thread-confinement">Thread confinement</a></h2>
 82  *
 83  * Resource scopes can be further divided into two categories: <em>thread-confined</em> resource scopes, and <em>shared</em>
 84  * resource scopes.
 85  * <p>
 86  * Confined resource scopes (see {@link #newConfinedScope()}), support strong thread-confinement guarantees. Upon creation,
 87  * they are assigned an <em>owner thread</em>, typically the thread which initiated the creation operation (see {@link #ownerThread()}).
 88  * After creating a confined resource scope, only the owner thread will be allowed to directly manipulate the resources
 89  * associated with this resource scope. Any attempt to perform resource access from a thread other than the
 90  * owner thread will result in a runtime failure.
 91  * <p>
 92  * Shared resource scopes (see {@link #newSharedScope()} and {@link #newImplicitScope()}), on the other hand, have no owner thread;
 93  * as such resources associated with this shared resource scopes can be accessed by multiple threads.
 94  * This might be useful when multiple threads need to access the same resource concurrently (e.g. in the case of parallel processing).
 95  * For instance, a client might obtain a {@link Spliterator} from a shared segment, which can then be used to slice the
 96  * segment and allow multiple threads to work in parallel on disjoint segment slices. The following code can be used to sum
 97  * all int values in a memory segment in parallel:
 98  *
 99  * <blockquote><pre>{@code
100 SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_INT);
101 try (ResourceScope scope = ResourceScope.newSharedScope()) {

102     MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
103     VarHandle VH_int = SEQUENCE_LAYOUT.elementLayout().varHandle(int.class);
104     int sum = StreamSupport.stream(segment.spliterator(SEQUENCE_LAYOUT), true)
105         .mapToInt(s -> (int)VH_int.get(s.address()))
106         .sum();
107 }
108  * }</pre></blockquote>
109  *
110  * <p>
111  * Explicit shared resource scopes, while powerful, must be used with caution: if one or more threads accesses
112  * a resource associated with a shared scope while the scope is being closed from another thread, an exception might occur on both
113  * the accessing and the closing threads. Clients should refrain from attempting to close a shared resource scope repeatedly
114  * (e.g. keep calling {@link #close()} until no exception is thrown). Instead, clients of shared resource scopes
115  * should always ensure that proper synchronization mechanisms (e.g. using resource scope handles, see below) are put in place
116  * so that threads closing shared resource scopes can never race against threads accessing resources managed by same scopes.
117  *
118  * <h2>Resource scope handles</h2>
119  *
120  * Resource scopes can be made <em>non-closeable</em> by acquiring one or more resource scope <em>handles</em> (see
121  * {@link #acquire()}. A resource scope handle can be used to make sure that resources associated with a given resource scope
122  * (either explicit or implicit) cannot be released for a certain period of time - e.g. during a critical region of code
123  * involving one or more resources associated with the scope. For instance, an explicit resource scope can only be closed
124  * <em>after</em> all the handles acquired against that scope have been closed (see {@link Handle#close()}).
125  * This can be useful when clients need to perform a critical operation on a memory segment, during which they have
126  * to ensure that the segment will not be released; this can be done as follows:
127  *
128  * <blockquote><pre>{@code
129 MemorySegment segment = ...
130 ResourceScope.Handle segmentHandle = segment.scope().acquire()
131 try {
132    <critical operation on segment>
133 } finally {
134    segment.scope().release(segmentHandle);
135 }
136  * }</pre></blockquote>
137  *
138  * Acquiring implicit resource scopes is also possible, but it is often unnecessary: since resources associated with
139  * an implicit scope will only be released when the scope becomes <a href="../../../java/lang/ref/package.html#reachability">unreachable</a>,
140  * clients can use e.g. {@link java.lang.ref.Reference#reachabilityFence(Object)} to make sure that resources associated
141  * with implicit scopes are not released prematurely. That said, the above code snippet works (trivially) for implicit scopes too.
142  *
143  * @implSpec
144  * Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
145  */
146 public sealed interface ResourceScope extends AutoCloseable permits ResourceScopeImpl {
147     /**
148      * Is this resource scope alive?
149      * @return true, if this resource scope is alive.
150      * @see ResourceScope#close()
151      */
152     boolean isAlive();
153 
154     /**
155      * The thread owning this resource scope.
156      * @return the thread owning this resource scope, or {@code null} if this resource scope is shared.
157      */
158     Thread ownerThread();
159 
160     /**
161      * Is this resource scope an <em>implicit scope</em>?
162      * @return true if this scope is an <em>implicit scope</em>.
163      * @see #newImplicitScope()
164      * @see #globalScope()
165      */
166     boolean isImplicit();
167 
168     /**
169      * Closes this resource scope. As a side-effect, if this operation completes without exceptions, this scope will be marked
170      * as <em>not alive</em>, and subsequent operations on resources associated with this scope will fail with {@link IllegalStateException}.
171      * Additionally, upon successful closure, all native resources associated with this resource scope will be released.
172      *
173      * @apiNote This operation is not idempotent; that is, closing an already closed resource scope <em>always</em> results in an
174      * exception being thrown. This reflects a deliberate design choice: resource scope state transitions should be
175      * manifest in the client code; a failure in any of these transitions reveals a bug in the underlying application
176      * logic.
177      *
178      * @throws IllegalStateException if one of the following condition is met:
179      * <ul>
180      *     <li>this resource scope is not <em>alive</em>
181      *     <li>this resource scope is confined, and this method is called from a thread other than the thread owning this resource scope</li>
182      *     <li>this resource scope is shared and a resource associated with this scope is accessed while this method is called</li>
183      *     <li>one or more handles (see {@link #acquire()}) associated with this resource scope have not been {@linkplain #release(Handle) released}</li>
184      * </ul>
185      * @throws UnsupportedOperationException if this resource scope is {@linkplain #isImplicit() implicit}.
186      */
187     void close();
188 
189     /**
190      * Add a custom cleanup action which will be executed when the resource scope is closed.
191      * The order in which custom cleanup actions are invoked once the scope is closed is unspecified.
192      * @param runnable the custom cleanup action to be associated with this scope.
193      * @throws IllegalStateException if this scope has already been closed.

194      */
195     void addCloseAction(Runnable runnable);
196 
197     /**
198      * Acquires a resource scope handle associated with this resource scope. An explicit resource scope cannot be
199      * {@linkplain #close() closed} until all the resource scope handles acquired from it have been {@linkplain #release(Handle)} released}.
200      * @return a resource scope handle.
201      */
202     Handle acquire();
203 
204     /**
205      * Release the provided resource scope handle. This method is idempotent, that is, releasing the same handle
206      * multiple times has no effect.
207      * @param handle the resource scope handle to be released.
208      * @throws IllegalArgumentException if the provided handle is not associated with this scope.
209      */
210     void release(Handle handle);
211 
212     /**
213      * An abstraction modelling a resource scope handle. A resource scope handle is typically {@linkplain #acquire() acquired} by clients
214      * in order to prevent an explicit resource scope from being closed while executing a certain operation.
215      * Once obtained, resource scope handles can be {@linkplain #release(Handle)} released}; an explicit resource scope can
216      * be closed only <em>after</em> all the resource scope handles acquired from it have been released.
217      */
218     sealed interface Handle permits ResourceScopeImpl.HandleImpl {
219 
220         /**
221          * Returns the resource scope associated with this handle.
222          * @return the resource scope associated with this handle.
223          */
224         ResourceScope scope();
225     }
226 
227     /**
228      * Create a new confined scope. The resulting scope is closeable, and is not managed by a {@link Cleaner}.
229      * @return a new confined scope.
230      */
231     static ResourceScope newConfinedScope() {
232         return ResourceScopeImpl.createConfined( null);
233     }
234 
235     /**
236      * Create a new confined scope managed by a {@link Cleaner}.
237      * @param cleaner the cleaner to be associated with the returned scope.
238      * @return a new confined scope, managed by {@code cleaner}.
239      * @throws NullPointerException if {@code cleaner == null}.
240      */
241     static ResourceScope newConfinedScope(Cleaner cleaner) {
242         Objects.requireNonNull(cleaner);
243         return ResourceScopeImpl.createConfined( cleaner);
244     }
245 
246     /**
247      * Create a new shared scope. The resulting scope is closeable, and is not managed by a {@link Cleaner}.
248      * @return a new shared scope.
249      */
250     static ResourceScope newSharedScope() {
251         return ResourceScopeImpl.createShared(null);
252     }
253 
254     /**
255      * Create a new shared scope managed by a {@link Cleaner}.
256      * @param cleaner the cleaner to be associated with the returned scope.
257      * @return a new shared scope, managed by {@code cleaner}.
258      * @throws NullPointerException if {@code cleaner == null}.
259      */
260     static ResourceScope newSharedScope(Cleaner cleaner) {
261         Objects.requireNonNull(cleaner);
262         return ResourceScopeImpl.createShared(cleaner);
263     }
264 
265     /**
266      * Create a new <em>implicit scope</em>. The implicit scope is a managed, shared, and non-closeable scope which only features
267      * <a href="ResourceScope.html#implicit-closure"><em>implicit closure</em></a>.
268      * Since implicit scopes can only be closed implicitly by the garbage collector, it is recommended that implicit
269      * scopes are only used in cases where deallocation performance is not a critical concern, to avoid unnecessary
270      * memory pressure.
271      *
272      * @return a new implicit scope.
273      */
274     static ResourceScope newImplicitScope() {
275         return ResourceScopeImpl.createImplicitScope();
276     }
277 
278     /**
279      * Returns an implicit scope which is assumed to be always alive.
280      * @return the global scope.
281      */
282     static ResourceScope globalScope() {
283         return ResourceScopeImpl.GLOBAL;
284     }
285 }

  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.incubator.foreign;
 27 
 28 import jdk.internal.foreign.ResourceScopeImpl;
 29 import jdk.internal.ref.CleanerFactory;
 30 
 31 import java.lang.invoke.MethodHandle;
 32 import java.lang.ref.Cleaner;
 33 import java.nio.ByteBuffer;
 34 import java.nio.channels.FileChannel;
 35 import java.nio.file.Path;
 36 import java.util.Objects;
 37 import java.util.Spliterator;
 38 
 39 /**
 40  * A resource scope manages the lifecycle of one or more resources. Resources (e.g. {@link MemorySegment}) associated
 41  * with a resource scope can only be accessed while the resource scope is {@linkplain #isAlive() alive},
 42  * and by the {@linkplain #ownerThread() thread} associated with the resource scope (if any).
 43  *
 44  * <h2>Deterministic deallocation</h2>
 45  *
 46  * Resource scopes support <em>deterministic deallocation</em>; that is, they can be {@linkplain ResourceScope#close() closed}
 47  * explicitly. When a resource scope is closed, it is no longer {@link #isAlive() alive}, and subsequent
 48  * operations on resources associated with that scope (e.g. attempting to access a {@link MemorySegment} instance)
 49  * will fail with {@link IllegalStateException}.
 50  * <p>
 51  * Closing a resource scope will cause all the {@linkplain #addCloseAction(Runnable) close actions} associated with that scope to be called.
 52  * Moreover, closing a resource scope might trigger the releasing of the underlying memory resources associated with said scope; for instance:
 53  * <ul>
 54  *     <li>closing the scope associated with a {@linkplain MemorySegment#allocateNative(long, long, ResourceScope) native memory segment}
 55  *     results in <em>freeing</em> the native memory associated with it;</li>
 56  *     <li>closing the scope associated with a {@linkplain MemorySegment#mapFile(Path, long, long, FileChannel.MapMode, ResourceScope) mapped memory segment}
 57  *     results in the backing memory-mapped file to be unmapped;</li>
 58  *     <li>closing the scope associated with an {@linkplain CLinker#upcallStub(MethodHandle, FunctionDescriptor, ResourceScope) upcall stub}
 59  *     results in releasing the stub;</li>
 60  *     <li>closing the scope associated with a {@linkplain VaList variable arity list} results in releasing the memory
 61  *     associated with that variable arity list instance.</li>
 62  * </ul>









 63  *
 64  * <h2>Implicit deallocation</h2>
 65  *
 66  * Resource scopes can be associated with a {@link Cleaner} instance, so that they are also closed automatically,
 67  * once the scope instance becomes <a href="../../../java/lang/ref/package.html#reachability">unreachable</a>.
 68  * This can be useful to allow for predictable, deterministic resource deallocation, while still preventing accidental
 69  * native memory leaks. In case a managed resource scope is closed explicitly, no further action will be taken when
 70  * the scope becomes unreachable; that is, {@linkplain #addCloseAction(Runnable) close actions} associated with a
 71  * resource scope, whether managed or not, are called <em>exactly once</em>.
 72  *
 73  * <h2><a id = "global-scope">Global scope</a></h2>
 74  *





 75  * An important implicit resource scope is the so called {@linkplain #globalScope() global scope}; the global scope is
 76  * a resource scope that cannot be closed, either explicitly or implicitly. As a result, the global scope will never
 77  * attempt to release resources associated with it. Examples of resources associated with the global scope are:
 78  * <ul>
 79  *     <li>heap segments created from {@linkplain MemorySegment#ofArray(int[]) arrays} or
 80  *     {@linkplain MemorySegment#ofByteBuffer(ByteBuffer) buffers};</li>
 81  *     <li>variable arity lists {@linkplain VaList#ofAddress(MemoryAddress, ResourceScope) obtained} from raw memory addresses;
 82  *     <li>native symbols {@linkplain SymbolLookup#lookup(String) obtained} from a {@linkplain SymbolLookup#loaderLookup() loader lookup},
 83  *     or from the {@link CLinker}.</li>
 84  * </ul>
 85  * In other words, the global scope is used to indicate that the lifecycle of one or more resources must, where
 86  * needed, be managed independently by clients.
 87  *
 88  * <h2><a id = "thread-confinement">Thread confinement</a></h2>
 89  *
 90  * Resource scopes can be divided into two categories: <em>thread-confined</em> resource scopes, and <em>shared</em>
 91  * resource scopes.
 92  * <p>
 93  * {@linkplain #newConfinedScope() Confined resource scopes}, support strong thread-confinement guarantees. Upon creation,
 94  * they are assigned an {@linkplain #ownerThread() owner thread}, typically the thread which initiated the creation operation.
 95  * After creating a confined resource scope, only the owner thread will be allowed to directly manipulate the resources
 96  * associated with this resource scope. Any attempt to perform resource access from a thread other than the
 97  * owner thread will result in a runtime failure.
 98  * <p>
 99  * {@linkplain #newSharedScope() Shared resource scopes}, on the other hand, have no owner thread;
100  * as such, resources associated with shared resource scopes can be accessed by multiple threads.
101  * This might be useful when multiple threads need to access the same resource concurrently (e.g. in the case of parallel processing).
102  * For instance, a client might obtain a {@link Spliterator} from a segment backed by a shared scope, which can then be used to slice the
103  * segment and allow multiple threads to work in parallel on disjoint segment slices. The following code can be used to sum
104  * all int values in a memory segment in parallel:
105  *
106  * <blockquote><pre>{@code

107 try (ResourceScope scope = ResourceScope.newSharedScope()) {
108     SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
109     MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
110     int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
111                         .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
112                         .sum();

113 }
114  * }</pre></blockquote>
115  *
116  * <p>
117  * Shared resource scopes, while powerful, must be used with caution: if one or more threads accesses
118  * a resource associated with a shared scope while the scope is being closed from another thread, an exception might occur on both
119  * the accessing and the closing threads. Clients should refrain from attempting to close a shared resource scope repeatedly
120  * (e.g. keep calling {@link #close()} until no exception is thrown). Instead, clients of shared resource scopes
121  * should always ensure that proper synchronization mechanisms (e.g. using temporal dependencies, see below) are put in place
122  * so that threads closing shared resource scopes can never race against threads accessing resources managed by same scopes.
123  *
124  * <h2>Temporal dependencies</h2>
125  *
126  * Resource scopes can depend on each other. More specifically, a scope can feature
127  * {@linkplain #keepAlive(ResourceScope) temporal dependencies} on one or more other resource scopes.
128  * Such a resource scope cannot be closed (either implicitly or explicitly) until <em>all</em> the scopes it depends on
129  * have also been closed.
130  * <p>
131  * This can be useful when clients need to perform a critical operation on a memory segment, during which they have
132  * to ensure that the scope associated with that segment will not be closed; this can be done as follows:
133  *
134  * <blockquote><pre>{@code
135 MemorySegment segment = ...
136 try (ResourceScope criticalScope = ResourceScope.newConfinedScope()) {
137     criticalScope.keepAlive(segment.scope());
138     <critical operation on segment>


139 }
140  * }</pre></blockquote>
141  *
142  * Note that a resource scope does not become <a href="../../../java/lang/ref/package.html#reachability">unreachable</a>
143  * until all the scopes it depends on have been closed.


144  *
145  * @implSpec
146  * Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
147  */
148 public sealed interface ResourceScope extends AutoCloseable permits ResourceScopeImpl {
149     /**
150      * Is this resource scope alive?
151      * @return true, if this resource scope is alive.
152      * @see ResourceScope#close()
153      */
154     boolean isAlive();
155 
156     /**
157      * The thread owning this resource scope.
158      * @return the thread owning this resource scope, or {@code null} if this resource scope is shared.
159      */
160     Thread ownerThread();
161 
162     /**
163      * Closes this resource scope. As a side effect, if this operation completes without exceptions, this scope will be marked








164      * as <em>not alive</em>, and subsequent operations on resources associated with this scope will fail with {@link IllegalStateException}.
165      * Additionally, upon successful closure, all native resources associated with this resource scope will be released.
166      *
167      * @apiNote This operation is not idempotent; that is, closing an already closed resource scope <em>always</em> results in an
168      * exception being thrown. This reflects a deliberate design choice: resource scope state transitions should be
169      * manifest in the client code; a failure in any of these transitions reveals a bug in the underlying application
170      * logic.
171      *
172      * @throws IllegalStateException if one of the following condition is met:
173      * <ul>
174      *     <li>this resource scope is not <em>alive</em>
175      *     <li>this resource scope is confined, and this method is called from a thread other than the thread owning this resource scope</li>
176      *     <li>this resource scope is shared and a resource associated with this scope is accessed while this method is called</li>
177      *     <li>one or more scopes which {@linkplain #keepAlive(ResourceScope) depend} on this resource scope have not been closed.
178      * </ul>
179      * @throws UnsupportedOperationException if this resource scope is the {@linkplain #globalScope() global scope}.
180      */
181     void close();
182 
183     /**
184      * Add a custom cleanup action which will be executed when the resource scope is closed.
185      * The order in which custom cleanup actions are invoked once the scope is closed is unspecified.
186      * @param runnable the custom cleanup action to be associated with this scope.
187      * @throws IllegalStateException if this scope has been closed, or if access occurs from
188      * a thread other than the thread owning this scope.
189      */
190     void addCloseAction(Runnable runnable);
191 
192     /**
193      * Creates a temporal dependency between this scope and the target scope. As a result, the target scope cannot
194      * be {@linkplain #close() closed} <em>before</em> this scope.
195      * @implNote A given scope can support up to {@link Integer#MAX_VALUE} pending keep alive requests.
196      * @param target the scope that needs to be kept alive.
197      * @throws IllegalArgumentException if {@code target == this}.
198      * @throws IllegalStateException if this scope or {@code target} have been closed, or if access occurs from
199      * a thread other than the thread owning this scope or {@code target}.












200      */
201     void keepAlive(ResourceScope target);







202 
203     /**
204      * Creates a new confined scope.
205      * @return a new confined scope.
206      */
207     static ResourceScope newConfinedScope() {
208         return ResourceScopeImpl.createConfined( Thread.currentThread(), null);
209     }
210 
211     /**
212      * Creates a new confined scope, managed by the provided cleaner instance.
213      * @param cleaner the cleaner to be associated with the returned scope.
214      * @return a new confined scope, managed by {@code cleaner}.

215      */
216     static ResourceScope newConfinedScope(Cleaner cleaner) {
217         Objects.requireNonNull(cleaner);
218         return ResourceScopeImpl.createConfined(Thread.currentThread(), cleaner);
219     }
220 
221     /**
222      * Creates a new shared scope.
223      * @return a new shared scope.
224      */
225     static ResourceScope newSharedScope() {
226         return ResourceScopeImpl.createShared(null);
227     }
228 
229     /**
230      * Creates a new shared scope, managed by the provided cleaner instance.
231      * @param cleaner the cleaner to be associated with the returned scope.
232      * @return a new shared scope, managed by {@code cleaner}.

233      */
234     static ResourceScope newSharedScope(Cleaner cleaner) {
235         Objects.requireNonNull(cleaner);
236         return ResourceScopeImpl.createShared(cleaner);
237     }
238 
239     /**
240      * Creates a new shared scope, managed by a private {@link Cleaner} instance. Equivalent to (but likely more efficient than)
241      * the following code:
242      * <pre>{@code
243     newSharedScope(Cleaner.create());
244      * }</pre>
245      * @return a shared scope, managed by a private {@link Cleaner} instance.

246      */
247     static ResourceScope newImplicitScope() {
248         return newSharedScope(CleanerFactory.cleaner());
249     }
250 
251     /**
252      * Returns the <a href="ResourceScope.html#global-scope"><em>global scope</em></a>.
253      * @return the <a href="ResourceScope.html#global-scope"><em>global scope</em></a>.
254      */
255     static ResourceScope globalScope() {
256         return ResourceScopeImpl.GLOBAL;
257     }
258 }
< prev index next >