edu.mit.streamjit.impl.compiler2.Actor.java Source code

Java tutorial

Introduction

Here is the source code for edu.mit.streamjit.impl.compiler2.Actor.java

Source

/*
 * Copyright (c) 2013-2015 Massachusetts Institute of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package edu.mit.streamjit.impl.compiler2;

import static com.google.common.base.Preconditions.*;
import com.google.common.collect.Collections2;
import com.google.common.collect.ContiguousSet;
import com.google.common.collect.DiscreteDomain;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Range;
import com.google.common.reflect.TypeToken;

import edu.mit.streamjit.api.Rate;
import edu.mit.streamjit.util.ReflectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * The compiler IR for a Worker or Token.
 * @author Jeffrey Bosboom <jbosboom@csail.mit.edu>
 * @since 9/21/2013
 */
public abstract class Actor implements Comparable<Actor> {
    private ActorGroup group;
    /**
     * The upstream and downstream Storage, one for each input or output of this
     * Actor.  TokenActors will have either inputs xor outputs.
     */
    private final ArrayList<Storage> upstream = new ArrayList<>(), downstream = new ArrayList<>();
    /**
     * Index functions (int -> int) that transform a nominal index
     * (iteration * rate + popCount/pushCount (+ peekIndex)) into a physical
     * index (subject to further adjustment if circular buffers are in use).
     * One for each input or output of this actor.
     */
    private final ArrayList<IndexFunction> upstreamIndex = new ArrayList<>(), downstreamIndex = new ArrayList<>();
    /**
     * Liveness information for the Storage on the inputs of this actor.  Lazily
     * initialized in inputSlots.
     */
    private ArrayList<StorageSlotList> inputSlots;
    private TypeToken<?> inputType, outputType;

    protected Actor(TypeToken<?> inputType, TypeToken<?> outputType) {
        //It would be technically more correct to create fresh type variables
        //for each actor, but that should never matter so long as we only care
        //about wrapper types.
        this.inputType = inputType;
        this.outputType = outputType;
    }

    public abstract int id();

    public ActorGroup group() {
        return group;
    }

    void setGroup(ActorGroup group) {
        assert ReflectionUtils.calledDirectlyFrom(ActorGroup.class);
        this.group = group;
    }

    public final boolean isPeeking() {
        for (int i = 0; i < inputs().size(); ++i)
            if (peek(i).max() > pop(i).max())
                return true;
        return false;
    }

    public TypeToken<?> inputType() {
        return inputType;
    }

    public void setInputType(TypeToken<?> type) {
        this.inputType = type;
    }

    public TypeToken<?> outputType() {
        return outputType;
    }

    public void setOutputType(TypeToken<?> type) {
        this.outputType = type;
    }

    public List<Storage> inputs() {
        return upstream;
    }

    public List<Storage> outputs() {
        return downstream;
    }

    public abstract Rate peek(int input);

    public abstract Rate pop(int input);

    public abstract Rate push(int output);

    /**
     * Returns the number of items peeked at but not popped from the given input
     * in a single iteration.
     * @param input the input index
     * @return the number of items peeked but not popped
     */
    public int excessPeeks(int input) {
        return Math.max(0, peek(input).max() - pop(input).max());
    }

    /**
     * Returns the logical indices peeked or popped on the given input during
     * the given iteration.  Note that this method may return a nonempty set
     * even if peeks(input) returns 0 and isPeeking() returns false.
     * @param input the input index
     * @param iteration the iteration number
     * @return the logical indices peeked or popped on the given input during
     * the given iteration
     */
    public ContiguousSet<Integer> peeks(int input, int iteration) {
        return ContiguousSet.create(Range.closedOpen(iteration * pop(input).max(),
                (iteration + 1) * pop(input).max() + excessPeeks(input)), DiscreteDomain.integers());
    }

    /**
     * Returns the logical indices peeked or popped on the given input during
     * the given iterations.  Note that this method may return a nonempty set
     * even if peeks(input) returns 0 and isPeeking() returns false.
     * @param input the input index
     * @param iterations the iteration numbers
     * @return the logical indices peeked or popped on the given input during
     * the given iterations
     */
    public ImmutableSortedSet<Integer> peeks(int input, Set<Integer> iterations) {
        if (iterations.isEmpty())
            return ImmutableSortedSet.of();
        if (iterations instanceof ContiguousSet)
            return peeks(input, (ContiguousSet<Integer>) iterations);
        ImmutableSortedSet.Builder<Integer> builder = ImmutableSortedSet.naturalOrder();
        for (int i : iterations)
            builder.addAll(peeks(input, i));
        return builder.build();
    }

