/*
 * 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 MapLoops.java
 * @run main/timeout=4700 MapLoops
 * @summary Exercise multithreaded maps, by default ConcurrentHashMap.
 * Multithreaded hash table test.  Each thread does a random walk
 * though elements of "key" array. On each iteration, it checks if
 * table includes key.  If absent, with probability pinsert it
 * inserts it, and if present, with probability premove it removes
 * it.  (pinsert and premove are expressed as percentages to simplify
 * parsing from command line.)
 */

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

public class MapLoops {
    static final int NKEYS = 100000;
    static int pinsert     = 60;
    static int premove     = 2;
    static int maxThreads  = 5;
    static int nops        = 1000000;
    static int removesPerMaxRandom;
    static int insertsPerMaxRandom;

    static final ExecutorService pool = Executors.newCachedThreadPool();

    public static void main(String[] args) throws Exception {

        Class mapClass = null;
        if (args.length > 0) {
            try {
                mapClass = Class.forName(args[0]);
            } catch(ClassNotFoundException e) {
                throw new RuntimeException("Class " + args[0] + " not found.");
            }
        }
        else
            mapClass = RWMap.class;

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

        if (args.length > 2)
            nops = Integer.parseInt(args[2]);

        if (args.length > 3)
            pinsert = Integer.parseInt(args[3]);

        if (args.length > 4)
            premove = Integer.parseInt(args[4]);

        // normalize probabilities wrt random number generator
        removesPerMaxRandom = (int)(((double)premove/100.0 * 0x7FFFFFFFL));
        insertsPerMaxRandom = (int)(((double)pinsert/100.0 * 0x7FFFFFFFL));

        System.out.println("Using " + mapClass.getName());

        Random rng = new Random(315312);
        Integer[] key = new Integer[NKEYS];
        for (int i = 0; i < key.length; ++i)
            key[i] = new Integer(rng.nextInt());

        // warmup
        System.out.println("Warmup...");
        for (int k = 0; k < 2; ++k) {
            Map<Integer, Integer> map = (Map<Integer,Integer>)mapClass.newInstance();
            LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
            CyclicBarrier barrier = new CyclicBarrier(1, timer);
            new Runner(map, key, barrier).run();
            map.clear();
            Thread.sleep(100);
        }

        for (int i = 1; i <= maxThreads; i += (i+1) >>> 1) {
            System.out.print("Threads: " + i + "\t:");
            Map<Integer, Integer> map = (Map<Integer,Integer>)mapClass.newInstance();
            LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
            CyclicBarrier barrier = new CyclicBarrier(i+1, timer);
            for (int k = 0; k < i; ++k)
                pool.execute(new Runner(map, key, barrier));
            barrier.await();
            barrier.await();
            long time = timer.getTime();
            long tpo = time / (i * (long)nops);
            System.out.print(LoopHelpers.rightJustify(tpo) + " ns per op");
            double secs = (double)(time) / 1000000000.0;
            System.out.println("\t " + secs + "s run time");
            map.clear();
        }
        pool.shutdown();
        if (! pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS))
            throw new Error();
    }

    static class Runner implements Runnable {
        final Map<Integer,Integer> map;
        final Integer[] key;
        final LoopHelpers.SimpleRandom rng = new LoopHelpers.SimpleRandom();
        final CyclicBarrier barrier;
        int position;
        int total;

        Runner(Map<Integer,Integer> map, Integer[] key,  CyclicBarrier barrier) {
            this.map = map;
            this.key = key;
            this.barrier = barrier;
            position = key.length / 2;
        }

        int step() {
            // random-walk around key positions,  bunching accesses
            int r = rng.next();
            position += (r & 7) - 3;
            while (position >= key.length) position -= key.length;
            while (position < 0) position += key.length;

            Integer k = key[position];
            Integer x = map.get(k);

            if (x != null) {
                if (x.intValue() != k.intValue())
                    throw new Error("bad mapping: " + x + " to " + k);

                if (r < removesPerMaxRandom) {
                    // get awy from this position
                    position = r % key.length;
                    map.remove(k);
                    return 2;
                }
                else
                    total += LoopHelpers.compute2(LoopHelpers.compute1(x.intValue()));
            }
            else {
                if (r < insertsPerMaxRandom) {
                    map.put(k, k);
                    return 2;
                }
            }
            return 1;
        }

        public void run() {
            try {
                barrier.await();
                int ops = nops;
                while (ops > 0)
                    ops -= step();
                barrier.await();
            }
            catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}
