package org.jerlang.vm;
import java.util.HashSet;
import org.jerlang.ProcessOrPort;
import org.jerlang.ProcessRegistry;
import org.jerlang.type.PidOrPortId;
/**
* References:
* http://www.erlang.se/euc/08/euc_smp.pdf
*/
public class Scheduler extends Thread {
private final HashSet<PidOrPortId> ids;
private final RunQueue<ProcessOrPort> runQueueMax;
private final RunQueue<ProcessOrPort> runQueueHigh;
private final RunQueue<ProcessOrPort> runQueueNormal;
private final RunQueue<ProcessOrPort> runQueueLow;
public Scheduler() {
ids = new HashSet<>();
runQueueMax = new RunQueue<>();
runQueueHigh = new RunQueue<>();
runQueueNormal = new RunQueue<>();
runQueueLow = new RunQueue<>();
}
public ProcessOrPort add(ProcessOrPort p) {
if (ids.contains(p.id())) {
System.err.println("Process or port already scheduled");
return p;
}
ids.add(p.id());
p.setScheduler(this);
switch (p.priority()) {
case MAX:
runQueueMax.push(p);
break;
case HIGH:
runQueueHigh.push(p);
break;
case NORMAL:
runQueueNormal.push(p);
break;
case LOW:
runQueueLow.push(p);
break;
}
return p;
}
/**
* Performing actions according to:
* https://www.erlang-solutions.com/resources/webinars/understanding-erlang-scheduler
*/
@Override
public void run() {
while (!isInterrupted()) {
checkIfTimersShouldBeTriggered();
maybeCheckBalance();
migrateProcessesAndPorts();
executeAnyAuxWork();
maybeCheckIO();
executeOnePort();
executeOneProcess();
}
}
private void checkIfTimersShouldBeTriggered() {
}
private void maybeCheckBalance() {
}
private void migrateProcessesAndPorts() {
}
private void executeAnyAuxWork() {
}
private void maybeCheckIO() {
}
private void executeOnePort() {
}
private void executeOneProcess() {
if (!execute(runQueueMax)) {
if (!execute(runQueueHigh)) {
if (!execute(runQueueNormal)) {
if (!execute(runQueueLow)) {
sleep();
}
}
}
}
}
private boolean execute(RunQueue<ProcessOrPort> runQueue) {
ProcessOrPort p = runQueue.poll();
if (p != null) {
ProcessRegistry.self(p);
p.execute();
ProcessRegistry.self(null);
switch (p.state()) {
case RUNNABLE:
runQueue.push(p);
break;
default:
ids.remove(p.pid());
break;
}
return true;
}
return false;
}
private void sleep() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
interrupt();
}
}
}