    /**
     * Returns the logical indices peeked or popped on the given input during
     * the given iterations.  Note that this method may return a nonempty set
     * even if peeks(input) returns 0 and isPeeking() returns false.
     * @param input the input index
     * @param iterations the iteration numbers
     * @return the logical indices peeked or popped on the given input during
     * the given iterations
     */
    public ContiguousSet<Integer> peeks(int input, ContiguousSet<Integer> iterations) {
        if (iterations.isEmpty())
            return ContiguousSet.create(Range.closedOpen(0, 0), DiscreteDomain.integers());
        return ContiguousSet.create(
                Range.closedOpen(iterations.first() * pop(input).max(),
                        (iterations.last() + 1) * pop(input).max() + excessPeeks(input)),
                DiscreteDomain.integers());
    }

    /**
     * Returns the logical indices peeked or popped on the given input during
     * the given iterations.  Note that this method may return a nonempty set
     * even if peeks(input) returns 0 and isPeeking() returns false.
     * @param input the input index
     * @param iterations the iteration numbers
     * @return the logical indices peeked or popped on the given input during
     * the given iterations
     */
    public ContiguousSet<Integer> peeks(int input, Range<Integer> iterations) {
        return peeks(input, ContiguousSet.create(iterations, DiscreteDomain.integers()));
    }

    /**
     * Returns the logical indices popped on the given input during the given
     * iteration.
     * @param input the input index
     * @param iteration the iteration number
     * @return the logical indices popped on the given input during the given
     * iteration
     */
    public ContiguousSet<Integer> pops(int input, int iteration) {
        return ContiguousSet.create(
                Range.closedOpen(iteration * pop(input).max(), (iteration + 1) * pop(input).max()),
                DiscreteDomain.integers());
    }

    /**
     * Returns the logical indices popped on the given input during the given
     * iteration.
     * @param input the input index
     * @param iterations the iteration numbers
     * @return the logical indices popped on the given input during the given
     * iterations
     */
    public ImmutableSortedSet<Integer> pops(int input, Set<Integer> iterations) {
        if (iterations.isEmpty())
            return ImmutableSortedSet.of();
        if (iterations instanceof ContiguousSet)
            return pops(input, (ContiguousSet<Integer>) iterations);
        ImmutableSortedSet.Builder<Integer> builder = ImmutableSortedSet.naturalOrder();
        for (int i : iterations)
            builder.addAll(pops(input, i));
        return builder.build();
    }

    /**
     * Returns the logical indices popped on the given input during the given
     * iteration.
     * @param input the input index
     * @param iterations the iteration numbers
     * @return the logical indices popped on the given input during the given
     * iterations
     */
    public ContiguousSet<Integer> pops(int input, ContiguousSet<Integer> iterations) {
        if (iterations.isEmpty())
            return ContiguousSet.create(Range.closedOpen(0, 0), DiscreteDomain.integers());
        return ContiguousSet.create(
                Range.closedOpen(iterations.first() * pop(input).max(), (iterations.last() + 1) * pop(input).max()),
                DiscreteDomain.integers());
    }

    /**
     * Returns the logical indices popped on the given input during the given
     * iteration.
     * @param input the input index
     * @param iterations the iteration numbers
     * @return the logical indices popped on the given input during the given
     * iterations
     */
    public ContiguousSet<Integer> pops(int input, Range<Integer> iterations) {
        return pops(input, ContiguousSet.create(iterations, DiscreteDomain.integers()));
    }

    /**
     * Returns the logical indices pushed to the given output during the given
     * iteration.
     * @param output the output index
     * @param iteration the iteration number
     * @return the logical indices pushed to the given input during the given
     * iteration
     */
    public ContiguousSet<Integer> pushes(int output, int iteration) {
        return ContiguousSet.create(
                Range.closedOpen(iteration * push(output).max(), (iteration + 1) * push(output).max()),
                DiscreteDomain.integers());
    }

