Path: blob/master/src/java.base/share/classes/sun/nio/fs/Cancellable.java
41159 views
/*1* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.fs;2627import jdk.internal.misc.Unsafe;28import java.util.concurrent.ExecutionException;2930/**31* Base implementation of a task (typically native) that polls a memory location32* during execution so that it may be aborted/cancelled before completion. The33* task is executed by invoking the {@link runInterruptibly} method defined34* here and cancelled by invoking Thread.interrupt.35*/3637abstract class Cancellable implements Runnable {38private static final Unsafe unsafe = Unsafe.getUnsafe();3940private final long pollingAddress;41private final Object lock = new Object();4243// the following require lock when examining or changing44private boolean completed;45private Throwable exception;4647protected Cancellable() {48pollingAddress = unsafe.allocateMemory(4);49unsafe.putIntVolatile(null, pollingAddress, 0);50}5152/**53* Returns the memory address of a 4-byte int that should be polled to54* detect cancellation.55*/56protected long addressToPollForCancel() {57return pollingAddress;58}5960/**61* The value to write to the polled memory location to indicate that the62* task has been cancelled. If this method is not overridden then it63* defaults to MAX_VALUE.64*/65protected int cancelValue() {66return Integer.MAX_VALUE;67}6869/**70* "cancels" the task by writing bits into memory location that it polled71* by the task.72*/73final void cancel() {74synchronized (lock) {75if (!completed) {76unsafe.putIntVolatile(null, pollingAddress, cancelValue());77}78}79}8081/**82* Returns the exception thrown by the task or null if the task completed83* successfully.84*/85private Throwable exception() {86synchronized (lock) {87return exception;88}89}9091@Override92public final void run() {93try {94implRun();95} catch (Throwable t) {96synchronized (lock) {97exception = t;98}99} finally {100synchronized (lock) {101completed = true;102unsafe.freeMemory(pollingAddress);103}104}105}106107/**108* The task body. This should periodically poll the memory location109* to check for cancellation.110*/111abstract void implRun() throws Throwable;112113/**114* Invokes the given task in its own thread. If this (meaning the current)115* thread is interrupted then an attempt is make to cancel the background116* thread by writing into the memory location that it polls cooperatively.117*/118static void runInterruptibly(Cancellable task) throws ExecutionException {119Thread t = new Thread(null, task, "NIO-Task", 0, false);120t.start();121boolean cancelledByInterrupt = false;122while (t.isAlive()) {123try {124t.join();125} catch (InterruptedException e) {126cancelledByInterrupt = true;127task.cancel();128}129}130if (cancelledByInterrupt)131Thread.currentThread().interrupt();132Throwable exc = task.exception();133if (exc != null)134throw new ExecutionException(exc);135}136}137138139