Dynamic input

defprimitive
{
  name        { LastOfN }
  domain      { DDF }
  desc
  {
    Given a control input with integer value N,
consume N particles from the data input and
produce only the last of these at the output.
  }

  input
  {
    name { control }
    type { int }
    num  { 0 }
  }

  input
  {
    name { input }
    type { anytype }
    num  { 0 }
  }

  output
  {
    name { output }
    type { =input }
    num  { 0 }
  }

  location { DDF library }

  protected
  {
    int readyToGo;
  }

  constructor
  {
    output.inheritTypeFrom(input);
  }

  setup
  {
    waitFor(control);
    readyToGo = FALSE;
  }

  go
  {
    // get control Particles from "control" porthole
    if (!readyToGo)
    {
      control.receiveData();
    }
    int num = int(control%0);
    if (input.numTokens() >= num)
    {
      // skip the num-1 inputs
      for (int i = num; i > 0; i--)
      {
        input.receiveData();
      }

      // prepare for the next round.
      waitFor(control);
      readyToGo = FALSE;

      // copy last input to output
      if (num < 1) return;
      output%0 = input%0;

      // generate output, and get ready for next firing
      output.sendData();
    }
    else
    {
      waitFor(input, num);
      readyToGo = TRUE;
    }
  }
}

The LastOfN primitive discards the first N − 1 particles from the input porthole and routes the last one to the output porthole. The value N is read from the control input. Since the control data varies, the number of particles to read from the input porthole is variable, as expected for a DDF primitive. The programmer can specify that the input porthole is dynamic by setting the num field of the input declaration to 0 using the preprocessor format:

num {0}

The firing rule of the primitive is controlled by the waitFor method of the DDFStar class (actually, it is defined in the base class, DynDFStar). The waitFor method takes a porthole as an argument, and an optional integer as a second argument. It indicates that the primitive should fire when the amount of data specified by the integer (default is 1) is available on the specified port. In the above example, the setup method specifies that the primitive should first wait for a control input. When a control input arrives, the go method reads the control value, and uses waitFor to specify that the primitive should fire next when the specified number of values have arrived at input. The protected member readyToGo is used to keep track of which input the primitive is waiting for. The line

for (int i = num; i > 0; i--) input.receiveData();

causes the appropriate number of inputs (given by num) to be consumed.