/*
 * Copyright 2004 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.
 */


/*
 *
 *   Sample target application for jvmti demos
 *
 *     java Context [threadCount [iterationCount [sleepContention]]]
 *           Default: java Context 5 10 0
 *
 *      threadCount     Number of threads
 *      iterationCount  Total turns taken for all threads
 *      sleepContention Time for main thread to sleep while holding lock
 *                      (creates monitor contention on all other threads)
 *
 */

/* Used to sync up turns and keep track of who's turn it is */
final class TurnChecker {
    int thread_index;
    TurnChecker(int thread_index) {
        this.thread_index = thread_index;
    }
}

/* Creates a bunch of threads that sequentially take turns */
public final class Context extends Thread {
    /* Used to track threads */
    private static long startTime;
    private static TurnChecker turn = new TurnChecker(-1);
    private static int total_turns_taken;

    /* Used for each Context thread */
    private final int thread_count;
    private final int thread_index;
    private final int thread_turns;

    /* Main program */
    public static void main(String[] argv) throws InterruptedException {
        int default_thread_count = 5;
        int default_thread_turns = 10;
        int default_contention_sleep = 0;
        int expected_turns_taken;
        long sleepTime = 10L;

        /* Override defaults */
        if ( argv.length >= 1 ) {
            default_thread_count = Integer.parseInt(argv[0]);
        }
        if ( argv.length >= 2 ) {
            expected_turns_taken = Integer.parseInt(argv[1]);
            default_thread_turns = expected_turns_taken/default_thread_count;
        }
        expected_turns_taken = default_thread_count*default_thread_turns;
        if ( argv.length >= 3 ) {
            default_contention_sleep = Integer.parseInt(argv[2]);
        }

        System.out.println("Context started with "
                 + default_thread_count + " threads and "
                 + default_thread_turns + " turns per thread");

        /* Get all threads running (they will block until we set turn) */
        for (int i = 0; i < default_thread_count; i++) {
            new Context(default_thread_count, i, default_thread_turns).start();
        }

        /* Sleep to make sure thread_index 0 make it to the wait call */
        System.out.println("Context sleeping, so threads will start wait");
        Thread.yield();
        Thread.sleep(sleepTime);

        /* Save start time */
        startTime = System.currentTimeMillis();

        /* This triggers the starting of taking turns */
        synchronized (turn) {
            turn.thread_index = 0;
            turn.notifyAll();
        }
        System.out.println("Context sleeping, so threads can run");
        Thread.yield();
        Thread.sleep(sleepTime);

        /* Wait for threads to finish (after everyone has had their turns) */
        while ( true ) {
            boolean done;
            done = false;
            synchronized (turn) {
                if ( total_turns_taken == expected_turns_taken ) {
                    done = true;
                }
                /* Create some monitor contention by sleeping with lock */
                if ( default_contention_sleep > 0 ) {
                    System.out.println("Context sleeping, to create contention");
                    Thread.yield();
                    Thread.sleep((long)default_contention_sleep);
                }
            }
            if ( done )
                break;
            System.out.println("Context sleeping, so threads will complete");
            Thread.sleep(sleepTime);
        }

        long endTime   = System.currentTimeMillis();
        long totalTime = endTime - startTime;

        System.out.println("Total time (milliseconds): " + totalTime);
        System.out.println("Milliseconds per thread: " +
                           ((double)totalTime / (default_thread_count)));

        System.out.println("Context completed");
        System.exit(0);
    }

    /* Thread object to run */
    Context(int thread_count, int thread_index, int thread_turns) {
        this.thread_count = thread_count;
        this.thread_index = thread_index;
        this.thread_turns = thread_turns;
    }

    /* Main for thread */
    public void run() {
        int next_thread_index = (thread_index + 1) % thread_count;
        int turns_taken       = 0;

        try {

            /* Loop until we make sure we get all our turns */
            for (int i = 0; i < thread_turns * thread_count; i++) {
                synchronized (turn) {
                    /* Keep waiting for our turn */
                    while (turn.thread_index != thread_index)
                        turn.wait();
                    /* MY TURN! Each thread gets thread_turns */
                    total_turns_taken++;
                    turns_taken++;
                    System.out.println("Turn #" + total_turns_taken
                                + " taken by thread " + thread_index
                                + ", " + turns_taken
                                + " turns taken by this thread");
                    /* Give next thread a turn */
                    turn.thread_index = next_thread_index;
                    turn.notifyAll();
                }
                /* If we've had all our turns, break out of this loop */
                if ( thread_turns == turns_taken ) {
                    break;
                }
            }
        } catch (InterruptedException intEx) { /* skip */ }

        /* Make sure we got all our turns */
        if ( thread_turns != turns_taken ) {
            System.out.println("ERROR: thread got " + turns_taken
                                        + " turns, expected " + thread_turns);
            System.exit(1);
        }
    }
}
