/*
 * Copyright 2006-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * 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.
 */

/*
 * @test
 * @bug 6503247 6574123
 * @summary Test resilience to tryAcquire methods that throw
 * @author Martin Buchholz
 */

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

/**
 * This uses a variant of the standard Mutex demo, except with a
 * tryAcquire method that randomly throws various Throwable
 * subclasses.
 */
@SuppressWarnings({"deprecation", "serial"})
public class FlakyMutex implements Lock {
    static class MyError extends Error {}
    static class MyException extends Exception {}
    static class MyRuntimeException extends RuntimeException {}

    static final Random rnd = new Random();

    static void maybeThrow() {
        switch (rnd.nextInt(10)) {
        case 0: throw new MyError();
        case 1: throw new MyRuntimeException();
        case 2: Thread.currentThread().stop(new MyException()); break;
        default: /* Do nothing */ break;
        }
    }

    static void checkThrowable(Throwable t) {
        check((t instanceof MyError) ||
              (t instanceof MyException) ||
              (t instanceof MyRuntimeException));
    }

    static void realMain(String[] args) throws Throwable {
        final int nThreads = 3;
        final CyclicBarrier barrier = new CyclicBarrier(nThreads + 1);
        final FlakyMutex m = new FlakyMutex();
        final ExecutorService es = Executors.newFixedThreadPool(nThreads);
        for (int i = 0; i < nThreads; i++) {
            es.submit(new Runnable() { public void run() {
                try {
                    barrier.await();
                    for (int i = 0; i < 10000; i++) {
                        for (;;) {
                            try { m.lock(); break; }
                            catch (Throwable t) { checkThrowable(t); }
                        }

                        try { check (! m.tryLock()); }
                        catch (Throwable t) { checkThrowable(t); }

                        try { check (! m.tryLock(1, TimeUnit.MICROSECONDS)); }
                        catch (Throwable t) { checkThrowable(t); }

                        m.unlock();
                    }
                } catch (Throwable t) { unexpected(t); }}});}
        barrier.await();
        es.shutdown();
        check(es.awaitTermination(10, TimeUnit.SECONDS));
    }

    private static class FlakySync extends AbstractQueuedLongSynchronizer {
        private static final long serialVersionUID = -1L;

        public boolean isHeldExclusively() { return getState() == 1; }

        public boolean tryAcquire(long acquires) {
            // Sneak in some tests for queue state
            if (hasQueuedPredecessors())
                check(getFirstQueuedThread() != Thread.currentThread());
            if (getFirstQueuedThread() == Thread.currentThread()) {
                check(hasQueuedThreads());
                check(!hasQueuedPredecessors());
            } else {
                // Might be true, but only transiently
                do {} while (hasQueuedPredecessors() != hasQueuedThreads());
            }

            maybeThrow();
            return compareAndSetState(0, 1);
        }

        public boolean tryRelease(long releases) {
            setState(0);
            return true;
        }

        Condition newCondition() { return new ConditionObject(); }
    }

    private final FlakySync sync = new FlakySync();
    public void lock() { sync.acquire(1); }
    public boolean tryLock() { return sync.tryAcquire(1); }
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }
    public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
    public void unlock() { sync.release(1); }
    public Condition newCondition()   { return sync.newCondition(); }
    public boolean isLocked()         { return sync.isHeldExclusively(); }
    public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }

    //--------------------- Infrastructure ---------------------------
    static volatile int passed = 0, failed = 0;
    static void pass() {passed++;}
    static void fail() {failed++; Thread.dumpStack();}
    static void fail(String msg) {System.out.println(msg); fail();}
    static void unexpected(Throwable t) {failed++; t.printStackTrace();}
    static void check(boolean cond) {if (cond) pass(); else fail();}
    static void equal(Object x, Object y) {
        if (x == null ? y == null : x.equals(y)) pass();
        else fail(x + " not equal to " + y);}
    public static void main(String[] args) throws Throwable {
        try {realMain(args);} catch (Throwable t) {unexpected(t);}
        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
        if (failed > 0) throw new AssertionError("Some tests failed");}
}
