/*
 * 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/
 */

import java.util.SplittableRandom;
import java.util.Queue;

public class UnboundedQueueFillEmptyLoops {
    static int maxSize = 10000;
    static final SplittableRandom rng = new SplittableRandom(3153122688L);
    static volatile int total;
    static Integer[] numbers;

    public static void main(String[] args) throws Exception {
        if (args.length < 1) {
            System.out.printf(
                "Usage: UnboundedQueueFillEmptyLoops className [maxSize]%n");
            System.exit(1);
        }

        final Class<?> klass;
        try {
            klass = Class.forName(args[0]);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Class " + args[0] + " not found.");
        }

        if (args.length > 1)
            maxSize = Integer.parseInt(args[1]);

        System.out.printf("Class: %s size: %d%n", klass.getName(), maxSize);

        numbers = new Integer[maxSize];
        for (int i = 0; i < maxSize; ++i)
            numbers[i] = Integer.valueOf(rng.nextInt());

        long time = 0L;
        for (int i = 0; i < 100; ++i) {
            time += oneRun(klass, (maxSize >> 1) + rng.nextInt(maxSize));
            Thread.sleep(100);
        }

        if (total == 0) System.out.print(" ");
        System.out.println();
        System.out.println("total time " + (time / 1000000) + " ms");
    }

    static long oneRun(Class<?> klass, int n) throws Exception {
        Queue<Integer> q =
            (Queue<Integer>) klass.getConstructor().newInstance();
        int sum = total;
        int size = numbers.length;
        int m = rng.nextInt(size);
        long startTime = System.nanoTime();
        for (int k = 0; k < n; ++k) {
            int adds = rng.nextInt(size);
            for (int i = 0; i < adds; ++i) {
                if (m >= size)
                    m = 0;
                q.offer(numbers[m++]);
            }
            for (Integer p; (p = q.poll()) != null; )
                sum += p.intValue();
        }
        total += sum;
        long endTime = System.nanoTime();
        long time = endTime - startTime;
        long ms = time / 1000000L;
        System.out.print(" " + ms);
        //        double secs = (double) time / 1000000000.0;
        //        System.out.print(" " + secs);
        return time;
    }

}
