Paul Toone avatar image
Paul Toone posted

Task Sequence Preempting   

Every task sequence has a preempting value. Preempting is used to break a TaskExecuter away from its current operation to execute a more important operation. For example, operator A's most important responsibility is to repair machines. When there are no machines to repair, however, it should also transport material throughout the model. If a machine breaks down while operator A is in the middle of transporting a flowitem somewhere, then the operator should stop whatever he is doing and repair the machine, instead of finishing the transport operation. To do this, you will need to use a preempting task sequence to break the operator away from his current operation.

To create a preempting task sequence, specify a non-zero value in the preempt parameter of the createemptytasksequence() command.

createemptytasksequence(operator, 0, PREEMPT_ONLY);

There are four possible preempt values. These values tell the TaskExecuter what to do with the original task sequence(s) that have been preempted.

  • 0 - PREEMPT_NOT - This value is non-preempting.
  • 1 - PREEMPT_ONLY - If a task sequence has this value, then the TaskExecuter will preempt the currently active task sequence and put it back in its task sequence queue to be finished later. When a task sequence is preempted, it is automatically placed at the front of the task sequence queue. When the TaskExecuter eventually comes back to the original task sequence, the current task in that task sequence will be done over again, since it was not finished. Also, you can specify a series of tasks to do over again when it comes back to the task sequence using the TASKTYPE_MILESTONE task. This preempt value is the most common used.
  • 2 - PREEMPT_AND_ABORT_ACTIVE - If a task sequence has this value, then the TaskExecuter will stop the currently active task sequence and destroy it, so that it will never come back to that original task sequence.
  • 3 - PREEMPT_AND_ABORT_ALL - If a task sequence has this value, then the TaskExecuter will stop the currently active task sequence, destroy it, and destroy all task sequences in its task sequence queue.

To query or change the preempting and/or priority values of a task sequence, you can use the getpreempt(), setpreempt(), getpriority(), and setpriority() commands. For more information on these commands, refer to the Commands documentation found through FlexSim's Help menu.

Interaction Between Multiple Preempting Task Sequences

If a TaskExecuter is currently working on a preempting task sequence, and it receives a new task sequence that is also preempting, it will use the priority value of the task sequence to determine which task sequence to do. If the priority value of the new task sequence is higher than the priority value of the one it is currently working on, the TaskExecuter will preempt its current task sequence and execute the new one. If the priority value of the new task sequence is less than or equal to the priority of the task sequence it is currently working on, then the TaskExecuter will not preempt the active task sequence, but will queue up the new task sequence just like any other task sequence it receives. If it must queue up the task sequence, it will not take the preempt value into account for its queueing logic unless you explicitly tell it to in the queue strategy.

Note on queueing a preempting task sequence: If a preempting task sequence does not actually preempt a TaskExecuter, then it will be queued up like any other task sequence. If you want to have preempting task sequence be brought to the front of the queue, then either make your preempting task sequences have higher priority than all other task sequences, or take preempting into account in the queue strategy.

Preempting Travel Tasks on Networks with Traffic Controls

Preemption can have some undesirable side effects if a TaskExecuter is traveling along a network with TrafficControls when the preemption happens. If preemption occurs when a TaskExecuter is traveling along a network edge, then the TaskExecuter will be "taken off" that edge and connected in an "inactive" travel state (the red line) to the next network node he would have arrived at had he finished traveling the edge. If the network node is a member of a TrafficControl whose area starts at that node (in other words, the TaskExecuter wasn't in the area yet when he was preempted), then the TaskExecuter will be "forced" into the traffic control area, meaning this may cause the number of objects in the area to exceed the maximum for that traffic control area. To avoid this, special logic has been added to the TaskExecuter's preemption mechanism, so that if he is preempted from a travel task directly to another travel task, then instead of being taken off the edge and connected to the next node, the preemption will call redirectnetworktraveler(), which will essentially keep him traveling as he was before on the edge, but his final destination will be changed so that when he arrives at the end of the edge, he will continue on a new path to the new destination. Note that this will only happen if the preemption mechanism can detect that the first durative task that the TaskExecuter will perform after the preemption is another travel task. By durative we mean any task that will take some amount of time to perform: TASKTYPE_TRAVEL, TASKTYPE_LOAD, TASKTYPE_UTILIZE, TASKTYPE_DELAY, etc. are durative, whereas TASKTYPE_SETNODENUM, TASKTYPE_TAG, TASKTYPE_MOVEOBJECT, TASKTYPE_SENDMESSAGE, TASKTYPE_NODEFUNCTION are not. If the preemption detects that the next durative task is not a travel task, then it will take the TaskExecuter off the edge as described above, in which case the TaskExecuter may be forced into a traffic control area.

Preempting With Dispatchers

If a preempting task sequence is given to a Dispatcher, the Dispatcher will not consider the preempt value of the task sequence unless you explicitly tell it to. If the Dispatcher is set to dispatch to the first available TaskExecuter, then it will do just that, and not send the preempting task sequence immediately to a TaskExecuter. If you want the Dispatcher to dispatch preempting task sequences immediately, then you will need to specify such logic in its Pass To function.

A TaskExecuter may be connected back to a Dispatcher by dragging an A-connect from the TaskExecuter to the Dispatcher. If this is done, then when the TaskExecuter receives a preempting task it will pass its current task back to the Dispatcher. The Dispatcher will then redistribute that task according to its dispatching logic. Tasks returned to the Dispatcher in this manner are returned in their current state so that the next TaskExecuter will begin where the previous TaskExecuter left off. This may cause some odd behavior that you should take into consideration when assigning preempting tasks. For example, if a TaskExecuter is traveling with an item when it is preempted, the TaskExecuter that receives this task will perform the travel and unload tasks without ever picking up the item from the first TaskExecuter. Instead, the item will "magically" appear at the right location when the unload completes. In order to prevent these odd behaviors you may want to query the TaskExecuter's state to determine if it is in a "preemptable" state (as you define it) before assigning the new task.

flexsim users manual
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.



paul.t contributed to this article


FlexSim 2016.1