Author: hlship Date: Mon Apr 24 16:11:48 2006 New Revision: 396714 URL: http://svn.apache.org/viewcvs?rev=396714&view=rev Log: Refactor annotations ReadLock and WriteLock into Synchronization.Read and Synchronization.Write.
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/Synchronized.java Removed: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/ReadLock.java tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/WriteLock.java Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalSynchronization.aj tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/Synchronization.aj tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/ClassTransformerImpl.java tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImpl.java tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/ClassTransformation.java tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/SynchronizationAspectTest.java tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/SynchronizationTarget.java tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/util/CollectionFactoryTest.java Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalSynchronization.aj URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalSynchronization.aj?rev=396714&r1=396713&r2=396714&view=diff ============================================================================== --- tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalSynchronization.aj (original) +++ tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalSynchronization.aj Mon Apr 24 16:11:48 2006 @@ -10,5 +10,5 @@ * the ReadLock or WriteLock annotations. */ pointcut targetClasses() : - within(xxx.org.apache.tapestry.internal.aspects..*); + within(org.apache.tapestry.internal..*); } Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/Synchronization.aj URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/Synchronization.aj?rev=396714&r1=396713&r2=396714&view=diff ============================================================================== --- tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/Synchronization.aj (original) +++ tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/Synchronization.aj Mon Apr 24 16:11:48 2006 @@ -3,17 +3,17 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; -import org.apache.tapestry.internal.annotations.ReadLock; -import org.apache.tapestry.internal.annotations.WriteLock; +import org.apache.tapestry.internal.annotations.Synchronized; /** * Manages multi-threaded access to methods of an object instance using a - * [EMAIL PROTECTED] java.util.concurrent.locks.ReadWriteLock}, driven by the [EMAIL PROTECTED] ReadLock} and - * [EMAIL PROTECTED] WriteLock} annotations. Methods that have the ReadLock annotation witll be advised to - * obtain and release the read lock around their execution. Methods with the WriteLock annotation - * will obtain and release the write lock around their execution. Methods with ReadLock that call a - * WriteLock-ed method (within the same instance) will release the read lock before invoking the - * WriteLock-ed method. + * [EMAIL PROTECTED] java.util.concurrent.locks.ReentrantReadWriteLock}, driven by the + * [EMAIL PROTECTED] Synchronized.Read} and [EMAIL PROTECTED] Synchronized.Write} annotations. Methods that have the + * Synchronized.Read annotation witll be advised to obtain and release the read lock around their + * execution. Methods with the Synchronized.Write annotation will obtain and release the write lock + * around their execution. Methods with Synchronized.Read that call a Synchronized.Write-ed method + * (within the same instance) will release the read lock before invoking the Synchronized.Write-ed + * method. * <p> * This aspect also enforces that the annotations are only applied to instance (not static) methods, * and that a method may be either read or write, but not both. @@ -21,36 +21,46 @@ * TODO: read-into-write not yet implemented! * * @author Howard M. Lewis Ship + * @see org.apache.tapestry.internal.annotations.Synchronized */ public abstract aspect Synchronization extends AbstractClassTargetting -perthis(readLockMethods() || writeLockMethods()) +perthis(annotatedClasses()) { private final ReadWriteLock _lock = new ReentrantReadWriteLock(); + pointcut annotatedClasses() : + targetClasses() && within(@Synchronized *); + + declare error : + targetClasses() && + execution(@(Synchronized.Read || Synchronized.Write) static * *(..)) : + "Synchronized.Read and Synchronized.Write annotations may only be applied to instance methods."; + declare error : targetClasses() && - execution(@(ReadLock || WriteLock) static * *(..)) : - "ReadLock and WriteLock annotations may only be applied to instance methods."; + execution(@(Synchronized.Read || Synchronized.Write) * *(..)) && + within(!@(Synchronized) Object+) : + "The class must be annotated with Synchronized in order to use the Synchronized.Read or Synchronized.Write annotations."; declare error : targetClasses() && - execution(@ReadLock @WriteLock * *(..)) : - "A method may be annotated with ReadLock or with WriteLock but not both."; + execution(@Synchronized.Read @Synchronized.Write * *(..)) : + "A method may be annotated with Synchronized.Read or with Synchronized.Write but not both."; - pointcut readLockMethods() : - execution(@ReadLock * *(..)) && targetClasses(); + pointcut readMethods() : + execution(@Synchronized.Read * *(..)) && annotatedClasses(); - pointcut writeLockMethods() : - execution(@WriteLock * *(..)) && targetClasses(); + pointcut writeMethods() : + execution(@Synchronized.Write * *(..)) && annotatedClasses(); /** Before read lock methods, acquire the read lock. */ - before() : readLockMethods() + before() : readMethods() { _lock.readLock().lock(); } /** After read lock methods (including thrown exceptions), release the read lock. */ - after() : readLockMethods() + after() : readMethods() { _lock.readLock().unlock(); } @@ -61,13 +71,13 @@ * case. */ - before(): writeLockMethods() + before(): writeMethods() { _lock.writeLock().lock(); } /** And release the write lock after the method completes (successfully, or with an exception). */ - after() : writeLockMethods() + after() : writeMethods() { _lock.writeLock().unlock(); } Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/Synchronized.java URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/Synchronized.java?rev=396714&view=auto ============================================================================== --- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/Synchronized.java (added) +++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/Synchronized.java Mon Apr 24 16:11:48 2006 @@ -0,0 +1,60 @@ +package org.apache.tapestry.internal.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Marker interface for classes whose methods may be annotated with Synchronized.Read or + * Synchronized.Write. It is the path of least AspectJ resistance to get things working as they + * should. + * + * @author Howard M. Lewis Ship + */ [EMAIL PROTECTED](TYPE) [EMAIL PROTECTED](RUNTIME) [EMAIL PROTECTED] [EMAIL PROTECTED] +public @interface Synchronized { + + /** + * Marker on methods that perform a read operation. A non-exclusive read lock will be acquired + * before the method executes, and will be released after the method completes (succesfully or + * otherwise). + * <p> + * This annotation may only be applied to methods within Synchronized types. It may only be + * applied to instance, not static methods. It may not be used in combination with the + * Synchronized.Write annotation. + */ + @Target(METHOD) + @Retention(RUNTIME) + @Documented + public @interface Read { + + } + + /** + * Marker on methods that perform a write operation. An exclusive write lock will be acquired + * before the method executes, and will be released after the method completes (succesfully or + * otherwise). + * <p> + * This annotation may only be applied to methods within Synchronized types. It may only be + * applied to instance, not static methods. It may not be used in combination with the + * Synchronized.Write annotation. + * <p> + * TODO: To acquire the write lock, one must give up one's read lock (if any). This is not + * supported yet, so invoking a Synchronized.Write method (even indirectly) from a + * Synchronized.Read method will hang the thread. + */ + @Target(METHOD) + @Retention(RUNTIME) + @Documented + public @interface Write { + + } +} Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/ClassTransformerImpl.java URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/ClassTransformerImpl.java?rev=396714&r1=396713&r2=396714&view=diff ============================================================================== --- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/ClassTransformerImpl.java (original) +++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/ClassTransformerImpl.java Mon Apr 24 16:11:48 2006 @@ -19,6 +19,7 @@ import javassist.CtClass; import org.apache.tapestry.annotations.ComponentClass; +import org.apache.tapestry.internal.annotations.Synchronized; import org.apache.tapestry.internal.model.MutableComponentModelImpl; import org.apache.tapestry.model.MutableComponentModel; import org.apache.tapestry.transform.ClassTransformWorker; @@ -30,6 +31,7 @@ * * @author Howard M. Lewis Ship */ [EMAIL PROTECTED] public class ClassTransformerImpl implements ClassTransformer { /** Map from class name to class transformation. */ @@ -37,6 +39,7 @@ private ClassTransformWorker _workers; + @Synchronized.Write public void transformClass(CtClass ctClass) { String classname = ctClass.getName(); @@ -61,6 +64,7 @@ _nameToClassTransformation.put(classname, transformation); } + @Synchronized.Read public Instantiator createInstantiator(Class componentClass) { String className = componentClass.getName(); Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImpl.java URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImpl.java?rev=396714&r1=396713&r2=396714&view=diff ============================================================================== --- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImpl.java (original) +++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImpl.java Mon Apr 24 16:11:48 2006 @@ -114,6 +114,7 @@ } } + // This is called from well within a synchronized block. public void onLoad(ClassPool pool, String classname) throws NotFoundException, CannotCompileException { @@ -218,7 +219,8 @@ return input.substring(0, lastdot); } - public void addPackage(String packageName) + // synchronized may be overkill, but that's ok. + public synchronized void addPackage(String packageName) { Defense.notBlank(packageName, "packageName"); Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/ClassTransformation.java URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/ClassTransformation.java?rev=396714&r1=396713&r2=396714&view=diff ============================================================================== --- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/ClassTransformation.java (original) +++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/ClassTransformation.java Mon Apr 24 16:11:48 2006 @@ -29,6 +29,10 @@ * transformed. A number of <em>workers</em> will operate upon the ClassTransformation to effect * the desired changes before the true class is loaded into memory. * <p> + * Instances of this class are not designed to be thread safe, access to an instance should be + * restricted to a single thread. In fact, the design of this type is to allow stateless singletons + * in multiple threads to work on thread-specific data (within the ClassTransformation). * + * <p> * The majority of methods concern the <em>declared</em> members (field and methods) of a specific * class, rather than any fields or methods inherited from a base class. * Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java?rev=396714&r1=396713&r2=396714&view=diff ============================================================================== --- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java (original) +++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java Mon Apr 24 16:11:48 2006 @@ -22,6 +22,8 @@ import java.util.Map; import java.util.Set; +import org.apache.tapestry.internal.annotations.Utility; + /** * Static factory methods to ease the creation of new collection types (when using generics). Most * of these method leverage the compiler's ability to match generic types by return value. Typical @@ -40,14 +42,9 @@ * * @author Howard M. Lewis Ship */ [EMAIL PROTECTED] public final class CollectionFactory { - - /** Prevent instantiation. */ - private CollectionFactory() - { - } - /** Constructs and returns a generic [EMAIL PROTECTED] HashMap} instance. */ public static <K, V> Map<K, V> newMap() { @@ -61,10 +58,10 @@ } /** - * Constructs a new [EMAIL PROTECTED] java.util.HashMap} instance from an existing Map instance. + * Constructs a new [EMAIL PROTECTED] java.util.HashMap} instance by copying an existing Map instance. */ - public static <K, V> Map<K, V> copyMap(Map<K, V> map) + public static <K, V> Map<K, V> newMap(Map<K, V> map) { return new HashMap<K, V>(map); } @@ -75,7 +72,7 @@ return new ArrayList<T>(); } - /** Easy way to convert a list of like-typed values into a list. */ + /** Easy way to convert an array of like-typed values into a list. */ public static <T> List<T> newList(T... values) { return Arrays.asList(values); Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/SynchronizationAspectTest.java URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/SynchronizationAspectTest.java?rev=396714&r1=396713&r2=396714&view=diff ============================================================================== --- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/SynchronizationAspectTest.java (original) +++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/SynchronizationAspectTest.java Mon Apr 24 16:11:48 2006 @@ -23,10 +23,13 @@ private static final int THREAD_COUNT = 1000; + private static final int THREAD_BLOCK_SIZE = 50; + @Test public void incrementCounter() throws Exception { List<Thread> threads = newList(); + List<Thread> running = newList(); for (int i = 0; i < THREAD_COUNT; i++) { @@ -44,15 +47,28 @@ }); threads.add(t); + + if (threads.size() >= THREAD_BLOCK_SIZE) + startThreads(threads, running); } - for (Thread t : threads) - t.start(); + startThreads(threads, running); - for (Thread t : threads) + for (Thread t : running) t.join(); assertEquals(_target.getCounter(), THREAD_COUNT); + } + + private void startThreads(List<Thread> threads, List<Thread> running) + { + for (Thread t : threads) + { + t.start(); + running.add(t); + } + + threads.clear(); } } Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/SynchronizationTarget.java URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/SynchronizationTarget.java?rev=396714&r1=396713&r2=396714&view=diff ============================================================================== --- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/SynchronizationTarget.java (original) +++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/SynchronizationTarget.java Mon Apr 24 16:11:48 2006 @@ -1,26 +1,23 @@ package org.apache.tapestry.internal.aspects; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import org.apache.tapestry.internal.annotations.ReadLock; -import org.apache.tapestry.internal.annotations.WriteLock; +import org.apache.tapestry.internal.annotations.Synchronized; /** * Class used to test the [EMAIL PROTECTED] Synchorization} aspect. * * @author Howard M. Lewis Ship */ [EMAIL PROTECTED] public class SynchronizationTarget { - private final ReadWriteLock _lock = new ReentrantReadWriteLock(); + // private final ReadWriteLock _lock = new ReentrantReadWriteLock(); private int _counter; - @ReadLock + @Synchronized.Read public int getCounter() { - _lock.readLock().lock(); + // _lock.readLock().lock(); try { @@ -28,14 +25,14 @@ } finally { - _lock.readLock().unlock(); + // _lock.readLock().unlock(); } } - @WriteLock + @Synchronized.Write public void incrementCounter() { - _lock.writeLock().lock(); + // _lock.writeLock().lock(); try { @@ -43,25 +40,25 @@ } finally { - _lock.writeLock().unlock(); + // _lock.writeLock().unlock(); } } - @WriteLock + @Synchronized.Write public void setCounter(int newValue) { - _lock.writeLock().lock(); + // _lock.writeLock().lock(); try { _counter = newValue; } finally { - _lock.writeLock().unlock(); + // _lock.writeLock().unlock(); } } - @ReadLock + @Synchronized.Write public void incrementCounterHard() { setCounter(getCounter() + 1); Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/util/CollectionFactoryTest.java URL: http://svn.apache.org/viewcvs/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/util/CollectionFactoryTest.java?rev=396714&r1=396713&r2=396714&view=diff ============================================================================== --- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/util/CollectionFactoryTest.java (original) +++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/util/CollectionFactoryTest.java Mon Apr 24 16:11:48 2006 @@ -52,7 +52,7 @@ map.put("this", CollectionFactoryTest.class); - Map<String, Class> copy = CollectionFactory.copyMap(map); + Map<String, Class> copy = CollectionFactory.newMap(map); assertEquals(copy, map); --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]