/*
 * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.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/publicdomain/zero/1.0/
 */

/*
 * @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);
        }
    }

}
