@@ -0,0 +1,5 @@ | |||
package foo; | |||
import java.lang.annotation.*; | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@interface Synchronized {} |
@@ -0,0 +1,91 @@ | |||
package foo; | |||
import org.aspectj.lang.annotation.SuppressAjWarnings; | |||
public aspect SynchronizedAspect perthis(@this(Synchronized)) { | |||
// private static final Logger log = LogManager.getLogger(SynchronizedAspect.class); | |||
// private Lock objectLock = new ReentrantLock(); | |||
// private static long timeout = 1800; | |||
// private static TimeUnit unit = TimeUnit.SECONDS; | |||
// private static boolean timeoutInitialized = false; | |||
// @SuppressWarnings({"rawtypes"}) | |||
// private final static synchronized void initTimeout(Class cl) { | |||
// timeout = SynchronizedStaticAspect.aspectOf(cl).timeout; | |||
// unit = SynchronizedStaticAspect.aspectOf(cl).unit; | |||
// timeoutInitialized = true; | |||
// log.trace("timeout inialized with " + timeout + " " + unit); | |||
// } | |||
pointcut synchronizedMethods() : | |||
execution(@Synchronized !synchronized !static * *..*.*(..)) | |||
; | |||
pointcut synchronizedStaticMethods() : | |||
execution(@Synchronized !synchronized static * *..*.*(..)) | |||
; | |||
pointcut ignoredSynchronized() : | |||
execution(@Synchronized * *..*.*(..)) | |||
&& !synchronizedMethods() | |||
&& !synchronizedStaticMethods() | |||
; | |||
declare warning : ignoredSynchronized() : | |||
"@Synchronized is ignored here"; | |||
declare warning : | |||
(synchronizedStaticMethods() || synchronizedMethods()) | |||
&& !@within(Synchronized) : | |||
"@Synchronized is ignored here because @Synchronized for class is missing"; | |||
/** | |||
* Uses the Lock class of Java 5 to put a synchronization wrapper around | |||
* a method. Advantage of this Lock class is the posibility to use a | |||
* timeout to avoid dead locks. | |||
* | |||
* @return the return value of the wrapped method | |||
*/ | |||
@SuppressAjWarnings({"adviceDidNotMatch"}) | |||
Object around() : synchronizedMethods() && @within(Synchronized) { | |||
return proceed(); | |||
/* | |||
if (!timeoutInitialized) { | |||
initTimeout(thisJoinPointStaticPart.getSignature().getDeclaringType()); | |||
} | |||
if (log.isTraceEnabled()) { | |||
log.trace("synchronizing " + thisJoinPoint.getSignature().toShortString() + "..."); | |||
} | |||
try { | |||
if (objectLock.tryLock(timeout, unit)) { | |||
if (log.isTraceEnabled()) { | |||
log.trace("lock granted for " | |||
+ thisJoinPoint.getSignature().toShortString()); | |||
} | |||
try { | |||
return proceed(); | |||
} finally { | |||
objectLock.unlock(); | |||
if (log.isTraceEnabled()) { | |||
log.trace("lock released for " | |||
+ thisJoinPoint.getSignature().toShortString()); | |||
} | |||
} | |||
} else { | |||
String msg = "can't get " + objectLock + " for " | |||
+ thisJoinPoint.getSignature().toShortString() | |||
+ " after " + timeout + " " + unit; | |||
log.error(msg); | |||
throw new RuntimeException(msg); | |||
} | |||
} catch (InterruptedException ie) { | |||
String msg = "interrupted: " | |||
+ thisJoinPoint.getSignature().toShortString(); | |||
log.warn(msg, ie); | |||
throw new RuntimeException(msg, ie); | |||
} | |||
*/ | |||
} | |||
} |
@@ -0,0 +1,98 @@ | |||
package foo; | |||
/** | |||
* For synchronization we synchronize each static method mark as @Synchronized | |||
* by a ReentrantLock. | |||
* | |||
* @author <a href="boehm@javatux.de">oliver</a> | |||
* @since 0.8 | |||
*/ | |||
import org.aspectj.lang.annotation.SuppressAjWarnings; | |||
public aspect SynchronizedStaticAspect pertypewithin(@Synchronized *) { | |||
/* | |||
private static final Logger log = LogManager.getLogger(SynchronizedStaticAspect.class); | |||
private Lock classLock = new ReentrantLock(); | |||
protected long timeout = 1800; | |||
protected TimeUnit unit = TimeUnit.SECONDS; | |||
*/ | |||
/** | |||
* This advice is used to get the timeout value for the wrapped static | |||
* methods. | |||
* | |||
* @param t the annotation with the timeout value | |||
*/ | |||
before(Synchronized t) : | |||
staticinitialization(@Synchronized *) && @annotation(t) { | |||
/* | |||
this.timeout = t.timeout(); | |||
this.unit = t.unit(); | |||
if (log.isTraceEnabled()) { | |||
log.trace("lock timeout for " | |||
+ thisJoinPointStaticPart.getSignature().getDeclaringType().getSimpleName() | |||
+ " set to " + this.timeout + " " + this.unit); | |||
} | |||
*/ | |||
} | |||
private Log log = new Log(); | |||
static class Log { | |||
public boolean isTraceEnabled() { return true;} | |||
public void trace(String s) {} | |||
public void error(String s) {} | |||
public void warn(String s,InterruptedException ie) {} | |||
} | |||
ClassLock classLock = new ClassLock(); | |||
static class ClassLock { | |||
public boolean tryLock(Object o, Object b) { | |||
return true; | |||
} | |||
public void unlock(){} | |||
} | |||
String timeout=""; | |||
String unit=""; | |||
/** | |||
* This is the synchronization wrapper for the static methods which are | |||
* synchronized by a ReentrantLock class. | |||
* | |||
* @return the return value of the static method | |||
*/ | |||
@SuppressAjWarnings | |||
Object around() : SynchronizedAspect.synchronizedStaticMethods() { | |||
if (log.isTraceEnabled()) { | |||
log.trace("synchronizing " + thisJoinPointStaticPart.getSignature().toShortString() + "..."); | |||
} | |||
try { | |||
if (classLock.tryLock(timeout, unit)) { | |||
if (log.isTraceEnabled()) { | |||
log.trace("lock granted for " | |||
+ thisJoinPointStaticPart.getSignature().toShortString()); | |||
} | |||
try { | |||
return proceed(); | |||
} finally { | |||
classLock.unlock(); | |||
if (log.isTraceEnabled()) { | |||
log.trace("lock released for " | |||
+ thisJoinPointStaticPart.getSignature().toShortString()); | |||
} | |||
} | |||
} else { | |||
String msg = "can't get " + classLock + " for " | |||
+ thisJoinPointStaticPart.getSignature().toShortString(); | |||
log.error(msg); | |||
throw new RuntimeException(msg); | |||
} | |||
} catch (InterruptedException ie) { | |||
String msg = "interrupted: " | |||
+ thisJoinPoint.getSignature().toShortString(); | |||
log.warn(msg, ie); | |||
throw new RuntimeException(msg, ie); | |||
} | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
package foo; | |||
//@ProfileMe | |||
//@ThreadSafe | |||
@Synchronized//(timeout = 2, unit = TimeUnit.SECONDS) | |||
public final class SynchronizedTest { //implements Runnable { | |||
@Synchronized | |||
public void incrementCounter() { | |||
/* | |||
int n = counter; | |||
log.debug("counter read (" + n + ")"); | |||
ThreadUtil.sleep(); | |||
n++; | |||
log.debug("counter increased (" + n + ")"); | |||
ThreadUtil.sleep(); | |||
counter = n; | |||
log.debug("counter written (" + n + ")"); | |||
*/ | |||
} | |||
public void run() { | |||
// incrementCounter(); | |||
} | |||
} |