/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 * This file is available under and governed by the GNU General Public
 * License version 2 only, as published by the Free Software Foundation.
 * However, the following notice accompanied the original version of this
 * file:
 *
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/licenses/publicdomain
 */

/*
 * @test
 * @bug 4486658
 * @compile -source 1.5 CancelledFutureLoops.java
 * @run main/timeout=2000 CancelledFutureLoops
 * @summary Checks for responsiveness of futures to cancellation.
 * Runs under the assumption that ITERS computations require more than
 * TIMEOUT msecs to complete.
 */

import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import java.util.*;

public final class CancelledFutureLoops {
    static final ExecutorService pool = Executors.newCachedThreadPool();
    static final LoopHelpers.SimpleRandom rng = new LoopHelpers.SimpleRandom();
    static boolean print = false;
    static final int ITERS = 1000000;
    static final long TIMEOUT = 100;

    public static void main(String[] args) throws Exception {
        int maxThreads = 5;
        if (args.length > 0)
            maxThreads = Integer.parseInt(args[0]);

        print = true;

        for (int i = 2; i <= maxThreads; i += (i+1) >>> 1) {
            System.out.print("Threads: " + i);
            try {
                new FutureLoop(i).test();
            }
            catch(BrokenBarrierException bb) {
                // OK; ignore
            }
            catch(ExecutionException ee) {
                // OK; ignore
            }
            Thread.sleep(TIMEOUT);
        }
        pool.shutdown();
        if (! pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS))
            throw new Error();
    }

    static final class FutureLoop implements Callable {
        private int v = rng.next();
        private final ReentrantLock lock = new ReentrantLock();
        private final LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
        private final CyclicBarrier barrier;
        private final int nthreads;
        FutureLoop(int nthreads) {
            this.nthreads = nthreads;
            barrier = new CyclicBarrier(nthreads+1, timer);
        }

        final void test() throws Exception {
            Future[] futures = new Future[nthreads];
            for (int i = 0; i < nthreads; ++i)
                futures[i] = pool.submit(this);

            barrier.await();
            Thread.sleep(TIMEOUT);
            boolean tooLate = false;
            for (int i = 1; i < nthreads; ++i) {
                if (!futures[i].cancel(true))
                    tooLate = true;
                // Unbunch some of the cancels
                if ( (i & 3) == 0)
                    Thread.sleep(1 + rng.next() % 10);
            }

            Object f0 = futures[0].get();
            if (!tooLate) {
                for (int i = 1; i < nthreads; ++i) {
                    if (!futures[i].isDone() || !futures[i].isCancelled())
                        throw new Error("Only one thread should complete");
                }
            }
            else
                System.out.print("(cancelled too late) ");

            long endTime = System.nanoTime();
            long time = endTime - timer.startTime;
            if (print) {
                double secs = (double)(time) / 1000000000.0;
                System.out.println("\t " + secs + "s run time");
            }

        }

        public final Object call() throws Exception {
            barrier.await();
            int sum = v;
            int x = 0;
            int n = ITERS;
            while (n-- > 0) {
                lock.lockInterruptibly();
                try {
                    v = x = LoopHelpers.compute1(v);
                }
                finally {
                    lock.unlock();
                }
                sum += LoopHelpers.compute2(LoopHelpers.compute2(x));
            }
            return new Integer(sum);
        }
    }

}
