0
votes

I’m trying to model a queue of ships that utilize a static resource which is a single dock (using flowcharts). The queue has three types of agents A, B, and C which have priorities 1, 2, and 3 respectively (this means that ship C has priority in the queue to utilize the dock). Now I need to model the following two behaviors related to preemption:

  1. The task of unloading the ship (the dock’s task when seized) must preempt when ship C arrives BUT not when ship A or B arrives. This means that the priorities defined in the “Task priority” field are valid to define the queue order of attention but not for preemption. The priorities for preemption should be: Ship A and B with priority 1 and Ship C with priority 2. How can I separate the priorities “ratings” for the queue from the priorities used to determine preemption?

shows the issue of having the same priority for queue and preemption

  1. When the task preempt, I need to move the current ship that is using the dock, to a waiting area, and when the task that caused the preemptions ends, the ship that preempted, must return to where the static resource is (the dock) and resume its delay block. How can I do this? I tried using the outPreempted port of the Seize block to add a moveTo block to move the agent to the waiting area, but this port seems to work only when preemption causes to end the task (terminate serving option). The flowchart of the described queue I’m trying to model is shown on the image with some red lines trying to explain intuitively (but wrong) what I’m trying to do:

enter image description here

1
I just solved point 2 with the "On task suspended" and "On task resumed" fields using agent.moveTo(...) function. - juanpablorv

1 Answers

0
votes

Why not separate the two? What you could do is put a Queue object before the Seize with A=1, B=2, C=3 ordering, then set the queue size of the Seize object to 0 and put the pre-emption priorities (A,B=1; C=2) into the Seize task priority field like you've done here.

UPDATE Having looked it some more, it appears the queue size on Seize can not be zero. In this case, the implementation was done using a Wait block. see here

Additionally on enter action of the seize block contains following code:

List<TestTwoSeizes_Demand> toFree = new ArrayList<>();

// there should be one agent in 'wait' and this will 
// mark it for removal
wait.forEach(waitingAgent -> {
    if (!waitingAgent.agent_type.equalsIgnoreCase("C")) {
        waitingAgent.preempted_by_C = true;
        toFree.add(waitingAgent);
    }
});

if (!toFree.isEmpty())
    toFree.forEach(a -> wait.free(a));

Also, the agent flowing through the process has 2 properties:

  1. agent_type - string A, B or C
  2. preempted_by_C - boolean, initially set to 'false'

So this is how it works:

  1. selectOutput sorts agents so that "C" go to seize and A, B goe to seize1
  2. wait is configured to exit on timeout so normally it acts like a delay
  3. seize defines priority 3 and seize1 defines priorities 1, 2 for A & B respectively, so "C" agents in seize will always come first
  4. when a "C" agent appears it will kick out and A or B agent out of wait
  5. selectOutput1 checks if the preempted_by_C flag is not set, and if it is then the kicked out agent goes back into seize1, but it is possible to give them any behaviour

Hopefully this works. Not the cleanest solution, but it seems that it is not possible to do queueing-preemption priority separation using standard configuration options.