package ch.retorte.intervalmusiccompositor.cache; import java.util.concurrent.ConcurrentLinkedQueue; import ch.retorte.intervalmusiccompositor.audiofile.AudioFile; import ch.retorte.intervalmusiccompositor.messagebus.DebugMessage; import ch.retorte.intervalmusiccompositor.spi.messagebus.MessageProducer; /** * Manages pending jobs for cache creation of imported music tracks. * * @author nw */ public class CreateCacheJobManager { private ConcurrentLinkedQueue<CreateCacheJob> pendingJobs; private MessageProducer messageProducer; private int threadLimit; private int threadCount = 0; public CreateCacheJobManager(MessageProducer messageProducer, int threadLimit) { this.messageProducer = messageProducer; this.threadLimit = threadLimit; this.pendingJobs = new ConcurrentLinkedQueue<>(); } private synchronized void dispatchOldestJob() { CreateCacheJob job = pendingJobs.poll(); job.addListener(this::notifyJobTermination); dispatch(job); } private void dispatch(CreateCacheJob j) { new Thread(j).start(); threadCount++; addDebugMessagesWith("Dispatched job: " + j); } public void addNewJob(CreateCacheJob j) { add(j); runJobs(); } private void add(CreateCacheJob j) { ((AudioFile) j.getAudioFile()).setQueuedStatus(); pendingJobs.add(j); } private void notifyJobTermination() { synchronized (this) { threadCount--; } addDebugMessagesWith("Collected job."); runJobs(); } private synchronized void runJobs() { while (canAcceptJobs()) { dispatchOldestJob(); } } private boolean canAcceptJobs() { return isJobAvailable() && isBelowConcurrentJobsLimit(); } private boolean isJobAvailable() { return 0 < pendingJobs.size(); } private boolean isBelowConcurrentJobsLimit() { return threadCount < threadLimit; } private void addDebugMessagesWith(String text) { messageProducer.send(new DebugMessage(this, text)); messageProducer.send(new DebugMessage(this, "Current jobs: " + threadCount)); } }