package DPJRuntime.Framework;
import extra166y.*;
import DPJRuntime.Framework.ArrayOps.*;
/**
* <p>class DisjointArray</p>
*
* <p>A linear array supporting safe parallel updates to its members.
* Supports several generic parallel operations that can be
* specialized via hook methods. Details TBA.</p>
**/
public final class DisjointArray<type T<region TR>, region AR>
implements DisjointContainer {
private final extra166y.ParallelArray<T> array in AR;
/**
* Constructor for use by create*() methods or subclasses
* to create a new DPJParallelArray, initially using the supplied
* array. To create a DisjointArray for now, use {@link #create},
* followed by the {@link #DisjointGenerator()} to populate it, or use
* {@link #withIndexedMapping} to create a new instance from an old one.
*
* @param array: the underlying ParallelArray instance
*/
private DisjointArray(extra166y.ParallelArray<T> array) pure {
this.array = array;
if (array == null)
throw new NullPointerException();
}
/** Hack to get around the fact that we can't write C<R>.class in
* the client. Also, it would be better to make T<TR> a method param
* and eliminate the extra class, but such isn't supported in the
* compiler yet! */
public static final class Creator<type T<region TR>, region AR> {
public DisjointArray<T,AR> create(int size,
Class<T<Root>> fakeEltType) pure{
Class<T> actualEltType = (Class<T>) fakeEltType;
extra166y.ParallelArray<T> array = extra166y.ParallelArray.
<T>create(size, actualEltType,
extra166y.ParallelArray.defaultExecutor());
return new DisjointArray<T,AR>(array);
}
}
/**
* Parallel methods for constructing, mapping and transforming
* all elements in the array.
*/
/** Parallel construction (non-indexed) of all elements.
*
* @param op: Operation to generate each new object of the array.
**/
public <effect E | effect E # writes AR effect E>
void replaceWithGeneratedValue(DisjointGenerator<T, effect E> generator)
writes AR effect E {
extra166y.Ops.Generator<T> wrapper = new DisjointGeneratorWrapper<T,effect E>(generator);
array.replaceWithGeneratedValue(wrapper);
}
// where
private class DisjointGeneratorWrapper<type T, effect E>
implements extra166y.Ops.Generator<T> {
private DisjointGenerator<T, effect E> generator;
public DisjointGeneratorWrapper(DisjointGenerator<T, effect E> generator) {
this.generator = generator;
}
public T op() { return generator.op(); }
}
/** Parallel unindexed mapping operation on all elements.
*
* @param op: Op. to generate a new object for each object in old array.
*
* @return : New DPJParallelArray<T2,AR> with objects produced by mapping.
*/
public <type T2<region R>, effect E | effect E # reads AR writes TR:* effect E>
DisjointArray<T2,AR>
withMapping(DisjointObjectToObject<T, T2, effect E> op)
reads AR effect E {
return new DisjointArray<T2,AR>
(array.withMapping(new DisjointObjectToObjectWrapper<T,T2,effect E>(op)).all());
}
// where
private class DisjointObjectToObjectWrapper<type T1, T2<region R>, effect E>
implements extra166y.Ops.Op<T1, T2> {
private DisjointObjectToObject<T1, T2, effect E> theOp;
public DisjointObjectToObjectWrapper(DisjointObjectToObject<T1, T2,effect E> op) { theOp = op; }
public final T2 op(T1 obj) { return theOp.<region R>op(obj); }
}
/** Parallel indexed mapping operation on all elements.
*
* @param op: Op. to generate a new object for each object in old array.
*
* @return : New DPJParallelArray<T,AR> with objects produced by mapping.
*/
public <type T2<region R>, effect E | effect E # reads AR writes TR:* effect E>
DisjointArray<T2,AR>
withIndexedMapping(DisjointIntAndObjectToObject<T, T2, effect E> mapper)
reads AR effect E {
return new DisjointArray<T2,AR>(array.withIndexedMapping
(new DisjointIntAndObjectToObjectWrapper<T,T2,effect E>(mapper)).
all());
}
// where
private class DisjointIntAndObjectToObjectWrapper<type T1, T2, effect E>
implements extra166y.Ops.IntAndObjectToObject<T1,T2> {
private DisjointIntAndObjectToObject<T1,T2,effect E> mapper;
public DisjointIntAndObjectToObjectWrapper
(DisjointIntAndObjectToObject<T1,T2,effect E> mapper)
{ this.mapper = mapper; }
public final T2 op(int idx, T1 obj) { return mapper.op(idx, obj); }
}
/** Parallel reduction of elements into a single value.
*
* @param op: Op. to reduce all elements into a single element.
* Op must be associative or results may be nondeterministic.
*
* @return : result of reduction
*/
public <effect E | effect E # reads AR effect E>
T reduce(Reducer<T, effect E> op, T base)
reads AR effect E {
return array.reduce(new ReducerWrapper<effect E>(op), base);
}
// where
private class ReducerWrapper<effect E> implements extra166y.Ops.Reducer<T> {
private Reducer<T, effect E> theReducer;
public ReducerWrapper(Reducer<T, effect E> reducer) { theReducer = reducer; }
public final T op(T a, T b) { return theReducer.op(a, b); }
}
public int size() pure { return array.size(); }
public T get(int i) reads AR { return array.get(i); }
}