Paul Toone avatar image
Paul Toone posted

Coordinated Task Sequences   

Coordinated task sequences are used for operations which require sophisticated coordination between two or more TaskExecuters. These task sequences implement concepts like allocation and de-allocation of TaskExecuters, as well as synchronizing several operations being done in parallel.


Coordinated task sequences are built and dispatched using a set of commands which are mutually exclusive from the default task sequence commands. The commands for coordinated task sequences are as follows.








The createcoordinatedtasksequence command takes one parameter, namely a reference to an object. This object is designated as the “task coordinator” who holds the task sequence, as well as coordinates the tasks. The task coordinator can also be one of the objects that is allocated within the task sequence. It can be any Dispatcher or TaskExecuter object. Note that selecting a task coordinator doesn't mean allocating that task coordinator. A task coordinator can be coordinating any number of coordinated task sequences at any one time. Also, unlike regular task sequences, coordinated task sequences are not queued up. The task coordinator will start executing the coordinated task sequence immediately when you dispatch it, no matter how many other coordinated task sequences it is coordinating.


The insertallocatetask command takes four parameters. The first is the task sequence. Second is the TaskExecuter or Dispatcher to give an “allocated” task to. When the task coordinator gets to an allocate task, it will actually create a separate task sequence with an “allocated” task in it, and pass that task sequence to the specified TaskExecuter or Dispatcher. In the case that it is a dispatcher, meaning you want to allocate any one of several TaskExecuters, then you can use the return value of this command as a key to reference the specific one that gets allocated, since you don’t know exactly which one it is at the time that you build the task sequence. The third and fourth parameters are the priority and preempting values of the separate task sequence that will be created. The fifth parameter is optional, and specifies whether the task is blocking. By default (0), the task is blocking. If 1 is passed in, then the task will not be blocking.


The insertproxytask command is similar to the inserttask command, with one parameter, the second, added. The second parameter specifies which allocated object you want to do the task. As the task coordinator is the one actually “executing” the task sequence, once he gets to a proxy task, he will instruct the allocated object to do the task “by proxy.” Notice that for involved1 and involved2, you can either pass in a key or a straight reference to an object.


The insertsync task halts execution of the task sequence until a specified task, referenced by its key, is finished. It takes two parameters: the task sequence, and a key value of a given proxy task. It is important to note that proxy tasks which are specified for different TaskExecuters, by default, will be done in parallel, unless a sync task is specified, whereas proxy tasks given to the same TaskExecuter will automatically be done in sequential order, without the need for a sync task.


The insertdeallocatetask command de-allocates a specific TaskExecuter, referenced by its key. The first parameter references the coordinated task sequence. The second parameter is the allocation key for the resource you want to de-allocate. The third parameter is optional, and specifies whether the task is blocking. By default (0), the task is blocking. If 1 is passed in, then the task will not be blocking.

The above code creates a coordinated task sequence that organizes the two task sequences, as shown in the diagram below.

Coordinated Task Sequence


A team of three operators share two forklifts. An operation needs one operator and one forklift. The operator should travel to the forklift, and the forklift should then move the operator into itself. Then the forklift should travel to the load location, pick an item, then travel to an unload location and drop off the item. Then the forklift should travel to its parking location, and unload the operator. Doing this using simple task sequences would be very difficult, because it deals with two different resources that work in a very coordinated fashion. Coordinated task sequences make this example much easier to simulate. The diagram below illustrates the two task sequences that need to be done for the forklift and operator. Notice that there are some parts where one resource needs to wait and do nothing while the other operates.


The code to build the task sequence would be written as follows. It is assumed that references called operatorteam and forkliftteam have been established. These reference dispatchers to three Operator objects, and two Transporter objects, respectively. References have also been established for a loadstation from which to load, an unloadstation to unload to, and the item.

treenode ts = createcoordinatedtasksequence(operatorteam);  int opkey = insertallocatetask(ts, operatorteam, 0, 0);  int forkliftkey = insertallocatetask(ts, forkliftteam, 0,0);  int traveltask = insertproxytask(ts, opkey, TASKTYPE_TRAVEL, forkliftkey, NULL);  insertsynctask(ts, traveltask);  insertproxytask(ts, forkliftkey, TASKTYPE_MOVEOBJECT, opkey, forkliftkey);  insertproxytask(ts, forkliftkey, TASKTYPE_TRAVEL, loadstation, NULL);  insertproxytask(ts, forkliftkey, TASKTYPE_LOAD, item, loadstation);  insertproxytask(ts, forkliftkey, TASKTYPE_TRAVEL, unloadstation, NULL);  insertproxytask(ts, forkliftkey, TASKTYPE_UNLOAD, item, unloadstation);  insertproxytask(ts, forkliftkey, TASKTYPE_TRAVEL, forkliftteam, NULL);  insertproxytask(ts, forkliftkey, TASKTYPE_MOVEOBJECT, opkey, model());  insertdeallocatetask(ts, forkliftkey);  insertdeallocatetask(ts, opkey);  dispatchcoordinatedtasksequence(ts);

Note on the above example: There are some model maintenance issues involved here. For example, if you happen to stop and reset the model while the operator is inside of the forklift, you will need to move the operator out of the forklift and back into the model from a reset trigger. Also, whenever you move the operator back into the model, you will need to set its location appropriately, since it is transferring between two different coordinate spaces.

Things to Remember

  • The first thing you must do before giving any resource proxy tasks is to allocate that resource.
  • You must get the key back from each allocate task, because you will use it later. The insertproxytask command takes a key for the executer of the proxy task. This is the key that the allocation task returns. You also will use this key when de-allocating the object.
  • While all proxy tasks for the same allocated resource are executed in sequence, proxy tasks for different allocated resources are executed in parallel, unless you explicitly put blocking tasks in the coordinated task sequence.
  • Blocking tasks are ones that block the parallel execution of the coordinated task sequence. The task coordinator goes straight through the task sequence, giving proxy tasks to the appropriate allocated resources, until a blocking task is encountered. It will then wait until that task's blocking requirement is met before continuing the task sequence. In other words, execution of all tasks occurring after that blocking task (regardless of which resource they apply to) will be stopped until the blocking task's requirement is met . The blocking tasks and their blocking requirements are as follows:
  1. Allocation Task: By default this task will block until the specified resource has been allocated. However, if the fifth parameter of insertallocatetask is 1, then the allocate task will not block.
  2. Sync Task: This task will block until the proxy task specified by its key is finished.
  3. De-allocation Task: By default this task will block until the specified resource has finished all its proxy tasks and is de-allocated. However, if the third parameter of insertdeallocatetask is 1, then the de-allocate task will not block.
  • The order in which you insert your tasks can have subtle yet important implications. This is especially true for placing your proxy tasks in relation to blocking tasks. Proxy tasks placed after certain blocking tasks can be executed very differently than if those proxy tasks were inserted before the blocking tasks.
  • Make sure that you de-allocate all objects that you allocate, or the task sequence won't properly release the objects it has allocated.
  • Once you have de-allocated a resource, do not give it any more proxy tasks.

Note on non-blocking de-allocate and allocate tasks: The functionality for allowing these tasks to be non-blocking is still in the beta state. Although we encourage you to use this feature, and there are no known bugs at the time of writing, know that you may run into some problems because this functionality hasn't yet been used extensively.

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