    /**
     * Returns the logical indices pushed to the given output during the given
     * iterations.
     * @param output the output index
     * @param iterations the iteration numbers
     * @return the logical indices pushed to the given input during the given
     * iterations
     */
    public ImmutableSortedSet<Integer> pushes(int output, Set<Integer> iterations) {
        if (iterations.isEmpty())
            return ImmutableSortedSet.of();
        if (iterations instanceof ContiguousSet)
            return pushes(output, (ContiguousSet<Integer>) iterations);
        ImmutableSortedSet.Builder<Integer> builder = ImmutableSortedSet.naturalOrder();
        for (int i : iterations)
            builder.addAll(pushes(output, i));
        return builder.build();
    }

    /**
     * Returns the logical indices pushed to the given output during the given
     * iterations.
     * @param output the output index
     * @param iterations the iteration numbers
     * @return the logical indices pushed to the given input during the given
     * iterations
     */
    public ContiguousSet<Integer> pushes(int output, ContiguousSet<Integer> iterations) {
        if (iterations.isEmpty())
            return ContiguousSet.create(Range.closedOpen(0, 0), DiscreteDomain.integers());
        return ContiguousSet.create(Range.closedOpen(iterations.first() * push(output).max(),
                (iterations.last() + 1) * push(output).max()), DiscreteDomain.integers());
    }

    /**
     * Returns the logical indices pushed to the given output during the given
     * iterations.
     * @param output the output index
     * @param iterations the iteration numbers
     * @return the logical indices pushed to the given input during the given
     * iterations
     */
    public ContiguousSet<Integer> pushes(int output, Range<Integer> iterations) {
        return pushes(output, ContiguousSet.create(iterations, DiscreteDomain.integers()));
    }

    public List<IndexFunction> inputIndexFunctions() {
        return upstreamIndex;
    }

    public int translateInputIndex(int input, int logicalIndex) {
        checkArgument(logicalIndex >= 0);
        IndexFunction idxFxn = upstreamIndex.get(input);
        try {
            return idxFxn.applyAsInt(logicalIndex);
        } catch (Throwable ex) {
            throw new AssertionError(String.format("index functions should not throw; translateInputIndex(%d, %d)",
                    input, logicalIndex), ex);
        }
    }

    public ImmutableSortedSet<Integer> translateInputIndices(final int input, Set<Integer> logicalIndices) {
        return ImmutableSortedSet
                .copyOf(Collections2.transform(logicalIndices, index -> translateInputIndex(input, index)));
    }

    public ImmutableSortedSet<Integer> translateInputIndices(final int input, Range<Integer> logicalIndices) {
        return translateInputIndices(input, ContiguousSet.create(logicalIndices, DiscreteDomain.integers()));
    }

    public List<IndexFunction> outputIndexFunctions() {
        return downstreamIndex;
    }

    public int translateOutputIndex(int output, int logicalIndex) {
        checkArgument(logicalIndex >= 0);
        IndexFunction idxFxn = downstreamIndex.get(output);
        try {
            return idxFxn.applyAsInt(logicalIndex);
        } catch (Throwable ex) {
            throw new AssertionError(String.format("index functions should not throw; translateOutputIndex(%d, %d)",
                    output, logicalIndex), ex);
        }
    }

    public ImmutableSortedSet<Integer> translateOutputIndices(final int input, Set<Integer> logicalIndices) {
        return ImmutableSortedSet
                .copyOf(Collections2.transform(logicalIndices, index -> translateOutputIndex(input, index)));
    }

    public ImmutableSortedSet<Integer> translateOutputIndices(final int input, Range<Integer> logicalIndices) {
        return translateOutputIndices(input, ContiguousSet.create(logicalIndices, DiscreteDomain.integers()));
    }

    public ImmutableSortedSet<Integer> reads(int input, int iteration) {
        return translateInputIndices(input, peeks(input, iteration));
    }

    public ImmutableSortedSet<Integer> reads(int input, Set<Integer> iterations) {
        return translateInputIndices(input, peeks(input, iterations));
    }

    public ImmutableSortedSet<Integer> reads(int input, Range<Integer> iterations) {
        return translateInputIndices(input, peeks(input, iterations));
    }

    public ImmutableSortedSet<Integer> reads(Storage storage, int iteration) {
        List<ImmutableSortedSet<Integer>> list = new ArrayList<>(inputs().size());
        for (int input = 0; input < inputs().size(); ++input)
            if (inputs().get(input).equals(storage))
                list.add(translateInputIndices(input, peeks(input, iteration)));
        return ImmutableSortedSet.copyOf(Iterables.concat(list));
    }

    public ImmutableSortedSet<Integer> reads(Storage storage, Set<Integer> iterations) {
        List<ImmutableSortedSet<Integer>> list = new ArrayList<>(inputs().size());
        for (int input = 0; input < inputs().size(); ++input)
            if (inputs().get(input).equals(storage))
                list.add(translateInputIndices(input, peeks(input, iterations)));
        return ImmutableSortedSet.copyOf(Iterables.concat(list));
    }

    public ImmutableSortedSet<Integer> reads(Storage storage, Range<Integer> iterations) {
        List<ImmutableSortedSet<Integer>> list = new ArrayList<>(inputs().size());
        for (int input = 0; input < inputs().size(); ++input)
            if (inputs().get(input).equals(storage))
                list.add(translateInputIndices(input, peeks(input, iterations)));
        return ImmutableSortedSet.copyOf(Iterables.concat(list));
    }

    public ImmutableMap<Storage, ImmutableSortedSet<Integer>> reads(int iteration) {
        ImmutableMap.Builder<Storage, ImmutableSortedSet<Integer>> builder = ImmutableMap.builder();
        for (Storage s : inputs())
            builder.put(s, reads(s, iteration));
        return builder.build();
    }

    public ImmutableMap<Storage, ImmutableSortedSet<Integer>> reads(Set<Integer> iterations) {
        ImmutableMap.Builder<Storage, ImmutableSortedSet<Integer>> builder = ImmutableMap.builder();
        for (Storage s : inputs())
            builder.put(s, reads(s, iterations));
        return builder.build();
    }

    public ImmutableMap<Storage, ImmutableSortedSet<Integer>> reads(Range<Integer> iterations) {
        ImmutableMap.Builder<Storage, ImmutableSortedSet<Integer>> builder = ImmutableMap.builder();
        for (Storage s : inputs())
            builder.put(s, reads(s, iterations));
        return builder.build();
    }

    public ImmutableSortedSet<Integer> consumes(int input, int iteration) {
        return translateInputIndices(input, pops(input, iteration));
    }

    public ImmutableSortedSet<Integer> consumes(int input, Set<Integer> iterations) {
        return translateInputIndices(input, pops(input, iterations));
    }

    public ImmutableSortedSet<Integer> consumes(int input, Range<Integer> iterations) {
        return translateInputIndices(input, pops(input, iterations));
    }

    public ImmutableSortedSet<Integer> consumes(Storage storage, int iteration) {
        List<ImmutableSortedSet<Integer>> list = new ArrayList<>(inputs().size());
        for (int input = 0; input < inputs().size(); ++input)
            if (inputs().get(input).equals(storage))
                list.add(translateInputIndices(input, pops(input, iteration)));
        return ImmutableSortedSet.copyOf(Iterables.concat(list));
    }

    public ImmutableSortedSet<Integer> consumes(Storage storage, Set<Integer> iterations) {
        List<ImmutableSortedSet<Integer>> list = new ArrayList<>(inputs().size());
        for (int input = 0; input < inputs().size(); ++input)
            if (inputs().get(input).equals(storage))
                list.add(translateInputIndices(input, pops(input, iterations)));
        return ImmutableSortedSet.copyOf(Iterables.concat(list));
    }

    public ImmutableSortedSet<Integer> consumes(Storage storage, Range<Integer> iterations) {
        List<ImmutableSortedSet<Integer>> list = new ArrayList<>(inputs().size());
        for (int input = 0; input < inputs().size(); ++input)
            if (inputs().get(input).equals(storage))
                list.add(translateInputIndices(input, pops(input, iterations)));
        return ImmutableSortedSet.copyOf(Iterables.concat(list));
    }

    public ImmutableMap<Storage, ImmutableSortedSet<Integer>> consumes(int iteration) {
        ImmutableMap.Builder<Storage, ImmutableSortedSet<Integer>> builder = ImmutableMap.builder();
        for (Storage s : inputs())
            builder.put(s, consumes(s, iteration));
        return builder.build();
    }

