01: package org.compass.core.converter.dynamic;
02:
03: import org.compass.core.converter.ConversionException;
04: import org.compass.core.mapping.ResourcePropertyMapping;
05:
06: /**
07: * A pool of {@link ExpressionEvaluator}s where the dynamic expression library
08: * does not provide a high performance thread save evaluation.
09: *
10: * @author kimchy
11: */
12: public class ThreadSafeExpressionEvaluator implements
13: ExpressionEvaluator {
14:
15: private final int initialPoolSize;
16:
17: private final int maxPoolSize;
18:
19: private transient ExpressionEvaluator[] pool;
20:
21: private int nextAvailable = 0;
22:
23: private final Object mutex = new Object();
24:
25: private final ExpressionEvaluatorFactory expressionEvaluatorFactory;
26:
27: public ThreadSafeExpressionEvaluator(int initialPoolSize,
28: int maxPoolSize,
29: ExpressionEvaluatorFactory expressionEvaluatorFactory) {
30: this .initialPoolSize = initialPoolSize;
31: this .maxPoolSize = maxPoolSize;
32: this .expressionEvaluatorFactory = expressionEvaluatorFactory;
33: }
34:
35: public Object evaluate(Object o,
36: ResourcePropertyMapping resourcePropertyMapping)
37: throws ConversionException {
38: ExpressionEvaluator expressionEvaluator = fetchFromPool();
39: try {
40: return expressionEvaluator.evaluate(o,
41: resourcePropertyMapping);
42: } finally {
43: putInPool(expressionEvaluator);
44: }
45: }
46:
47: private ExpressionEvaluator fetchFromPool() {
48: ExpressionEvaluator result;
49: synchronized (mutex) {
50: if (pool == null) {
51: nextAvailable = -1;
52: pool = new ExpressionEvaluator[maxPoolSize];
53: for (int i = 0; i < initialPoolSize; i++) {
54: putInPool(expressionEvaluatorFactory.create());
55: }
56: }
57: while (nextAvailable < 0) {
58: try {
59: mutex.wait();
60: } catch (InterruptedException e) {
61: throw new ConversionException(
62: "Interrupted whilst waiting for a free item in the pool",
63: e);
64: }
65: }
66: result = pool[nextAvailable];
67: nextAvailable--;
68: }
69: if (result == null) {
70: result = expressionEvaluatorFactory.create();
71: putInPool(result);
72: }
73: return result;
74: }
75:
76: private void putInPool(ExpressionEvaluator expressionEvaluator) {
77: synchronized (mutex) {
78: nextAvailable++;
79: pool[nextAvailable] = expressionEvaluator;
80: mutex.notify();
81: }
82: }
83:
84: }
|