Tech Note

Title:               Asynchronous Material Transfers
Date:              March 31, 2004
Written by:     Peter Bosch
Number:        TN-011
Version:         0.52

Background – We need to find a way to model a solid transfer. In the real world, cake is removed from a vessel and placed in an IBC or drum. That container is then placed somewhere for temporary storage, and later, when the receiving vessel is ready for it, the containers are retrieved, and the cake is placed into the receiving vessel. Up until the advent of this use-case, all transfers were modeled as synchronous operations in the SOM. This TechNote describes a mechanism for modeling asynchronous transfers in the SOM, such that the transfer and receive can occur at different times.

Not A Problem – Asynchronous Transferal of Material

There are two aspects to this challenge – the first one we will discuss is the synchronous or asynchronous transferal of material. The protocol that a receive operation follows (embedded in the TransferInHelper) is that, for each input port, the peer of that port is asked what it expects to transfer out. The receiver then looks to see if all of those materials are already on the connector. If they are, it takes the materials and continues on. If they are not, it becomes a listener to that connector, being notified each time a new material is placed on the connector. Each time a new material is placed on the connector, the receiver wakes up and checks the materials now currently on the connector. As before, if they are on the connector, it takes them and processes them. In they are not, it continues to wait.

Well-suited to a synchronous transfer when the executing tasks are synchronized, this protocol also already supports the concept of an asynchronous transfer, if the executing tasks are not synchronized. The sender may place material on the connector long before the receiver has started to run, and when the receiver runs, the materials are there and may be retrieved and used. Alternatively, if the receiver runs before the sender, it will enter its “waiting for materials” sleep, and when the materials are placed on the connector by the sender, once it runs, the receiver will wake up and accept the materials.

The sender, if it runs before the receiver, may transfer materials out, and then continue onward to other tasks. The receiver will pick up the materials when it is ready.

The receiver, if it runs before the sender, will wait for the sender to run, and eventually to transfer materials out.

The Challenge – Remapping & Establishing Plumbing

The challenge comes in because we need to establish plumbing between transfer and receive operation steps during remapping, when child tasks are being created and attached. Currently, the two operations remap in lock-step, and the transfer opStep establishes the connection once the receive OpStep has created its children. But we want, now, to be able to remap independently, since the transfer and the receive operations need to be able to happen independently to each other.
Synchronous Mapping & Plumbing – Transferring Liquid

A transfer operation and its partner receive operation are synchronized – that is, neither can start until both are ready to start. Both operations therefore start at the same time, when the synchronizer fires. In Figure 1 below, the labels (1,2) and (2,1) indicate that either task’s precursors can be satisfied first – neither runs until they are both ready. First, they are given an opportunity to remap (which includes the creation of, and establishment of ancillary plumbing for, OperationSteps under each.) The way this happens is that the transfer operation begins remapping (3) creates its children (4), and then yields so that the receive operation’s remap event can fire (5) and it can create its children (6) and then call Yield. Finally, the transfer operation continues its remapping, establishing a connection between its own transfer-out operation step and its partner operation’s receive operation step (7). When the transfer operation finishes creating the connection it enters its PreDelay, allowing the receive operation also to continue.

synchronous mapping and plumbing

Figure 1 : Synchronous Mapping & Plumbing


Asynchronous Mapping & Plumbing – Transferring Solids

A Transfer-Solid operation is done asynchronously, and is described in Figure 2. The key difference is that the transfer operation can do its portion of mapping, and then continue onward, allowing the receive operation to do its mapping, and complete the plumbing hook-up when it is otherwise enabled to run.

The first two things (1,2)/(2,1) to happen are the incoming events to the pre-vertices of the transfer and receive operations. Once the Transfer operation’s pre-vertex is satisfied, its remapping event (3) fires, the transfer operation’s child tasks are created (4), and a “dangling connector” – a connector with a supplier but no consumer – is created. A yield operation lets anyone else queued up for that time-slot run. The remapping event returns, and the Transfer operation’s pre-vertex fires. This causes the CoStart ligature to (5) satisfy the pre-vertex of the receive operation, possibly enabling that operation to run, too (if its other precursors have completed). Once the receiving operation is ready to run, its remapping event fires (6), its child OpSteps are created (7), and a connection is established between the existing “dangling connector” and the receive opStep (8).

 

Figure 2 : Asynchronous Mapping & Plumbing


Integration APIs

The current APIs and steps for integration of this mechanism are as follows:

1.)    After creating the transfer and receive operations:

mb.CreateAsyncTransfer(transferFlour,m_xferFlourPortKey,receiveFlour,m_recvFlourPortKey);

2.)    …Then in the transfer operation after remapping, create a dangling connection keyed to the Guid of your choice:

mb.CreateAsyncTransferConnection(theTask,m_xferFlourPortKey,m_looseEndIdentifier);

3.)    …finally in the receive operation, connect to the dangling connection by referencing the key Guid:

mb.ConnectToAsyncTransferConnection(m_looseEndIdentifier,theTask,m_recvFlourPortKey);

 

