package contention.benchmark; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import contention.abstractions.CompositionalMap; /** * The loop executed by each thread of the map * benchmark. * * @author Vincent Gramoli * */ public class ThreadLoop implements Runnable { /** The instance of the running benchmark */ public CompositionalMap<Integer, Integer> bench; /** The stop flag, indicating whether the loop is over */ protected volatile boolean stop = false; /** The pool of methods that can run */ protected Method[] methods; /** The number of the current thread */ protected final short myThreadNum; /** The counters of the thread successful operations */ public long numAdd = 0; public long numRemove = 0; public long numAddAll = 0; public long numRemoveAll = 0; public long numSize = 0; public long numContains = 0; /** The counter of the false-returning operations */ public long failures = 0; /** The counter of the thread operations */ public long total = 0; /** The counter of aborts */ public long aborts = 0; /** The random number */ Random rand = new Random(); public long getCount; public long nodesTraversed; public long structMods; /** * The distribution of methods as an array of percentiles * * 0% cdf[0] cdf[2] 100% * |--writeAll--|--writeSome--|--readAll--|--readSome--| * |-----------write----------|--readAll--|--readSome--| cdf[1] */ int[] cdf = new int[3]; public ThreadLoop(short myThreadNum, CompositionalMap<Integer, Integer> bench, Method[] methods) { this.myThreadNum = myThreadNum; this.bench = bench; this.methods = methods; /* initialize the method boundaries */ assert (Parameters.numWrites >= Parameters.numWriteAlls); cdf[0] = 10 * Parameters.numWriteAlls; cdf[1] = 10 * Parameters.numWrites; cdf[2] = cdf[1] + 10 * Parameters.numSnapshots; } public void stopThread() { stop = true; } public void printDataStructure() { System.out.println(bench.toString()); } public void run() { while (!stop) { Integer newInt = rand.nextInt(Parameters.range); Integer a, b; int coin = rand.nextInt(1000); if (coin < cdf[0]) { // 1. should we run a writeAll operation? // init a collection Map<Integer, Integer> hm = new HashMap<Integer, Integer>(newInt, newInt); hm.put(newInt / 2, newInt / 2); // accepts duplicate try { if (bench.keySet().removeAll(hm.keySet())) numRemoveAll++; else failures++; } catch (Exception e) { System.err.println("Unsupported writeAll operations! Leave the default value of the numWriteAlls parameter (0)."); } } else if (coin < cdf[1]) { // 2. should we run a writeSome // operation? if (2 * (coin - cdf[0]) < cdf[1] - cdf[0]) { // add if ((a = bench.putIfAbsent((int) newInt, (int) newInt)) == null) { numAdd++; } else { failures++; } } else { // remove if ((a = bench.remove((int) newInt)) != null) { numRemove++; } else failures++; } } else if (coin < cdf[2]) { // 3. should we run a readAll operation? bench.size(); numSize++; } else { // 4. then we should run a readSome operation if (bench.get((int) newInt) != null) numContains++; else failures++; } total++; assert total == failures + numContains + numSize + numRemove + numAdd + numRemoveAll + numAddAll; } // System.out.println(numAdd + " " + numRemove + " " + failures); this.getCount = CompositionalMap.counts.get().getCount; this.nodesTraversed = CompositionalMap.counts.get().nodesTraversed; this.structMods = CompositionalMap.counts.get().structMods; System.out.println("Thread #" + myThreadNum + " finished."); } }