1e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera/* 2e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. 3e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * 5e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * This code is free software; you can redistribute it and/or modify it 6e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * under the terms of the GNU General Public License version 2 only, as 7e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * published by the Free Software Foundation. Oracle designates this 8e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * particular file as subject to the "Classpath" exception as provided 9e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * by Oracle in the LICENSE file that accompanied this code. 10e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * 11e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * This code is distributed in the hope that it will be useful, but WITHOUT 12e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * version 2 for more details (a copy is included in the LICENSE file that 15e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * accompanied this code). 16e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * 17e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * You should have received a copy of the GNU General Public License version 18e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * 2 along with this work; if not, write to the Free Software Foundation, 19e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * 21e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * or visit www.oracle.com if you need additional information or have any 23e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * questions. 24e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera */ 25e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 26e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmerapackage sun.nio.fs; 27e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 28e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmeraimport sun.misc.Unsafe; 29e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmeraimport java.util.concurrent.ExecutionException; 30e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 31e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera/** 32e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * Base implementation of a task (typically native) that polls a memory location 33e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * during execution so that it may be aborted/cancelled before completion. The 34e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * task is executed by invoking the {@link runInterruptibly} method defined 35e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * here and cancelled by invoking Thread.interrupt. 36e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera */ 37e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 38e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmeraabstract class Cancellable implements Runnable { 39e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera private static final Unsafe unsafe = Unsafe.getUnsafe(); 40e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 41e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera private final long pollingAddress; 42e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera private final Object lock = new Object(); 43e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 44e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera // the following require lock when examining or changing 45e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera private boolean completed; 46e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera private Throwable exception; 47e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 48e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera protected Cancellable() { 49e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera pollingAddress = unsafe.allocateMemory(4); 50e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera unsafe.putIntVolatile(null, pollingAddress, 0); 51e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 52e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 53e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera /** 54e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * Returns the memory address of a 4-byte int that should be polled to 55e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * detect cancellation. 56e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera */ 57e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera protected long addressToPollForCancel() { 58e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera return pollingAddress; 59e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 60e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 61e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera /** 62e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * The value to write to the polled memory location to indicate that the 63e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * task has been cancelled. If this method is not overridden then it 64e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * defaults to MAX_VALUE. 65e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera */ 66e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera protected int cancelValue() { 67e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera return Integer.MAX_VALUE; 68e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 69e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 70e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera /** 71e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * "cancels" the task by writing bits into memory location that it polled 72e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * by the task. 73e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera */ 74e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera final void cancel() { 75e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera synchronized (lock) { 76e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera if (!completed) { 77e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera unsafe.putIntVolatile(null, pollingAddress, cancelValue()); 78e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 79e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 80e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 81e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 82e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera /** 83e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * Returns the exception thrown by the task or null if the task completed 84e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * successfully. 85e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera */ 86e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera private Throwable exception() { 87e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera synchronized (lock) { 88e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera return exception; 89e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 90e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 91e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 92e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera @Override 93e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera public final void run() { 94e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera try { 95e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera implRun(); 96e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } catch (Throwable t) { 97e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera synchronized (lock) { 98e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera exception = t; 99e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 100e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } finally { 101e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera synchronized (lock) { 102e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera completed = true; 103e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera unsafe.freeMemory(pollingAddress); 104e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 105e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 106e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 107e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 108e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera /** 109e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * The task body. This should periodically poll the memory location 110e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * to check for cancellation. 111e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera */ 112e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera abstract void implRun() throws Throwable; 113e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera 114e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera /** 115e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * Invokes the given task in its own thread. If this (meaning the current) 116e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * thread is interrupted then an attempt is make to cancel the background 117e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * thread by writing into the memory location that it polls cooperatively. 118e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera */ 119e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera static void runInterruptibly(Cancellable task) throws ExecutionException { 120e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera Thread t = new Thread(task); 121e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera t.start(); 122e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera boolean cancelledByInterrupt = false; 123e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera while (t.isAlive()) { 124e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera try { 125e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera t.join(); 126e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } catch (InterruptedException e) { 127e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera cancelledByInterrupt = true; 128e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera task.cancel(); 129e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 130e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 131e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera if (cancelledByInterrupt) 132e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera Thread.currentThread().interrupt(); 133e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera Throwable exc = task.exception(); 134e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera if (exc != null) 135e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera throw new ExecutionException(exc); 136e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera } 137e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera} 138