package org.compass.core.converter.dynamic; import org.compass.core.converter.ConversionException; import org.compass.core.mapping.ResourcePropertyMapping; /** * A pool of {@link ExpressionEvaluator}s where the dynamic expression library * does not provide a high performance thread save evaluation. * * @author kimchy */ public class ThreadSafeExpressionEvaluator implements ExpressionEvaluator { private final int initialPoolSize; private final int maxPoolSize; private transient ExpressionEvaluator[] pool; private int nextAvailable = 0; private final Object mutex = new Object(); private final ExpressionEvaluatorFactory expressionEvaluatorFactory; public ThreadSafeExpressionEvaluator(int initialPoolSize, int maxPoolSize, ExpressionEvaluatorFactory expressionEvaluatorFactory) { this.initialPoolSize = initialPoolSize; this.maxPoolSize = maxPoolSize; this.expressionEvaluatorFactory = expressionEvaluatorFactory; } public Object evaluate(Object o, ResourcePropertyMapping resourcePropertyMapping) throws ConversionException { ExpressionEvaluator expressionEvaluator = fetchFromPool(); try { return expressionEvaluator.evaluate(o, resourcePropertyMapping); } finally { putInPool(expressionEvaluator); } } private ExpressionEvaluator fetchFromPool() { ExpressionEvaluator result; synchronized (mutex) { if (pool == null) { nextAvailable = -1; pool = new ExpressionEvaluator[maxPoolSize]; for (int i = 0; i < initialPoolSize; i++) { putInPool(expressionEvaluatorFactory.create()); } } while (nextAvailable < 0) { try { mutex.wait(); } catch (InterruptedException e) { throw new ConversionException("Interrupted whilst waiting for a free item in the pool", e); } } result = pool[nextAvailable]; nextAvailable--; } if (result == null) { result = expressionEvaluatorFactory.create(); putInPool(result); } return result; } private void putInPool(ExpressionEvaluator expressionEvaluator) { synchronized (mutex) { nextAvailable++; pool[nextAvailable] = expressionEvaluator; mutex.notify(); } } }