Renewable Resources

21 Mar 2023

Commands may produce, or renew, resources, in addition to consuming resources. Consider the resource requirements of these commands:

  • Command c1 requires <sys_memory, 0.75>

  • Command c2 requires <sys_memory, -0.125>

  • Command c3 requires <sys_memory, 0.375>

In our example, commands c1 and c3 consume 0.75 and 0.375 units of sys_memory respectively, while c2 produces 0.125 units of sys_memory.

Commands c1 and c3 can’t execute simultaneously, because their total sys_memory usage, 1.125, would exceed the limit of 1.0. But if c2 is started after c1, its production of sys_memory reduces total usage enough to allow c3 to execute.

Note that this can only work if the commands are started on successive macro steps. Resource consumption and production are accounted for separately by the resource arbiter, starting from the resources already allocated at the beginning of the macro step. If all 3 nodes begin execution at once, no matter how the resource priorities are arranged, the resource arbiter will reject 2 of the 3 commands.

The entire PLEXIL plan (filed in plexil/examples/resource4.ple) is given below.

Integer Command c1;
Integer Command c2;
Integer Command c3;

SimpleTask:
Concurrence
{
  C1: {
    Integer returnValue = -1;
    EndCondition returnValue == 10;
    PostCondition C1.command_handle == COMMAND_SUCCESS;
    Resource Name = "sys_memory",
      UpperBound = 0.75,
      Priority = 20;
    returnValue = c1();
  }
  C2: {
    Integer returnValue = -1;
    StartCondition Sibling(C1).state == EXECUTING;
    EndCondition returnValue == 10;
    PostCondition C2.command_handle == COMMAND_SUCCESS;
    Resource Name = "sys_memory",
      UpperBound = -0.125,
      Priority = 40;
    returnValue = c2();
  }
  C3: {
    Integer mem_priority = 30;
    Integer returnValue = -1;
    StartCondition Sibling(C2).state == EXECUTING;
    EndCondition returnValue == 10;
    PostCondition C3.command_handle == COMMAND_SUCCESS;
    Resource Name = "sys_memory",
      UpperBound = 0.375,
      Priority = mem_priority;
    returnValue = c3();
  }
}