All Downloads are FREE. Search and download functionalities are using the official Maven repository.

patterntesting.concurrent.SynchronizedAspect.aj Maven / Gradle / Ivy

/**
 * $Id: SynchronizedAspect.aj,v 1.3 2016/12/18 21:56:49 oboehm Exp $
 *
 * Copyright (c) 2008 by Oliver Boehm
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * (c)reated 13.11.2008 by oliver ([email protected])
 */
package patterntesting.concurrent;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.*;

import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.apache.logging.log4j.*;

import patterntesting.annotation.concurrent.Synchronized;

/**
 * For synchronization we synchronize each method mark as @Synchronized
 * by a ReentrantLock. The first approach uses a ConcurrentHashMap to hold
 * the lock for each object. But this would introduce a memory leak because
 * the synchronized object will be never freed - there is always the reference
 * from the HashMap to it.
 * 
* Now we instantiate for each object a seperate aspect using the perthis * clause. This means you must now mark also the object as @Synchronized not * only the methods. *
* For synchronization of static methods we keep the ConcurrentHashMap approach * because classes are not freed by the garbage collector. * * @author oliver * @since 0.8 */ 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); } /** * We don't want to get with an synchronized method so we do not address * it here */ 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) { 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); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy