/* * Javolution - Java(TM) Solution for Real-Time and Embedded Systems * Copyright (C) 2012 - Javolution (http://javolution.org/) * All rights reserved. * * Permission to use, copy, modify, and distribute this software is * freely granted, provided that this notice is preserved. */ package javolution.context.internal; import javolution.context.ConcurrentContext; import javolution.lang.MathLib; /** * Holds the default implementation of ConcurrentContext. */ public final class ConcurrentContextImpl extends ConcurrentContext { private int completedCount; // Nbr of concurrent task completed. private Throwable error; // Any error raised. private int initiatedCount; // Nbr of concurrent task initiated. private final ConcurrentContextImpl parent; private ConcurrentThreadImpl[] threads; private int lastThreadInitiated; // Holds index of the last thread initiated. /** * Default constructor (root). */ public ConcurrentContextImpl() { this.parent = null; int nbThreads = ConcurrentContext.CONCURRENCY.get(); threads = new ConcurrentThreadImpl[nbThreads]; for (int i = 0; i < nbThreads; i++) { threads[i] = new ConcurrentThreadImpl(); threads[i].start(); } } /** * Inner implementation. */ public ConcurrentContextImpl(ConcurrentContextImpl parent) { this.parent = parent; this.threads = parent.threads; // Inherit threads from parents. } // Informs this context of the completion of a task (with possible error). public synchronized void completed(Throwable error) { if (error != null) { this.error = error; } completedCount++; this.notify(); } @Override public void execute(Runnable logic) { if (threads.length > 0) { int i = lastThreadInitiated; while (true) { // Searches available thread. i++; if (i >= threads.length) i = 0; if (threads[i].execute(logic, this)) { initiatedCount++; lastThreadInitiated = i; return; } if (i == lastThreadInitiated) break; // Cycled through. } } // No concurrent thread to do the job, lets do it ourself. try { logic.run(); } catch (Throwable e) { error = e; } } @Override public synchronized void exit() { super.exit(); try { while (initiatedCount != completedCount) { this.wait(); } } catch (InterruptedException ex) { this.error = ex; } if (error == null) return; // Everything fine. if (error instanceof RuntimeException) throw (RuntimeException) error; if (error instanceof Error) throw (Error) error; throw new RuntimeException(error); } @Override public int getConcurrency() { return threads.length; } @Override public void setConcurrency(int concurrency) { // The setting of the concurrency can only reduce the number // of threads available in the context. int nbThreads = MathLib.min(parent.threads.length, concurrency); threads = new ConcurrentThreadImpl[nbThreads]; for (int i = 0; i < nbThreads; i++) { // Reused from parent threads. threads[i] = parent.threads[i]; } } @Override protected ConcurrentContext inner() { return new ConcurrentContextImpl(this); } }