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

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

Go to download

PatternTesting Concurrent (patterntesting-concurrent) is a collection of useful thread aspects. It has support for testing, for sychnronization and for concurrent programming. Some of the ideas used in this library comes from reading Brian Goetz's book "Java Concurrency in Practice".

There is a newer version: 2.5.0
Show newest version
/*
 * $Id: RunParallelAspect.aj,v 1.5 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.01.2009 by oliver ([email protected])
 */
package patterntesting.concurrent;

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

import patterntesting.annotation.concurrent.RunParallel;
import patterntesting.runtime.util.JoinPointHelper;

/**
 * This aspect together with the @RunParallel annotation allows you to
 * run a method parallel in different threads.
 *
 * @author oliver
 * @since 0.9
 */
@SuppressAjWarnings({"adviceDidNotMatch"})
public aspect RunParallelAspect percflow(parallelMethods()) {

    private static Logger log = LogManager.getLogger(RunParallelAspect.class);

    static {
        log.debug("{} is successful initialized.", RunParallelAspect.class);
    }
    
    /** Here one of the results of a parallel run is stored. */
    public Object result;

    /** The parallel runs. */
    public RunParallel parallelRuns;

    /**
     * Parallel methods.
     */
    pointcut parallelMethods() :
        execution(@RunParallel * *..*.*(..))
        || execution(@RunParallel *..*.new(..));

    /**
     * Each method marked as @RunParallel is started in its own
     * thread and the result of it is stored in result.
     *
     * @param t the @RunParallel annotation with the information,
     *        how many parallel threads should be started.
     * @return the object from one of the thread. The different parallel
     *         executions should be either of type "void" or should return
     *         for each call the same result. Otherwise the result is not
     *         predictable.
     *
     * @{link "http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg09446.html"}
     * @{link "http://dev.eclipse.org/newslists/news.eclipse.technology.ajdt/msg01872.html"}
     */
    @SuppressAjWarnings({"adviceDidNotMatch"})
    Object around(RunParallel t) : parallelMethods() && @annotation(t) {
        parallelRuns = t;
        Runnable work = new Runnable() {
            public void run() {
                if (log.isTraceEnabled()) {
                    log.trace("> "
                            + JoinPointHelper.getAsShortString(thisJoinPoint)
                            + " started...");
                }
                Object x = proceed(parallelRuns);
                if (log.isTraceEnabled()) {
                    log.trace("< "
                            + JoinPointHelper.getAsShortString(thisJoinPoint)
                            + " = " + x);
                }
                result = x;
            }
        };
        runParallel(work, t);
        return result;
    }

    /**
     * This method starts the given Runnable in several threads.
     * @param work
     * @param runs contains the information how many thread should be created.
     */
    private void runParallel(Runnable work, RunParallel runs) {
        int n = runs.value();
        Thread[] threads = new Thread[n];
        for(int i = 0; i < n; i++) {
            threads[i] = new Thread(work, "t"+i);
            log.debug("starting " + threads[i] + "...");
            threads[i].start();
        }
        for(int i = 0; i < n; i++) {
            waitFor(threads[i]);
        }
        if (result == null) {
            log.debug("All {} threads are finished with no result.", n);
        } else {
            log.debug("All {} threads are finished with result = {}.", n, result);
        }
    }

    private void waitFor(Thread t) {
        try {
            t.join();
        } catch (InterruptedException ie) {
            log.warn("can't no longer wait for " + t, ie);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy