Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
groovyx.gpars.util.PAUtils Maven / Gradle / Ivy
Go to download
The Groovy and Java high-level concurrency library offering actors, dataflow, CSP, agents, parallel collections, fork/join and more
// GPars - Groovy Parallel Systems
//
// Copyright © 2008-11 The original author or authors
//
// 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 or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package groovyx.gpars.util;
import groovy.lang.Closure;
import groovyx.gpars.ReactorMessagingRunnable;
import groovyx.gpars.dataflow.DataflowVariable;
import groovyx.gpars.scheduler.Pool;
import org.codehaus.groovy.runtime.InvokerInvocationException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
/**
* Handy methods build PA from different types
*
* @author Vaclav Pech
* Date: 24th Oct 2010
*/
@SuppressWarnings({"UtilityClass", "AbstractClassWithoutAbstractMethods", "AbstractClassNeverImplemented", "StaticMethodOnlyUsedInOneClass"})
public abstract class PAUtils {
public static Collection createCollection(final Iterable object) {
final Collection collection = new ArrayList();
for (final T item : object) {
collection.add(item);
}
return collection;
}
public static Collection createCollection(final Iterator iterator) {
final Collection collection = new ArrayList();
while (iterator.hasNext()) {
collection.add(iterator.next());
}
return collection;
}
public static String[] createArray(final CharSequence value) {
final String[] chars = new String[value.length()];
for (int i = 0; i < value.length(); i++) {
chars[i] = String.valueOf(value.charAt(i));
}
return chars;
}
public static Map.Entry[] createArray(final Map map) {
@SuppressWarnings({"unchecked"})
final Map.Entry[] result = new Map.Entry[map.size()];
int i = 0;
for (final Map.Entry entry : map.entrySet()) {
result[i] = entry;
i++;
}
return result;
}
/**
* If the passed-in closure expects two arguments, it is considered to be a map-iterative code and is then wrapped
* with a single-argument closure, which unwraps the key:value pairs for the original closure.
* If the supplied closure doesn't expect two arguments, it is returned unchanged.
*
* @param cl The closure to use for parallel methods
* @return The original or an unwrapping closure
*/
public static Closure buildClosureForMaps(final Closure cl) {
if (cl.getMaximumNumberOfParameters() == 2) return new Closure(cl.getOwner()) {
private static final long serialVersionUID = -7502769124461342939L;
@Override
public T call(final Object arguments) {
@SuppressWarnings({"unchecked"})
final Map.Entry entry = (Map.Entry) arguments;
return cl.call(entry.getKey(), entry.getValue());
}
@Override
public T call(final Object[] args) {
return this.call(args[0]);
}
};
return cl;
}
/**
* If the passed-in closure expects three arguments, it is considered to be a map-iterative_with_index code and is then wrapped
* with a two-argument closure, which unwraps the key:value pairs for the original closure.
* If the supplied closure doesn't expect three arguments, it is returned unchanged.
*
* @param cl The closure to use for parallel methods
* @return The original or an unwrapping closure
*/
public static Closure buildClosureForMapsWithIndex(final Closure cl) {
if (cl.getMaximumNumberOfParameters() == 3) return new Closure(cl.getOwner()) {
private static final long serialVersionUID = 4777456744250574403L;
@SuppressWarnings({"rawtypes", "RawUseOfParameterizedType"})
@Override
public Class[] getParameterTypes() {
return new Class[]{Map.Entry.class, Integer.class};
}
@Override
public int getMaximumNumberOfParameters() {
return 2;
}
@Override
public T call(final Object[] args) {
@SuppressWarnings({"unchecked"})
final Map.Entry entry = (Map.Entry) args[0];
final Integer index = (Integer) args[1];
return cl.call(entry.getKey(), entry.getValue(), index);
}
};
return cl;
}
/**
* Builds a resulting map out of an map entry collection
*
* @param result The collection containing map entries
* @return A corresponding map instance
*/
public static Map buildResultMap(final Collection> result) {
final Map map = new HashMap(result.size());
for (final Map.Entry item : result) {
map.put(item.getKey(), item.getValue());
}
return map;
}
/**
* Builds a comparator depending on the number of arguments accepted by the supplied closure.
*
* @param handler The one or two argument closure to build a comparator on
* @return A new Comparator to use
*/
public static Comparator createComparator(final Closure handler) {
if (handler.getMaximumNumberOfParameters() == 2) return new Comparator() {
@Override
public int compare(final Object o1, final Object o2) {
return (Integer) handler.call(o1, o2);
}
};
else return new Comparator() {
@SuppressWarnings({"unchecked"})
@Override
public int compare(final Object o1, final Object o2) {
return ((Comparable) handler.call(o1)).compareTo(handler.call(o2));
}
};
}
/**
* Creates a closure that will insert elements in the appropriate group
*
* @param cl The distinction closure
* @param map The map of groups to contribute to
* @return null
*/
public static Closure createGroupByClosure(final Closure cl, final ConcurrentMap> map) {
return new Closure(cl.getOwner(), cl.getDelegate()) {
private static final long serialVersionUID = 5495474569312257163L;
@Override
@SuppressWarnings({"unchecked"})
public Object call(final Object arguments) {
final K result = cl.call(arguments);
final List localList = new ArrayList();
localList.add((T) arguments);
final List myList = Collections.synchronizedList(localList);
final Collection list = map.putIfAbsent(result, myList);
if (list != null) list.add((T) arguments);
return null;
}
};
}
/**
* Performs a single step in the evaluation of parameters passed into an asynchronous function
*
* @param pool The thread pool to use
* @param args The list of original arguments
* @param current The index of the current argument to evaluate
* @param soFarArgs A list of arguments evaluated so far
* @param result The DFV expecting the function result to be bound to once calculated
* @param original The original non-asynchronous function to invoke once all arguments are available
* @param pooledThreadFlag Indicates, whether we now run in a pooled thread so we don't have to schedule the original function invocation, once all arguments have been bound
*/
@SuppressWarnings({"unchecked"})
public static void evaluateArguments(final Pool pool, final Object[] args, final int current, final List soFarArgs,
final DataflowVariable result, final Closure original, final boolean pooledThreadFlag) {
if (current == args.length) {
if (pooledThreadFlag) {
try {
final Object call = original.call(soFarArgs.toArray(new Object[soFarArgs.size()]));
result.leftShift(call);
} catch (InvokerInvocationException e) {
result.bind(e.getCause());
} catch (Exception all) {
result.bind(all);
} catch (Error error) {
result.bind(error);
throw error;
}
} else {
pool.execute(new Runnable() {
@Override
public void run() {
try {
result.leftShift(original.call(soFarArgs.toArray(new Object[soFarArgs.size()])));
} catch (InvokerInvocationException e) {
result.bind(e.getCause());
} catch (Exception all) {
result.bind(all);
} catch (Error error) {
result.bind(error);
throw error;
}
}
});
}
} else {
final Object currentArgument = args[current];
if (currentArgument instanceof DataflowVariable) {
final DataflowVariable variable = (DataflowVariable) currentArgument;
if (variable.isBound()) {
Object currentValue = null;
try {
currentValue = variable.getVal();
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while processing arguments", e);
}
if (currentValue instanceof Throwable) result.leftShift(currentValue);
else {
soFarArgs.add(currentValue);
evaluateArguments(pool, args, current + 1, soFarArgs, result, original, pooledThreadFlag);
}
} else {
variable.whenBound(pool, new ReactorMessagingRunnable() {
@Override
protected Object doRun(final Object argument) {
if (argument instanceof Throwable) result.leftShift(argument);
else {
soFarArgs.add(argument);
evaluateArguments(pool, args, current + 1, soFarArgs, result, original, true);
}
return null;
}
});
}
} else {
soFarArgs.add(currentArgument);
evaluateArguments(pool, args, current + 1, soFarArgs, result, original, pooledThreadFlag);
}
}
}
}