Revision: 682
http://stripes.svn.sourceforge.net/stripes/?rev=682&view=rev
Author: bengunter
Date: 2007-12-12 15:43:26 -0800 (Wed, 12 Dec 2007)
Log Message:
-----------
Added thread local caching of Formatter instances and a test to make sure it's
working.
Modified Paths:
--------------
trunk/stripes/src/net/sourceforge/stripes/format/DefaultFormatterFactory.java
trunk/tests/src/net/sourceforge/stripes/format/DefaultFormatterFactoryTest.java
Modified:
trunk/stripes/src/net/sourceforge/stripes/format/DefaultFormatterFactory.java
===================================================================
---
trunk/stripes/src/net/sourceforge/stripes/format/DefaultFormatterFactory.java
2007-12-12 19:18:51 UTC (rev 681)
+++
trunk/stripes/src/net/sourceforge/stripes/format/DefaultFormatterFactory.java
2007-12-12 23:43:26 UTC (rev 682)
@@ -44,6 +44,22 @@
private Map<Class<?>, Class<? extends Formatter<?>>> classCache =
Collections
.synchronizedMap(new HashMap<Class<?>, Class<? extends
Formatter<?>>>());
+ /** Thread local cache of formatter instances. */
+ private ThreadLocal<Map<Class<? extends Formatter<?>>, Formatter<?>>>
instanceCache = new ThreadLocal<Map<Class<? extends Formatter<?>>,
Formatter<?>>>() {
+ @Override
+ protected Map<Class<? extends Formatter<?>>, Formatter<?>>
initialValue() {
+ return new HashMap<Class<? extends Formatter<?>>, Formatter<?>>();
+ }
+ };
+
+ /** Thread local flag that, if true, causes the instance cache to be reset
in each thread. */
+ private ThreadLocal<Boolean> clearInstanceCache = new
ThreadLocal<Boolean>() {
+ @Override
+ protected Boolean initialValue() {
+ return false;
+ }
+ };
+
/** Stores a reference to the Configuration passed in at initialization
time. */
private Configuration configuration;
@@ -80,15 +96,21 @@
* @param formatterClass the implementation class that will handle the
formatting
*/
public void add(Class<?> targetType, Class<? extends Formatter<?>>
formatterClass) {
+ this.formatters.put(targetType, formatterClass);
if (classCache.size() > 0)
clearCache();
- this.formatters.put(targetType, formatterClass);
}
/** Clear the class and instance caches. This is called by [EMAIL
PROTECTED] #add(Class, Class)}. */
- protected void clearCache() {
+ protected synchronized void clearCache() {
log.debug("Clearing formatter cache");
classCache.clear();
+ clearInstanceCache = new ThreadLocal<Boolean>() {
+ @Override
+ protected Boolean initialValue() {
+ return true;
+ }
+ };
}
/**
@@ -223,8 +245,21 @@
public Formatter<?> getInstance(Class<? extends Formatter<?>> clazz,
String formatType, String formatPattern, Locale locale)
throws Exception {
- // TODO: add thread local caching of formatter classes
- Formatter<?> formatter = clazz.newInstance();
+ // If the reset flag is turned on, then clear the cache and turn the
flag off
+ if (clearInstanceCache.get()) {
+ log.debug("Clearing formatter instance cache for thread ",
+ Thread.currentThread().getName());
+ instanceCache.get().clear();
+ clearInstanceCache.set(false);
+ }
+
+ // Look for an instance in the cache. If none is found then create one
and cache it.
+ Formatter<?> formatter = instanceCache.get().get(clazz);
+ if (formatter == null) {
+ formatter = clazz.newInstance();
+ log.debug("Caching instance of formatter ", clazz);
+ instanceCache.get().put(clazz, formatter);
+ }
formatter.setFormatType(formatType);
formatter.setFormatPattern(formatPattern);
formatter.setLocale(locale);
Modified:
trunk/tests/src/net/sourceforge/stripes/format/DefaultFormatterFactoryTest.java
===================================================================
---
trunk/tests/src/net/sourceforge/stripes/format/DefaultFormatterFactoryTest.java
2007-12-12 19:18:51 UTC (rev 681)
+++
trunk/tests/src/net/sourceforge/stripes/format/DefaultFormatterFactoryTest.java
2007-12-12 23:43:26 UTC (rev 682)
@@ -148,13 +148,43 @@
Assert.assertEquals(YFormatter.class, formatter.getClass());
}
- public static void main(String[] args) throws Exception {
- DefaultFormatterFactoryTest test = new DefaultFormatterFactoryTest();
- test.testFormatterSuperclass();
- test.testFormatterInterface();
- test.testNullFormatterIsNeverBestMatch();
- test.testFormatterSuperclassImplementsInterface();
- test.testFormatterForInterfaceSuperclass();
+ @Test(groups = "fast")
+ public void testFormatterInstanceCaching() throws Exception {
+ DefaultFormatterFactory factory = new DefaultFormatterFactory();
+ factory.init(new DefaultConfiguration());
+
+ Locale locale = Locale.getDefault();
+ Formatter<?> first, second;
+
+ // register some formatters
+ factory.add(X.class, XFormatter.class);
+ factory.add(Y.class, YFormatter.class);
+ factory.add(Z.class, ZFormatter.class);
+
+ // get each twice in succession and compare the references to make
sure it's the same object
+ first = factory.getFormatter(SuperclassImplementsX.class, locale,
null, null);
+ second = factory.getFormatter(SuperclassImplementsX.class, locale,
null, null);
+ Assert.assertTrue(first == second);
+ first = factory.getFormatter(SuperclassImplementsY.class, locale,
null, null);
+ second = factory.getFormatter(SuperclassImplementsY.class, locale,
null, null);
+ Assert.assertTrue(first == second);
+ first = factory.getFormatter(SuperclassImplementsZ.class, locale,
null, null);
+ second = factory.getFormatter(SuperclassImplementsZ.class, locale,
null, null);
+ Assert.assertTrue(first == second);
+
+ // do it again but force a cache clear between gets
+ first = factory.getFormatter(SuperclassImplementsX.class, locale,
null, null);
+ factory.add(X.class, XFormatter.class);
+ second = factory.getFormatter(SuperclassImplementsX.class, locale,
null, null);
+ Assert.assertFalse(first == second);
+ first = factory.getFormatter(SuperclassImplementsY.class, locale,
null, null);
+ factory.add(Y.class, YFormatter.class);
+ second = factory.getFormatter(SuperclassImplementsY.class, locale,
null, null);
+ Assert.assertFalse(first == second);
+ first = factory.getFormatter(SuperclassImplementsZ.class, locale,
null, null);
+ factory.add(Z.class, ZFormatter.class);
+ second = factory.getFormatter(SuperclassImplementsZ.class, locale,
null, null);
+ Assert.assertFalse(first == second);
}
public void testFormatterForInterfaceSuperclass() throws Exception {
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development