/*
 * Bus.java
 *
 * Created on Mar 26, 2016
 *
 * Copyright (c) 2016  Artur Rataj.
 *
 * This code is distributed under the terms of the GNU Library
 * General Public License, either version 3 of the license or, at
 * your option, any later version.
 */

package mirela;

import mirela.*;
import hc.*;

/**
 * A bus. A packet size is copied from that of a producer.
 * 
 * @author Artur Rataj
 */
public class Bus extends AbstractConsumer {
    /**
     * Transmission time of data from subsequent inputs, fixed part.
     */
    AbstractDelay transmissionFixed;
    /**
     * Transmission time of data from subsequent inputs, per byte.
     */
    AbstractDelay transmissionPerByte;
    /**
     * Total transmission type, computed after the packet size is known.
     */
    AbstractDelay transmissionTotal;
    PairBarrier sync;
    /**
     * Creates a new instance of <code>First</code>.
     * 
     * @param system Mirela system, to which this node will be added
     * @param fixed transmission time of data from subsequent inputs, fixed part
     * @param perByte transmission time of data from subsequent inputs, per byte;
     * null for no extra overhead caused by size; if not null, the producer must
     * specify its packet size
     */
    public Bus(Mirela system, AbstractDelay fixed, AbstractDelay perByte) {
        super(system);
        transmissionTotal = transmissionFixed = fixed;
        transmissionPerByte = perByte;
        sync = new PairBarrier();
    }
    @Override
    public void addProducer(AbstractNode producer) {
        super.addProducer(producer);
        if(transmissionPerByte != null && packetSize != -1)
            transmissionTotal = transmissionFixed.getSum(
                    transmissionPerByte.getProduct(packetSize));
    }
    public void put(int index) {
        sync.produce(index);
    }
    @Override
    public void active() {
        if(transmissionPerByte != null && packetSize == -1)
            throw new RuntimeException("transmission per byte but no packet size");
        super.active();
        sync.activate(numProducers, 1);
    }
    @Override
    public void run() {
        while(true) {
            sync.consume();
            transmissionTotal.sleep();
            produce();
        }
    }
}
