package org.simantics.db.impl.query; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.concurrent.Semaphore; import org.simantics.db.impl.graph.BarrierTracing; import org.simantics.db.impl.graph.ReadGraphImpl; import org.simantics.db.impl.query.QueryProcessor.AsyncBarrier; import org.simantics.db.impl.query.QueryProcessor.SessionTask; public class Scheduling { private final Semaphore requests; private Map> freeScheduling = new HashMap<>(); private LinkedList topLevelTasks = new LinkedList(); public Scheduling(Semaphore requests) { this.requests = requests; } public SessionTask getSubTask(ReadGraphImpl parent) { synchronized(this) { assert(parent.asyncBarrier.isBlocking()); LinkedList tasks = freeScheduling.get(parent.asyncBarrier); if(tasks == null) return null; SessionTask task = tasks.removeLast(); if(tasks.isEmpty()) freeScheduling.remove(parent.asyncBarrier); return task; } } public boolean pumpTask(ArrayList tasks) { synchronized(this) { // First finish existing executions if(!freeScheduling.isEmpty()) { Map.Entry> ls = freeScheduling.entrySet().iterator().next(); assert(ls.getKey().isBlocking()); tasks.add(ls.getValue().removeLast()); if(ls.getValue().isEmpty()) freeScheduling.remove(ls.getKey()); return true; } // Check for new tasks if(!topLevelTasks.isEmpty()) { tasks.add(topLevelTasks.removeLast()); return true; } return false; } } final public SessionTask scheduleOrReturnForExecution(SessionTask request) { assert(request != null); synchronized(this) { if(BarrierTracing.BOOKKEEPING) { Exception current = new Exception(); Exception previous = BarrierTracing.tasks.put(request, current); if(previous != null) { previous.printStackTrace(); current.printStackTrace(); } } requests.release(); if(request.rootGraph != null) { AsyncBarrier sb = request.rootGraph.asyncBarrier.getBlockingBarrier(); if(sb != null) { LinkedList ls = freeScheduling.get(sb); if(ls == null) { ls = new LinkedList(); freeScheduling.put(sb, ls); } ls.addFirst(request); return null; } } topLevelTasks.addFirst(request); } return null; } }