package exm.stc.jvm.runtime; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Random; import java.util.concurrent.ConcurrentLinkedDeque; /** * The global task queue * TODO: priorities * */ public class TaskQueue { /** * TODO: allow passing in of queues so that each thread * can have in own local heap * @param numThreads */ public TaskQueue(int numThreads) { this.numThreads = numThreads; this.targeted = new ArrayList<ConcurrentLinkedDeque<Task>>(numThreads); this.regular = new ArrayList<ArrayDeque<Task>>(numThreads); for (int i = 0; i < numThreads; i++) { this.targeted.add(new ConcurrentLinkedDeque<Task>()); this.regular.add(new ArrayDeque<Task>()); } } private final int numThreads; /** * Targeted task queues (one per thread) */ private final ArrayList<ConcurrentLinkedDeque<Task>> targeted; /** * Personal non-targeted task queue (one per thread) * TODO: priorities */ private final ArrayList<ArrayDeque<Task>> regular; /** * TODO: each thread should hold local reference to own deque * @return a task, or null if nothing available */ public Task getTask(int threadNum) { // Targeted have highest priority Task res = targeted.get(threadNum).pollLast(); if (res != null) return res; // Next, try to see if something in local deque ArrayDeque<Task> myDeque = regular.get(threadNum); synchronized (myDeque) { res = myDeque.pollLast(); } if (res != null) return res; // Finally, search other deques to steal work // TODO: exit condition - detect idle, or go to sleep Random r = new Random(); while (true) { int deque = r.nextInt(numThreads - 1); if (deque >= threadNum) deque++; ArrayDeque<Task> otherDeque = regular.get(threadNum); // Task from other end synchronized (otherDeque) { res = otherDeque.pollFirst(); } if (res != null) return res; } } }