These APIs can be wrapped, and may change as we proceed into integration, but this is where they stand right now – it seems wise to wait ‘til integration is ready to proceed, to do smoothing & wrapping of this API & mechanism.

Test/Demo Application

There is a test case that demonstrates this mechanism, in zTestUnsynchedTransfers.cs. This test is intended as both a test and a demonstration of the new proposed mechanism.

unit recipeWe run the test with varying values for d1 and d2, to ensure that the transfer and receive operations occur in both orders (transfer-first, transfer-second) and simultaneously.

We report when the transfer and receive operations are starting, when their remapping events run, when material arrives at the transfer operation’s output port and the receive operation’s input port, and when the dangling connector is created, and subsequently, when it is attached to.

Results are in the next section.
Test Results

 

Running transfer test with transfer operation delayed by 00:00:00,

                        and receive operation delayed by 00:00:00.

...destroying Synchronizer

...adding CoStart

1/1/0001 12:00:00 AM : Transfer Flour Remapping is being called.

                Creating Dangling Connector under key 07072ea9-5943-44ed-b972-16306546202b

1/1/0001 12:00:00 AM : Transfer Flour execution is starting.

1/1/0001 12:00:00 AM : Receive Flour Remapping is being called.

                Attaching to Dangling Connector under key 07072ea9-5943-44ed-b972-16306546202b

1/1/0001 12:00:00 AM : Transfer Flour Validation is being called.

1/1/0001 12:00:00 AM : data (Mixture (20.0 deg C) of 100.00 kg of Flour) arrived at Transfer Flour's port.

1/1/0001 12:00:00 AM : data (Mixture (20.0 deg C) of 100.00 kg of Flour) arrived at Receive Flour's port.

1/1/0001 12:00:00 AM : Receive Flour execution is starting.

1/1/0001 12:00:00 AM : Receive Flour Validation is being called.

1/1/0001 12:10:00 AM : Transfer Flour execution is finishing.

1/1/0001 12:10:00 AM : Receive Flour execution is finishing.

 

 

Running transfer test with transfer operation delayed by 00:00:00,

                        and receive operation delayed by 02:00:00.

...destroying Synchronizer

...adding CoStart

1/1/0001 12:00:00 AM : Transfer Flour Remapping is being called.

                Creating Dangling Connector under key 2617314c-444b-4229-9295-39d7a5670c37

1/1/0001 12:00:00 AM : Transfer Flour execution is starting.

1/1/0001 12:00:00 AM : Transfer Flour Validation is being called.

1/1/0001 12:00:00 AM : data (Mixture (20.0 deg C) of 100.00 kg of Flour) arrived at Transfer Flour's port.

1/1/0001 12:00:00 AM : data (Mixture (20.0 deg C) of 100.00 kg of Flour) arrived at Receive Flour's port.

1/1/0001 12:10:00 AM : Transfer Flour execution is finishing.

1/1/0001 2:00:00 AM : Receive Flour Remapping is being called.

                Attaching to Dangling Connector under key 2617314c-444b-4229-9295-39d7a5670c37

1/1/0001 2:00:00 AM : Receive Flour execution is starting.

1/1/0001 2:00:00 AM : Receive Flour Validation is being called.

1/1/0001 2:10:00 AM : Receive Flour execution is finishing.

 

 

Running transfer test with transfer operation delayed by 02:00:00,

                        and receive operation delayed by 00:00:00.

...destroying Synchronizer

...adding CoStart

1/1/0001 2:00:00 AM : Transfer Flour Remapping is being called.

                Creating Dangling Connector under key bd137223-b010-444f-88e2-4f85cb18ae7a

1/1/0001 2:00:00 AM : Transfer Flour execution is starting.

1/1/0001 2:00:00 AM : Receive Flour Remapping is being called.

                Attaching to Dangling Connector under key bd137223-b010-444f-88e2-4f85cb18ae7a

1/1/0001 2:00:00 AM : Transfer Flour Validation is being called.

1/1/0001 2:00:00 AM : data (Mixture (45.0 deg C) of 100.00 kg of Flour) arrived at Transfer Flour's port.

1/1/0001 2:00:00 AM : data (Mixture (45.0 deg C) of 100.00 kg of Flour) arrived at Receive Flour's port.

1/1/0001 2:00:00 AM : Receive Flour execution is starting.

1/1/0001 2:00:00 AM : Receive Flour Validation is being called.

1/1/0001 2:10:00 AM : Transfer Flour execution is finishing.

1/1/0001 2:10:00 AM : Receive Flour execution is finishing.

Tests completed. Hit <Enter> to continue.


Possible Issues:

If it is the first time a model has run (no data left over in the SOMOperationDetails object), the sender has not begun to run, and the receiver runs, there will not be any transfer specs in the transfer-out operation, and the receive operation will not be able to discern that any materials are going to be transferred. If we can say that there will be no “empty transfers” (transfer operations that transfer no materials at all) then we can, in this case, assume that the sender has not yet been provisioned, and drop into the receiver’s normal “waiting-for-materials” sleep.