    public ImmutableMap<Storage, ImmutableSortedSet<Integer>> consumes(Set<Integer> iterations) {
        ImmutableMap.Builder<Storage, ImmutableSortedSet<Integer>> builder = ImmutableMap.builder();
        for (Storage s : inputs())
            builder.put(s, consumes(s, iterations));
        return builder.build();
    }

    public ImmutableMap<Storage, ImmutableSortedSet<Integer>> consumes(Range<Integer> iterations) {
        ImmutableMap.Builder<Storage, ImmutableSortedSet<Integer>> builder = ImmutableMap.builder();
        for (Storage s : inputs())
            builder.put(s, consumes(s, iterations));
        return builder.build();
    }

    public ImmutableSortedSet<Integer> writes(int output, int iteration) {
        return translateOutputIndices(output, pushes(output, iteration));
    }

    public ImmutableSortedSet<Integer> writes(int output, Set<Integer> iterations) {
        return translateOutputIndices(output, pushes(output, iterations));
    }

    public ImmutableSortedSet<Integer> writes(int output, Range<Integer> iterations) {
        return translateOutputIndices(output, pushes(output, iterations));
    }

    public ImmutableSortedSet<Integer> writes(Storage storage, int iteration) {
        List<ImmutableSortedSet<Integer>> list = new ArrayList<>(outputs().size());
        for (int output = 0; output < outputs().size(); ++output)
            if (outputs().get(output).equals(storage))
                list.add(translateOutputIndices(output, pushes(output, iteration)));
        return ImmutableSortedSet.copyOf(Iterables.concat(list));
    }

    public ImmutableSortedSet<Integer> writes(Storage storage, Set<Integer> iterations) {
        List<ImmutableSortedSet<Integer>> list = new ArrayList<>(outputs().size());
        for (int output = 0; output < outputs().size(); ++output)
            if (outputs().get(output).equals(storage))
                list.add(translateOutputIndices(output, pushes(output, iterations)));
        return ImmutableSortedSet.copyOf(Iterables.concat(list));
    }

    public ImmutableSortedSet<Integer> writes(Storage storage, Range<Integer> iterations) {
        List<ImmutableSortedSet<Integer>> list = new ArrayList<>(outputs().size());
        for (int output = 0; output < outputs().size(); ++output)
            if (outputs().get(output).equals(storage))
                list.add(translateOutputIndices(output, pushes(output, iterations)));
        return ImmutableSortedSet.copyOf(Iterables.concat(list));
    }

    public ImmutableMap<Storage, ImmutableSortedSet<Integer>> writes(int iteration) {
        ImmutableMap.Builder<Storage, ImmutableSortedSet<Integer>> builder = ImmutableMap.builder();
        for (Storage s : outputs())
            builder.put(s, writes(s, iteration));
        return builder.build();
    }

    public ImmutableMap<Storage, ImmutableSortedSet<Integer>> writes(Set<Integer> iterations) {
        ImmutableMap.Builder<Storage, ImmutableSortedSet<Integer>> builder = ImmutableMap.builder();
        for (Storage s : outputs())
            builder.put(s, writes(s, iterations));
        return builder.build();
    }

    public ImmutableMap<Storage, ImmutableSortedSet<Integer>> writes(Range<Integer> iterations) {
        ImmutableMap.Builder<Storage, ImmutableSortedSet<Integer>> builder = ImmutableMap.builder();
        for (Storage s : outputs())
            builder.put(s, writes(s, iterations));
        return builder.build();
    }

    public StorageSlotList inputSlots(int input) {
        if (inputSlots == null) {
            inputSlots = new ArrayList<>(inputs().size());
            for (int i = 0; i < inputs().size(); ++i)
                inputSlots.add(new StorageSlotList());
        }
        return inputSlots.get(input);
    }

    @Override
    public final int compareTo(Actor o) {
        return Integer.compare(id(), o.id());
    }

    @Override
    public final boolean equals(Object obj) {
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final Actor other = (Actor) obj;
        if (id() != other.id())
            return false;
        return true;
    }

    @Override
    public final int hashCode() {
        return id();
    }
}